什么是组件
—————————————————————————————————————
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。
我们已经知道,可以通过以下方式创建一个 Vue 实例:
new Vue({
el: '#some-element',
// 选项
})
全局组件
要注册一个全局组件,可以使用 Vue.component(tagName, options)。例如:
// 注册
Vue.component("MyComponent",{
template:"<h1>我是全局注册的MyComponent组件,数据是{{ mymessage }}</h1> ",
//data需要用function,为了解决传址问题
data:function(){
return{
mymessage:"我是全局组件里的数据",
}
}
// 创建根实例
new Vue({
el:"#app",
})
组件在注册之后,便可以作为自定义元素 <my-component></my-component> 在一个实例的模板中使用。注意确保在初始化根实例之前注册组件:
<!--将下面定义的MyComponent在上面作为标签,并将驼峰式命名法改为小写加横线连接 -->
<div id="app">
<my-component></my-component>
</div>
局部组件
你不必把每个组件都注册到全局。你可以通过某个 Vue 实例/组件的实例选项 components 注册仅在其作用域中可用的组件:
var Child = {
template: '<div>我是局部组件</div>'
}
new Vue({
el:"#app",
components: {
// <my-component> 将只在父组件模板中可用
'my-component': Child
}
})
<div id="app">
<my-component></my-component>
</div>
组件引入方式
1.直接引入
<my-component></my-component>
2.通过is属性:好处是可以动态引人组件
<div :is="judge?'hello-world':'my-component'"></div>
keep-alive缓存标签
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染
<keep-alive>
<div :is="judge?'hello-world':'my-component'"></div>
</keep-alive>
Vue 开发调试模式
在终端输入以下命令,进入vue环境
cd vues
在进入vues文件夹后
1.首先安装依赖
vue init webpack vuetest
会生成vuetest文件夹
2.进入vuetest,运行vue
cd vuetset
npm run dev
3.运行完成后有服务器地址生成
1.png4.vue调试环境
在浏览器地址栏输入:http://localhost:8080
5.成功界面
2.png6.vuetest文件夹目录结构
image.png项目没有上线之前,东西都在src里面,src里面assets里面放的是图片,components里面是.vue组件文件,components里面的组件通过App.vue单入口引入
终端命令:输入以下打包
npm run build
项目上线打包之后会生成dist文件,上线的是dist文件
static在生成的时候会有一个默认的gitkeep文件,即使是空的,在github上传也不会过滤掉
7.第一个组件文件MyComponent.vue
<template>
<!--最外层只能有一个容器,必须有容器包裹-->
<!--scoped:作用域,style只在组件内部有效-->
<div>
<!--单文件组件-->
<div>我是div1</div>
<div>我是div2</div>
{{ message }}
</div>
</template>
<script>
export default {
name: "MyComponent",
data:function(){
return {
message:"我的信息111111"
}
}
}
</script>
<style scoped>
</style>
在App.vue单入口全局组件中引入,并注册
引入语句:MyComponent就是自己创建的文件名称
import MyComponent from '@/components/MyComponent'
注册语句:
在script中components里面写入MyComponent
<template>
<div id="app">
<!--组件可以是单标签,可以是双标签(可以里面写内容)-->
<HelloWorld/>
<MyComponent></MyComponent>
</div>
</template>
<script>
//引入
import HelloWorld from './components/HelloWorld'
import MyComponent from '@/components/MyComponent'
export default {
name: 'App',
components: {
HelloWorld,
MyComponent,
},
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行结果:
image.png
8.组件的传参(通过属性)prop
我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。
创建一个Person.vue文件
<template>
<div >
<!--通过属性传址-->
<p> 姓名:{{username}}</p>
<p> 肤色:{{color}}</p>
<p> 身高:{{height}}</p>
<button @click="showProps">点击我触发函数,查看Prop</button>
</div>
</template>
<script>
export default {
name: "person",
// 组件间的通信通过props来拿到数据
// props:['username','height','color'],
props:{
username:{type:String},
height:{type:Number},
color:String,
},
methods:{
showProps:function(){
console.log(this.username,this.height,this.color);
}
}
}
</script>
<style scoped>
</style>
在App.vue中引入,注册
<template>
<div id="app">
<!--通过属性传参-->
<!-- :属性名就是动态属性-->
<person
username="张三"
color="黄色"
:height="181"
></person>
<person
username="李四"
color="白色"
:height="183"
></person>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Person from '@/components/Person'
export default {
name: 'App',
components: {
HelloWorld,
Person,
},
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行结果:
image.png
9.插槽
默认插槽
它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。
新建Myslot.vue
<template>
<div>
<h1>我是slot组件</h1>
<!--当App.vue中的<my-slot>标签中没有内容时会默认显示以下内容-->
<slot>我是默认内容</slot>
</div>
</template>
<script>
export default {
name: "myslot"
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<my-slot></my-slot>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import MySlot from '@/components/MySlot'
export default {
name: 'App',
components: {
HelloWorld,
MySlot,
},
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行结果:
image.png
具名插槽
<slot> 元素可以用一个特殊的特性 name 来进一步配置如何分发内容。多个插槽可以有不同的名字。具名插槽将匹配内容片段中有对应 slot 特性的元素。
新建Myslot.vue
<template>
<div>
<h1>我是slot组件</h1>
<slot name="header"></slot>
<slot>我是默认内容</slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: "myslot"
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<my-slot>
<!--具名插槽-->
<p slot="header">我是头部</p>
<p slot="footer">我是底部</p>
<p>我是插槽内容</p>
</my-slot>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import MySlot from '@/components/MySlot'
export default {
name: 'App',
components: {
HelloWorld,
MySlot,
},
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行结果:
image.png
10.自定义事件 Emit(接收发送过来的事件和参数)
新建 Emit.vue
<template>
<div>
<h1>我是emit组件 发射,广播</h1>
<!--父级组件就是app.vue-->
<button @click="passDad">点击我的时候向父级传递事件,参数</button>
</div>
</template>
<script>
export default {
name: "emit",
data:function(){
return{
message:"我是测试下数据"
}
},
methods:{
passDad:function(){
// 传递事件
// 第一个参数是发射事件的名称
// 后面参数是要传递的数据
// 在App.vue的Emit方法参数接收 this.message
this.$emit("myfn",this.message);
}
}
}
</script>
<style scoped>
</style>
App.vue
<template>
<div id="app">
<!--接收发送过来的事件和参数-->
<Emit @myfn="fn"></Emit>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Emit from '@/components/Emit'
export default {
name: 'App',
components: {
HelloWorld,
Emit,
},
methods:{
fn:function(mydata){
console.log(mydata);
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
运行结果:点击button,控制台打印
image.png
11.过渡动画 transition(通过name在style里面给动画)
1.动态组件的过度
html:
<!--组件的动态切换:模式切换mode切换(默认 in-out)应该设置为 out-in-->
<transition name="fade" mode="out-in">
<div :is="switchC?'Component1':'Component2'"></div>
</transition>
<!--顺序不对,应该上一个先出去,下一个再进来-->
<button @click="switchC=!switchC">点击我切换组件</button>
js:
//引入两个组件,进行切换
import Component1 from './Component1'
import Component2 from './Component2'
<style scoped>
.fade-enter-active,.fade-leave-active{
transition:all 1s;
}
.fade-enter,.fade-leave-to{
opacity:0;
}
App.vue
<template>
<div id="app">
<!--过渡动画-->
<Transition></Transition>
</div>
</template>
<script>
import Transition from '@/components/Transition'
export default {
name: 'App',
components: {
Transition
},
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
2.v-if和v-else之间的过度;(
注意:如果v-if和v-else 的标签是一样的 例如 :
<p v-if="judge">我是if里的内容</p>
<p v-else>我是else里的内容</p>
<!--因为有缓存,没有改节点,直接改的内容,过度动画会失去作用:要给每一个加上一个唯一的key例如:-->
<p v-if="judge" key="1">我是if里的内容</p>
<p v-else key="2">我是else里的内容</p>
12.JavaScript 钩子
js过渡动画不需要给transition加上name属性,最好要加上跳过css检测的属性----v-bind:css="false"属性
<template>
<div>
<transition
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
:css="false"
>
<div class="mydiv" v-show="myjudge">我是div里的内容</div>
</transition>
<button class="mybtn" @click="myjudge=!myjudge">点击我切换</button>
</div>
</template>
<script>
//引入两个组件,进行切换
import Component1 from './Component1'
import Component2 from './Component2'
export default {
name: "",
data:function(){
return{
judge:true,
switchC:true,
myjudge:true
}
},
components:{
Component1,
Component2
},
methods:{
beforeEnter:function(el){
//el是transition标签里包裹的节点
// console.log(el);
$(el).css({left:"0px",opacity:0});
},
enter:function(el,done){
$(el).animate({left:"400px",opacity:1},done)
//done一下,转交给下一个事件钩子,不然后面不执行,可以直接当成回调
// done();
},
leave:function(el,done){
$(el).animate({left:"800px",opacity:0},done)
}
}
}
</script>
<style scoped>
.mydiv{
position:absolute;
left:400px;
}
.mybtn{
margin-top:30px;
}
</style>
App.vue同上,不变
过渡的类名(在style里面给,v就是name名)
image.pngvue.js官网:https://cn.vuejs.org/
我的博客链接
更多资源就在我的gitHub:https://github.com/huzixian2017/huzixian2017.github.io
网友评论