vue中的组件间通信

108 阅读1分钟

一.父给子数据通信

a.使用props

父组件:父组件用绑定语法将自己的变量绑定给子组件定义的公开属性

<ul class="todo-list">
      <todo-item v-for="(item, i) of tasks" :key="i" :i="i" @del="del">
         <!-- 将i通过绑定语法给子组件添加了i变量-->
        <template v-slot:task>{{ item }}</template>
      </todo-item>
    </ul>

子组件:子组件用props定义公开的属性用于接收父组件的变量值

export default {
  props:["i"],
    //子组件使用props接收i变量
  methods:{
    del(){
      this.$emit("del",this.i)
    }    
  }
}

b.使用插槽访问(适用于简单的数据展示,数据不需要进行复杂的操作)

父组件:插槽中的的内容取决于父组件如何使用,比如可以使用插值语法将父组件中的变量传递给子组件

 <template v-slot:task>{{ item }}</template>
  <!-- 使用插槽定义显示内容-->

子组件:子组件定义插槽,使用v-slot的参数形式提供其名称

<slot name="task"></slot>
<!-- 子组件定义插槽-->

二.子给父数据通信

分为两步

1.父组件:在引用的子组件上添加一个自定义事件,监听自定义事件的发生,绑定父组件中的一个处理函数

 <todo-item v-for="(item, i) of tasks" :key="i" :i="i" @del="del">
     <!-- 父组件添加del自定义事件-->
        <template v-slot:task>{{ item }}</template>
      </todo-item>
methods:{
del(i) {//父组件的处理函数中执行i的操作
      console.log("执行删除操作");
      this.tasks.splice(i, 1);
    },
}

2.子组件通过$emit(“父亲的自定义事件名称”,参数值)触发事件父组件的自定义事件,传递数据给监听器

<button @click="del">x</button></li>
<!--子组件中触发事件-->
export default {
  methods:{
    del(){
      this.$emit("del",this.i)
        //子组件中使用$emit()传参给父组件的del函数
    }    
  }
}

三.兄弟间数据通信

分三步:
1.兄弟间通信需要一个桥梁,定义一个空的vue实例bus保存事件,关联到数据接收方的处理函数上,导入到原来vue的原型对象中,使得bus可以被每个vue的实例使用
2.数据发送方:数据发送方的事件处理函数中,使用this.bus.$emit()触发公共的bus对象保存的事件,并传参
input type="text" v-model="task"><button @click="add">+</button>
//数据发送方,使用$emit()向bus对象上保存的事件传参
methods:{
    add(){ 
      this.bus.$emit("add_task",this.task)
      this.task="";
    }
  }
3.数据接收方:在数据加载完成后,向公共的bus对象添加一个自定义的事件,关联到自己的一个处理函数
//数据的接收方,在回调函数中执行操作
created() {   
    this.bus.$on("add_task",(task)=>{
         this.tasks.push(task)
     });
    //上面一句话等同
    //this.bus.$on("add_task", this.add.bind(this));
  },
  methods: {
    add(task) {
      this.tasks.push(task);
    }
  },

四.refref与parent打通父子间相互通信

1.ref被用来给元素或者子组件注册引用信息,引用信息将会注册到父组件的$ref对象上,
2.如果是普通的DOM元素,那么就指向这个DOM元素,
<input type="text" v-model="task" ref="input" /><button @click="add">+</button>
<!--input是普通的dom元素-->
mounted() {
    this.$refs.input.focus();
   //所以此时指向的是当前页面的标记的input元素
  },

使用方法如下:

父组件:
 <todo-add ref="todoAdd"></todo-add>
父组件访问子组件:this.$ref.子组件别名.子数据/方法名
    methods:{
    add(){
      this.tasks.push(this.$refs.todoAdd.task)
        //访问子组件的task数据
    },
    del(i){
    console.log("删除元素")
     this.tasks.splice(i,1)
   }
子组件访问父组件:this.$parent.子数据/方法名
methods:{
   del(){
   //子组件的子组件,使用$parent.$parent访问向上两层的父组件的方法
     this.$parent.$parent.del(this.i);
   }
 }