Vue 组件通信

2/13/2019 vue组件通信

# 1. props & $emit 父子相互传值(常用方法)

  • A、 props 父传子

主要传值,可以传方法,但不常用

语法:

父组件使用v-bind动态绑定数据 :自定义属性名="值"

子组件使用props 接收数据

props:["自定义属性名"]

或者

props:{
       "自定义属性名"{
       type:Array,
       default:默认值,
       required:是否必填
      }
  }

例子:

<!-- 父组件 -->
<template>
  <div class="father">
      <h2>props/$emit[传统的父子通信]</h2>
    <Son :data_Father="data_one" />  <!--第一步 父组件用 v-bind 向子组件发送数据 -->
  </div>
</template>
<script>
import Son from '../components/ZuJian/zujian/Son_one'
export default {

  name: "father",
  data() {
    return {
      data_one: "我是父组件的数据056"//父组件的数据
    }
  },
  components: {
    Son
  }
}
</script>
<!-- 子组件 -->
<template>
  <div class="son">
  <h2>我是子组件</h2>
  组件通信练习{{ data_Father }}</div>  <!-- 使用数据 -->

</template>
<script>
export default {
  name: "son",
  props: ['data_Father']//第二步,用 props ,接收数据
};
</script>
<style>
</style>

注意:

在父组件的属性名 data_Father 和子组件中用来接收的变量要保持一致!data_one在父组件一致即可,与子组件无关。 你不应该在子组件内部直接改变 prop,具体原因可以直接看官网介绍

  • B、$emit 子传父

可以传方法或值

语法:

子组件调用@emit()方法,这个方法接收两个参数

$emit("自定义事件名称"(必写),传递的值(可选))

父组件使用v-on 简写 @自定义事件名=""

例子:

<!-- 子组件 -->
<template>
  <div class="son">
    <h3>我是子组件组件--通信练习</h3>
    <button @click="SonClick">修改父组件数据</button>
    <!-- 子组件用 v-on 绑定一个用来修改父组件数据的函数(函数在父组件里) -->
  </div>
</template>
<script>
export default {
  name: "son",
  methods: {
    SonClick() {
      /*
      调用父组件提供的函数,从而实现父子通信
      $emit有两个参数 ,
      a 父组件提供的函数名(字符串的形式),
      b 新是数据(传递给父组件里用于修改数据的函数的参数)
      */
     this.$emit('handleSon', '子组件修改了数据')
      // handSon是父组件函数名
    }
  }
};

</script>
<style>
</style>
<!-- 父组件 -->
<template>
  <div class="father">
    <h3>props/$emit[传统的父子通信]</h3>
    <!-- 子组件Son用 v-on 绑定的函数修改父组件数据 一般情况下自定义函数名和值是一致的,防止混乱 本例中为了演示,不同-->
    <Son @handleSon="handleFather" />
    {{ data }}
  </div>
</template>
<script>
import Son from '../components/ZuJian/zujian/Son_one'
export default {
  name: "father",
  components: {
    Son
  },
  data() {
    return {
      data: '父组件的数据信息'
    }
  },
  methods: {
    // 声明一个让 子组件 来调用的方法
    handleFather(data_Son) {
      // 拿到了来自子组件传递过来的新的数据
      this.data = data_Son
      console.log(data_Son)
    }
  },
}
</script>

注意

父组件中的函数 handleFather 是子组件上的自定义属性的值;handleSon是让子组件通过$emit 修改数据的函数名,和父组件里子组件上是自定义属性名一致。

# 2. 父传子 $attrs & $listeners

跨组件通信 父传子

Vue_2.4 中新增的 $attrs/$listeners 可以进行跨级的组件通信。$attrs 包含了父级作用域中不作为 prop 的属性绑定(classstyle 除外)

# $attrs

attributes:属性的缩写;可以批量向下传递数据 / 只传属性 数据 $attrs 是组件(vue实例上)固有的用来描述该组件身上的所有属性集合的对象;如果继续向下传递,在中间组件中 v-bind = "$attrs"

  1. 顶级组件种定义值 并传递
   <Child :msg="msg" />
 data() {
    return {
      msg: "123",
    };
  },
  1. 子组件 继续传递
 <GrandChild :msg="msg"></GraChild>
  1. 最终组件 使用数据
  {{ $attrs.msg }}

# $listeners

批量向下传递方法 / 只传方法

$listeners 是组件上的属性,用来保存组件身上的方法;如果继续向下传递,使用 v-on="$listeners",

  1. 顶级组件 定义数据和方法
  //  顶级组件中将 msg(数据) changeMsgFn (方法) 传递下去
  <About :msg="msg" v-on:changeMsgFn="changeMsgFn" />
  // 向下传递的 数据
  data() {
    return {
      msg: "123",
    };
  },
  // 定义的修改父组件数据的方法, 等待 后代组件调用
  methods: {
    changeMsgFn() {
      this.msg = "abc";
    },
  },
  1. 子级组件
// 继续向下传递数据和方法
 <Child :msg="msg" v-on="$listeners"></Child>
  1. 最终子组件
  // 使用父组件 数据
  {{ $attrs.msg }}
  // 调用父组件的方法
  <button @click="$listeners.changeMsgFn">孙组件的按钮</button>

# 3. 子修改父 通过 props 传方法

子组件通过传递的方法 修改父组件

  1. 父组件
        // 将数据和方法都传递给子组件
    <About :msg="msg" :changeMsgFn="changeMassage" />
<script>

