之前用vue完成了公司的新项目,遇到一些问题,也收获了很多。vue项目中涉及最多的就是组件间的通信。所及对vue组件间的通信做如下小结:
父子组件间的通信
子组件使用父组件的数据
子组件要显式地用props选项声明它期待获得的数据,声明props有两种形式:
1.数组形式
一般情况下,我们使用简单的数组形式即可
//子组件
Vue.component('person', {
props: ['name', 'age','sex'],
template:'<span>{{name}}</span><span>{{age}}</span><span>{{sex}}</span>'
})
//父组件
<person name="'Tom'" age="25" sex="M"></person>
//在实际开发中,我们往往需要动态的将数据传到子组件,那就要用v-bind或者缩写冒号
<person v-bind:name="userName" :age="userAge" :sex="userSex"></person>
2.对象形式
对象形式,与数组形式的不同是可以设置类型、默认值和自定义校验规则等
Vue.component('person', {
props: {
// 只检测类型
name: String,
// 检测类型 + 其他验证
age: {
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
}
}
})
父组件使用子组件的数据
起初单纯的以为props是双向绑定的,后面查看官方文档知道:
props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。另外,每次父组件更新时,子组件的所有 props 都会更新为最新值。
那么子组件要把数据传递回父组件怎么做呢?那就是自定义事件。
下面是官方的一个例子:
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
在子组件中使用$emit发出事件消息,在父组件中使用v-on接收
注:
1.如果你的属性是一个对象,那么它是双向绑定的,因为对象本身就是引用
2.官方说在2.3+版本可以使用.sync修饰符进行双向绑定
<person:name.sync="userName" :age.sync="userAge" :sex.sync="userSex"></person>
非父子组件间的通信
有些时候我们需要在非父子组件间传递数据,上述props的形式已经行不通了 ,那么我们需要使用到eventBus。
eventBus其实是引入一个新的vue实例,然后通过分别调用这个实例的事件触发和监听来实现通信和参数传递。
//bus.js
import Vue from 'vue';
export default new Vue();
//A组件发出消息,传递user参数
import bus from 'bus.js';
methods: {
chooseUser(user) {
bus.$emit('chooseUser',user);
}
}
//B组件接收消息,执行回调
import bus from 'bus.js';
created() {
bus.$on('chooseUser', function(user){
console.log(user);
});
}
//注:如果是单页应用,应当在组件销毁前移除事件监听器,防止路由切换时重复监听(这也是之前遇到的大坑)
beforeDestroy() {
bus.$off();
},
在中大型项目中,通信变得比较复杂,建议使用vuex,vuex涉及的知识比较多,这里就不作具体描述了。