组件
组件就是为了拆分Vue实例的代码量的,能够让我们以不同的组件来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。
组件化和模块化的不同
模块化:是从代码逻辑的角度进行划分的,方便代码分层开发,保证每个功能模块的职能单一;
组件化:是从UI界面的角度进行划分的,前端的组件化方便UI组件的重用。
全局组件
直接在script标签中定义,和new Vue平级,不需要再进行注册,可以直接在html标签中使用
//全局组件
Vue.component('todo-list',{
template:"<li>全局组件</li>"
这个地方也可以写成”#tem” 然后在vue实例#app的外面书写html代码<template id=’tem’></template>
})
<todo-list></todo-list>
局部组件
直接在script标签中定义,和new Vue平级,只是定义了一个变量,需要进行注册
//局部组件,定义完之后要在Vue中的components注册一下
var TodoItem = {
props:['content'],
template:'<li v-on:click="clickAler">{{content}}</li>'
methods:{
clickAler:function(e){
// alert(this.content);
this.$emit('delete',this.index);
//子组件向外发布一个delete事件,并携带数据this.index
}
}
}
new Vue({
el:'#root', //挂载点:el参数对应的dom标签
// template:'<h1>hello {{msg}}</h1>', //模板:挂载点内部的内容
// 如果一个vue实例没有template,那么它就会找挂载点,并把挂载点下面的DOM当做一个模板
components:{
'todo-item': TodoItem
},
data: { //vue实例里面的数据
msg:'hello ffff',
num:123,
list:['第一个','第二个','第三个'],
inputValue:'',
inputList:[]
},
methods:{
commit:function(){
this.inputList.push(this.inputValue);
this.inputValue = '';
}
}
})
<todo-item v-for='(item,index) in inputList'
v-bind:key='index' v-bind:content='item'
v-bind:index='index'
v-on:delete='deleteItem'
></todo-item>
组件名称使用了驼峰命名,则在引用组件的时候需要把大写的驼峰改为小写的字母,同时两个单词之间使用‘-’连接;如果不适用驼峰,则直接拿名称来使用。
组件中的data必须是一个function并return数据对象,这样才能保证这个组件在不同的地方使用的时候数据不会实现共享,每个组件之间的数据是独立的。
render渲染组件
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
render:function(createElements){
return createElements(login)
}
})
在这个vue实例中只能渲染login这个组件,其他标签不会显示。
也可以写成render:h=>h(login),将h作为createElements的别名,返回h(login)即为createElements(login)
组件切换
方式一:
if-else
方式二:
使用component标签
<a href="" @click.prevent="comName='login'"></a>
<a href="" @click.prevent="comName='register'"></a>
<component :is="comName"></component>
组件传值
在组件的使用时,可以给组件传值,首先给组件绑定一个变量content,里面存放的值对应的是inputList的item,然后在组件的定义中添加props:[‘content’],这样在组件的模板中就可以使用content传过来值了。
其实每一个vue组件就相当于一个vue实例,那么#root对应的vue实例也就是一个父组件,也就相当于在父组件中使用了子组件。如果一个vue实例没有template,那么就会去找它的挂载点,挂载点下面的所有DOM标签就是对应的模板,这样就解释了后面我们编程的时候,每个子组件我们都给一个文件存放,并且不写template标签。一个实例就对以一个组件。
父组件向子组件传值
父组件可以在引用子组件的时候通过属性绑定(****v-bind:****)的形式把需要传递给子组件的数据传递过去。
v-bind:content='item'
把inputList数组中的item作为一个属性content传递给todo-item这个子组件,在子组件的props属性中添加这个属性”content”,这样就可以在子组件中使用这个数据了。
方式一:使用props向子组件传值
(content是属性,item是父组件要传的数据,在子组件的props中用content接收这个数据)
父组件:
子组件:
在子组件中,data中的数据是可读可写的,props中的数据是只读的
父组件也可以向子组件传递方法,但是是用v-on:进行绑定的,v-on:func123=’parentFun’,在子组件中使用这个方法是用this.
父组件:
子组件:
子组件向父组件传值
通过发布订阅的方式
子组件首先发布一个事件delete并携带一个数据this.$emit(‘delete’,this.index),在父组件中订阅了这个delete事件,并用方法deleteItem来接受子组件传过来的事件返回,v-on:delete=’deteleItem’,这样在deleteItem方法的参数中便可以得到子组件传过来的this.index数据。
本质上是父组件定义了一个带参数的方法,并把这个方法传递给了子组件,当子组件调用这个方法的时候把自己的数据当做实参传入这个方法,父组件就相当于通过这个方法拿到了子组件的数据。
子组件:同样是childEvent事件,只不过子组件携带了参数
父组件:
和之前父组件向子组件不同的是,parentMethod有返回e,这个e就是子组件传过来的值
父组件可以通过this.refs获取子组件的方法、数据。