import About from "./components/About.vue";
export default {
    name: "app",
    data() {
      return {
        msg: "123",
      };
    },
// 定义一个修改父组件数据的方法  一会子组件会调用该方法
    methods: {
      changeMassage() {
        this.msg = "abc";
      },
    },
  }
  </script>
  1. 子组件

接受数据和方法

props: ["msg", "changeMsgFn"],

绑定子组件上的事件,调用父组件的方法,达到修改父组件数据的目的

 {{ msg }}
    <button @click="changeMsgFn">about子组件按钮</button>

# 3. 父传子 provide / inject

只能父传子数据 父子跨级通信时

  • 父组件 注入
  provide: {
    message: "123",
  },
  • 子组件 接收
  inject: ["message"],

使用

{{message}}

# 4. $refs 父访问子

父访问子

  1. 父组件使用ref绑定子组件,通过$refs 获取子组件实例,使用子组件的数据和方法
    <About ref="childref" />
    <button @click="doSome"></button>

  methods: {
    doSome() {
      console.log(this.$refs.childref.childdata);
    },
  }
  1. 子组件的数据
  data() {
    return {
      childdata: "childdata",
    };
  },

# 5. eventBus 中央事件池(同级通信)

父子之间 / 同级通信

# 父子间

  1. 定义一个中央事件池 eventBus.js
import Vue from 'vue'

const eventBus = new Vue()

export default eventBus
  1. 需要发送数据的地方 引入eventBus.js文件 添加事件和数据
import eventBus from "./eventBus";
 data(){
   return {
     title:""
   }
 }
 methods: {
    add() {
      // 发送方法
      eventBus.$emit("addItem", this.title);
    },
  },
  1. 在要使用数据的地方引入,并监听数据
import eventBus from "./eventBus";

    // 调用事件发送 使用数据
    methods: {
      handleAddTitle(title) {
        console.log(title);
      },
    },
  mounted() {
    // 监听事件名, 调用事件方法
    eventBus.$on("addItem", this.handleAddTitle);
  },
  // 销毁添加的事件 防止内存泄漏
  beforeDestroy() {
    eventBus.$off("addItem", this.handleAddTitle);
  },

#

  • 绑定到vue原型上
// main.js
Vue.prototype.$bus = new Vue()
// 绑定   created() {} 中
this.$bus.$emit('dowloadCurrent', this.tableDatas, formHead)
// 使用   created() {} 中
this.$bus.$off('dowloadCurrent').$on('dowloadCurrent', (tableDatas, formHead) => {
      //  ······
    })

# 同级之间

  1. 父组件中引入子组件
  // 引入子组件 并传递给子组件
    <Child1 :msg="msg" />
    <Child2 :msg="msg" />
  import Child1 from "./components/Child1.vue";
  import Child2 from "./components/Child2.vue";

  //  定义的数据
  data() {
    return {
      msg: "123",
    };

  1. 子组件一
    //Child1
    // 使用数据
    {{ myMsg }}
    // 修改数据 调用
    <button @click="changeone">chlid1 修改</button>
    //引入eventBus
    import eventBus from "./eventBus";

  // 将接收的方法赋值到本组件上
  data() {
    return {
      myMsg: this.msg,
    };
  },
  // 接收的数据
  props: ["msg"],
  // 修改用的方法
  methods: {
    changeone() {
      const a = "abc";
      this.myMsg = a;
      console.log(this.myMsg);
      // 向eventBus 中央事件池中添加自定义事件 并带参
      eventBus.$emit("changeone", a);
    },
  },
};

子组件二

    //child2
    //使用数据
    {{ myMsg }}

  // 引入eventBus
  import eventBus from "./eventBus";
export default {
  // 将数据赋值到本组件
  data() {
    return {
      myMsg: this.msg,
    };
  },
  // 接收父组件数据
  props: ["msg"],
  // 在create钩子中监听自定义事件
  created() {
    // 接收参数并修改
    eventBus.$on("changeone", (item) => {
      this.myMsg = item;
    });
  },

* 不使用父组件的数据,只从当前兄弟组件中传递给另一个组件数据也是可以的。

# 6. 同级之间通过父组件修改(比较 low )

  • 顶级组件
    // 父组件中的两个子组件
    <Child1 :msg="msg" @changeone="changeone" />
    <Child2 :msg="msg" />
  // 父组件中的数据
  data() {
    return {
      msg: "123",
    };
  },
  // 父组件中的修改数据的方法
  methods: {
    changeone(item) {
      this.msg = item;
    },
  },
  • 子级组件

兄弟组件一

  // 使用数据
  {{ msg }}
  // 调用 发送方法
  <button @click="changeone">chlid1 修改</button>
  //  接收数据
  <script>
  props: ["msg"],

  methods: {
    // 发送方法和数据
    changeone() {
      this.$emit("changeone", "abc");
    },
  },
  </script>

兄弟组件二

  // 使用数据
  {{msg}}
  // 接收数据
  props: ["msg"],

# 7. vuex 父子/同级 通信

vuex仓库文件store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    msg: "123"
  },
  mutations: {
    changeone(state, item) {
      state.msg = item
    }
  },
  actions: {
    changeone(content, item) {
      content.commit("changeone", item)
    }
  },
  modules: {
  }
})

子组件一

  // 使用仓库中的数据
  {{ $store.state.msg }}

  <button @click="changeone">chlid1 修改</button>

  methods: {
    changeone() {
      const a = "abc";
      this.$store.dispatch("changeone", a);
    },
  },

子组件二

 {{ $store.state.msg }}
最后提交: 2/13/2023, 11:11:57 AM