Vue.js组件间通信

前端这点事 62 0

父子通信

父对子:子组件用props接受父组件数据

子对父:$emit触发自定义事件通过参数传递数据

注意:在子组件尽量不能对父组件传进来的数据props进行修改(如下报错),需要修改的话一般用data深拷贝,或者computed返回给新属性,

1>.引用数据类型

如果父组件传递给子组件的是一个引用类型的数据,在子组件内部对数据源进行修改的时候,父组件会同步修改。

为了避免同步修改,需要对其进行深复制

props:['obj'],
data(){
   return {
     myObj: JSON.parse(JSON.stringify(this.obj))
   }
}

2>.自定义事件

引用数据类型会同步修改,但简单类型却不行。

所有的 prop 都使得其父子 prop 之间形成了一个 单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。(引用类型除外)

这时候便需要自定义事件。

父:
<div>
   <blog :title="title" @changeTitle="changeTitle"></blog>
</div>
data:{
   title:"hello"
},
methods:{
   // 接收
   changeTitle(t){
      this.title = t;
   }
}

子:
props:['title'],
data(){ return { myTitle:this.title }},
created(){
    // 5s 后 父子的title都变了
    setTimeout(()=>{
       this.myTitle = "my hello";
       this.$emit("changeTitle", this.myTitle);
    },5000)
}

引用类型中,如果只需要某些属性需要告知父组件,可同时采用 深复制和自定义事件

全局通信

new Vue() 作为eventBus:

app.js
Vue.prototype.$eventHub = new Vue();  // 
...
 
父:
<div>
   <blog :title="title"></blog>
</div>
data:{
   title:"hello"
},
created(){
   // this就是当前vue实例,它的原型链上有一个$eventHub,
   // 订阅事件
   this.$eventHub.$on("changeTitle",(e)=>{
      this.title = e;
   })
}
...
子:
props:['title'],
data(){ return { myTitle:this.title }},
created(){
    // 5s 后 父子的title都变了
    setTimeout(()=>{
       this.myTitle = "my hello";
       // $emit 发布
       this.$eventHub.$emit("changeTitle", this.myTitle);
    },5000)
}

.sync语法糖

只进行简单的数据双向控制,而不做其他操作,这里vue提供一个修饰符.sync

父:
<blog :title.sync="title"></blog>
子:
props:['title'],
created(){
   // 5s 后 父子的title都变了     setTimeout(()=>{
       this.myTitle = "my hello";
       // $emit 触发        bus.$emit("update:title", this.myTitle);
    },5000)
}

sync是一个语法糖,省略了在父组件监听update:xxx事件并读取参数的相关代码,因此子组件触发事件必须以update:开头才能双向绑定相关数据

 

slot作用域插槽

让插槽内容能够访问子组件中传过来的数据,原本的slot-scope已被废弃,最新用法如下

将要传输的内容在子组件中绑定在插槽上

<div>
  <slot :user="user"></slot>
</div>

父组件对应接收并使用,传过来的名称可自定义,default表示默认插槽

    <div id="app">
      <child>
        <template v-slot:default="slotData">
          {{ slotData.user.firstName }}
        </template>
      </child>
    </div>

作用域插槽不管可以传数据,也可以把子组件中的方法传给父组件使用

 

 

 

标签: Vue

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~