Vue实践--父子组件间的通信(未完待续)

来源:互联网 发布:淘宝黑名单在哪里设置 编辑:程序博客网 时间:2024/05/21 20:26

父子组件间的通信(在这里父组件就是你自定义的标签,子组件就是父组件template里面的内容),父组件通过props选项向子组件传递参数或数据,子组件接收到参数后根据参数的不同来执行不同的操作。也就是说,在组件中使用props选项来声明需要从父组件接受的数据(通俗点说就是,组件在注册的时候通过props选项声明子组件(template所指)需要从父组件中接受的数据),props选项的值可以是字符串数组或者对象

值是字符串数组:

HTML部分:

<!-- (例1):父子通过props传递 --><my-component :message="msg" array="[1,2,3,4]"></my-component>
JS部分:

Vue.component("my-component",{props:["message","array"],// 子组件template:"<div >{{message}}<div @click='changeVal'>{{message}}</div></div>",})
注意:
  1.如果你直接在父组件上自定义属性并且传递数字,布尔值,数组,对象,而不是使用v-bind在父组件上绑定属性,传递的仅仅是字符串。如下面的例子:

HTML部分:

<my-component array="[1,2,3,4]"></my-component><!-- 9 --><my-component :array="dataArray"></my-component><!-- 4 -->
JS部分:

Vue.component("my-component",{props:["message","array"],// 子组件template:"<div >{{message}}<div @click='changeVal'>{{message}}</div></div>",data:function(){return {tips:"我来自data选项"}}})var myApp = new Vue({el:"#container",data:{msg:"来自父组件上的数据",dataArray:[1,2,3,4],initMsg:"初始化数据"}})

 2.同一个组件在复用的时候是相互独立的

通过上例我们可以发现,无论是组件中data函数的返回值还是从父组件中传递过来的数据,子组件都能操作,那么他们之间有何区别呢
我个人感觉主要是作用域:props声明的数据可能来自于Vue实例中的data选项,而data函数返回值,其作用域仅仅在于组件内部,是自己的私有数据。因此可以在data函数中将props数据作为返回值保存起来,这样以后你就可以随意操纵数据了,也就避免了直接操纵父组件数据,从而影响父组件。
其实在Vue2.x中,通过props传递数据是单向的,也就是说,当父组件数据的变化会引起子组件数据的变化,但是反之不行,这也意味着,其实在子组件中无论你怎么操作从props传递过来的数据,父组件的状态都不会改变

为了验证这个想法,看下面的例子

HTML部分:

<div class="model"><our-component :mero="initMsg"></our-component><input type="text" name="test" v-model = "initMsg"><span>{{initMsg}}</span></div>
JS部分:

Vue.component("our-component",{props:["mero"],template:"<div @click='changeMSG'>{{mero}}</div>",methods:{changeMSG:function(){alert(1)//this表示当前的组件our-component(可以视组件的地位和Vue实例的地位差不多)this.mero = "我被改变啦!"}}})var myApp = new Vue({el:"#container",data:{msg:"来自父组件上的数据",dataArray:[1,2,3,4],initMsg:"初始化数据"}})

结果:

初始化的时候是这样的:


当触发点击事件的时候,变成了这样:


可以看到,span元素内的值一直都没有变化,也就说明实例中的initMsg没有发生改变,由于v-bind是双向绑定的,所以父组件中对应的属性没有发生改变(虽然我们看不到),但即使是这样也要注意:为了安全起见,从父组件中传递过来的数据,要在组件的data选项中将其保存起来,或者利用计算属性


说完了父组件向子组件传递数据,那么子组件要向父组件传递数据该怎么办?其实子组件向父组件通信通过$emit()实现;

大意为子组件使用了一个事件,比如click然后产生了一个效果(组件中methods选项中的函数做的事),然后将这样的效果命名放入父组件(this.$emit(自定义事件名,[参数1]),[参数2]……),注意事件名要小写字母,不要用驼峰命名法)中,当做一个事件来触发,每当这样的效果发生一次时,这样父组件的事件也被触发了(v-on给父组件绑定以上自定义事件),即可以产生另一种效果(一般操作的是Vue实例中的数据,随意操作,可以传参参数子组件中的数据,也可以不传),这样可以加强这两个效果的紧密联系,并且这样有趣又好用的方式也可以用在自己想要的地方。这样当绑定在子组件上的事件触发的时候,父组件上的事件也会触发并执行一系列方法。

例如:

HTML部分

<div id="container" v-cloak><p>当前的值是:<span>{{total}}</span></p><!-- 给父组件绑定自定义事件 --><my-component @increasefunc="changeTotal"
@decreasefunc="changeTotal"
></my-component></div>
JS部分:

// 自定义组件;Vue.component("my-component",{template:"\<div>\<button @click='increaseTotal'>add</button>\<button @click='decreaseTotal'>reduce</button>\</div>",data:function(){return{counter:0}},methods:{increaseTotal:function(){this.counter++;console.log(this.counter)// 同下this.$emit("increasefunc",this.counter);},decreaseTotal:function(){this.counter--;console.log(this.counter);// 定义自定义事件名,第一个参数是事件名,第二个参数及以后是要传递的数据// 也可以不传递参数,事件名自定义this.$emit("decreasefunc",this.counter)}}})var myApp = new Vue({el:"#container",data:{total:0},methods:{changeTotal:function(total){// 形参total用来保存从子组件传递过来的数据的,也可以不传参,this.total++;}}})
以上当点击绑定在子组件上的click事件的时候,就会通过this.$emit()方法“告诉”父组件:子组件点击了(事件被触发了),那么此时绑定在父组件上的对应的自定义事件也会触发,并执行相应的函数changeTotal函数,实现了子组件和父组件事件的单向紧耦合





 
原创粉丝点击