子组件与父组件通讯,我们可以利用$emit触发这个自定义事件,然后调用子组件的父组件中接受这个时间和传递过来的参数做下一步的处理,比如下面的方法:
子组件:this.$emit('自定义属性', foo)
父组件:<z-select @自定义属性='方法'/>
方法会收到foo这个子组件传递过来的值。如果是一个复杂的实现需要传递多个值,或者需要对值进行进一步更复杂的处理的时候这样非常合适,如果仅仅是绑定某一个属性的值,对于这样的写法,需要同时在父组件和子组件中写控制的逻辑,就耦合的比较深入了,这时候我们就非常留恋Vue在原生组件上v-model双向数据绑定那种简洁的写法。那么如何在子组件上实现如原生组件一样的v-model呢?本篇讨论一下这个解决方案。
简略总结一下:
第一步:父组件中给子组件v-model一个自己的foo属性
第二步:子组件用一个model属性来接收这个foo属性的值;
第三步:子组件需要model中定义一个自己属性(这里使用pfoo)来存放父组件传递过来的foo值,并指定反馈父组件数值变化的自定义函数(这里使用event1)
第四步:子组件开始使用自己内部的input等v-model改变自己的属性值(pfoo),或者直接用函数改变属性值
第五步:子组件以某一个用户的操作触发改变,调用某一个函数来触发自定义事件(event1),使用$emit传递数值给父组件v-model属性。完成同步。
看起来好像有些复杂,但是我们用代码来说明一下就非常简单了。为方便,这里我使用httpVueLoader来加载vue组件,方便后端小伙伴们直接开工。
1.我们先来定义父组件环境
<!--引入必要的js库-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/http-vue-loader@1.4.1/src/httpVueLoader.js"></script>
<!--定义vue-->
<div id="app">
{{foo}}
<zizujian v-model="foo" :rows="rows"></zizujian>
</div>
<script>
var Vue = window.Vue;
// 注册组件
Vue.use(httpVueLoader);
var rows = ["1","2","3","4"]
new Vue({
el: "#app",
//用httpVueLoader挂载vue子组件
components: {
'zizujian': 'url:zi.vue',
},
data:function(){
return{
rows:rows,
foo:"abc"
}
}
});
</script>
2.接下来我们写一个子组件来接收父组件绑定的v-model值.
<template>
<div>
<!--这里循环输出从父组件接收过来的数据-->
<li v-for="row in rows">{{row}}</li>
<!--定义一个原生的input来尝试改变一下pfoo的值,同时抓取input事件作为触发回送v-model值的事件,这里用doChange函数接住这个事件-->
<input v-model="pfoo" type="text" @input="doChange">
</div>
</template>
<script>
module.exports = {
//定义model接住父组件的v-model的值
model: {
prop: "pfoo",//指定自己的pfoo属性接受数值
event: "event1"//指定自己的event1事件回送数据给父组件
},
props: {
rows: {
type: Array,
default: []
},
//根据自己model的要求定义pfoo属性
pfoo: { type: String, default: "" }
},
methods:{
//接住@input的事件触发,同时回传数据给父组件,这里回传的是pfoo,也就是当时用于接受父组件值的属性,你也可以回传任意
doChange(val){
console.log(val)
console.log(this.pfoo);
this.$emit('event1',this.pfoo);
},
}
};
</script>
网友评论