1、概念:
组件是vuejs最核心的功能,主要是为了复用和相互传值。分为父传子,子传父、父子双向绑定、非父子关系值传递。
2、父传子:
例子:
<div id="app">
<button @click="add"></button>
<my-component :input-text="total"></my-component>
</div>
Vue.component('my-component',{
props:['inputText'],
template:'\
<div>\
<input :value="inputText">\
</div>\
'
});
var app=new Vue({
el:"#app",
data:{
total:0
},
methods:{
add:function () {
this.total++;
}
}
});
理解:
父组件传递值给子组件,在子组件的自定义标签v-bind绑定自定义属性值,在子组件用props接收
(注意点,props需要使用驼峰命名法才行)
3、子传父:
例子:
<div id="app">
<input :value="total">
<my-component @add="handler" @remove="handler"></my-component>
</div>
Vue.component('my-component',{
template:'\
<div>\
<button @click="add">+1</button>\
<button @click="remove">-1</button>\
</div> \
',
data:function(){
return{
sum:0
}
},
methods:{
add:function () {
this.sum++;
this.$emit('add',this.sum);
},
remove:function () {
this.sum--;
this.$emit('remove',this.sum);
}
}
});
var app=new Vue({
el:"#app",
data:{
total:0
},
methods: {
handler:function (total) {
this.total=total;
}
}
});
理解:
子传父需要通过自定义监听事件v-on和$emit触发事件配合来实现,比如上面的例子:
(1)、在父组件的中自定义监听事件@add="handler"(当自定义监听事件add被触发之后,handler方法就会执行)。
(2)、在子组件中this.$emit('add',this.sum);(触发add事件,并返回子组件的数据)
(3)、handler方法里面将子组件返回的值赋值给父组件的变量
从而完成了子传父
4、子传父(v-model绑定语法糖方式):
例子:
<div id="app">
<input :value="total"/>
<my-component v-model="total"></my-component>
</div>
Vue.component('my-component',{
template:'\
<div>\
<button @click="add">+1</button>\
<button @click="del">-1</button>\
</div>\
',
data:function () {
return{
temTotal:0
}
},
methods:{
add:function () {
this.temTotal++;
this.$emit('input',this.temTotal);
},
del:function () {
this.temTotal--;
this.$emit('input',this.temTotal);
}
}
});
var app=new Vue({
el:"#app",
data:{
total:0
}
});
理解:
子传父还可以通过v-model绑定的方式和 this.$emit('input',this.temTotal)配合来实现(其实是一种语法糖),比如上面的例子:
(1)、在父组件的中通过v-model绑定实例变量total
(2)、在子组件中 this.$emit('input',this.temTotal);(触发input事件,并返回子组件的数据)
(3)、注意:这一步是通过语法糖自动执行了的,就是v-on:input绑定了一个方法,这个方法将子组件返回的值赋值给父组件的变量
(就是v-model绑定的变量)
从而完成了子传父
5、父子相传:
例子:
<div id="app">
<p>{{total}}</p>
<button @click="add">添加</button>
<my-component v-model="total"></my-component>
</div>
Vue.component('my-component',{
props:['value'],
template:'\
<div>\
<input :value="value" @input="updateValue"/>\
</div>\
',
methods: {
updateValue:function (event) {
this.$emit('input',event.target.value);
}
}
});
var app=new Vue({
el:"#app",
data:{
total:0
},
methods:{
add:function () {
this.total++;
}
}
});
理解:
父子相传可以通过v-model绑定的方式和 this.$emit('input',this.temTotal)配合来实现(其实是一种语法糖),比如上面的例子:
(1)、在父组件的中通过v-model绑定实例变量total
(2)、在子组件中,设置props['value']来接收父组件传来的值
(2)、在子组件中 this.$emit('input',event.target.value);(触发input事件,并返回子组件的数据)
(3)、注意:这一步是通过语法糖自动执行了的,就是v-on:input绑定了一个方法,这个方法将子组件返回的值赋值给父组件的变量
(就是v-model绑定的变量)
从而完成了父子相传,注意点就是,通过v-model绑定,传到子组件的值要用固定的value来接收
6、非父子相传:
例子:
<div id="app2">
<my-component></my-component>
var bus=new Vue();
Vue.component('my-component',{
template:'\
<div>\
<input v-model="total">\
<button @click="send">发送</button>\
</div>\
',
data:function(){
return{
total:0
}
},
methods:{
send:function () {
bus.$emit('on-meagges',this.total);
}
}
});
var app2=new Vue({
el:"#app2"
});
var app=new Vue({
el:"#app",
data:{
meassges:""
},
mounted:function () {
var _this=this;
bus.$on('on-meagges',function (msg) {
_this.meassges=msg
});
}
});
理解:
非父子相传可以通过设置一个中介vue实例来完成,比如上面的例子:
(1)、在app实例的钩子函数,在挂载的时候中介实例bus通过$on方法注册监听事件on-meagges
,声明监听事件方法,将返回值赋值给app实例的变量meassges
(2)、在子组件中,设置bus.$emit('on-meagges',this.total);触发中介实例bus的on-meagges事件,返回my-component组件的变量值
从而完成了非父子相传,其实就是在目标组件里面给中介组件bus注册自定义监听事件,在发送数据的组件里面触发bus的监听事件。
7、父链:
在子组件中使用this.$parent可以直接访问该组件的父组件,父组件也可以用this.$children访问子组件,
尽管可以这样,但是最好不要使用这种操作。子组件应该尽可能的避免依赖父组件的数据,更不应该主动去修改它,
因为这样会使得父子组合紧密耦合,违反了vue组件的设计原则。
8、子组件索引
通过this.$children来遍历出特定的组件是比较难的,因为组件动态渲染时在,
序列不固定,这时候可以给子组件指定一个索引ref="",
然后就可以通过this.$refs.索引名来访问子组件了,
$refs在组件渲染完成后填充,并且不是响应式的,仅仅作为一个直接访问子组件的应急方案,应该尽量避免使用$refs
9、我的总结:
父子组件传值:props接收父组件的值,通过自定义事件监听和this.$emit触发监听事件配合,
来传递子组件的值给父组件,可以通过v-model语法糖的方式来做(v-model双向绑定后,
自动将子组件的值赋值给v-model绑定的变量,并且不需要自定义属性来传递父组件的数据,
在子组件中props默认为value就是父组件传递过来的v-model值)
非父子组件的传值就依靠中间实例来完成,在目标组件声明自定义事件方法,在发送数据的组件this.$emit触发事件。