• vue中组件通信的方式


    目录

    props

    $emit

    ref和$ref实现父子组件之间的通信

    全局事件总线bus

    创建一个事件总线bus

    组件间传值(这里用于兄弟组件传值)

    依赖注入(provide/inject)

    $parent/$children

    vuex通信

    插槽slot

    匿名插槽(默认插槽)

    具名插槽

    作用域插槽


    props

    props只能用于父组件向子组件传递数据,子组件通过props获得父组件传递过来的数据,子组件的数据会随着父组件的更新而响应式更新。

    1. <template>
    2.   <div class="father">
    3.     <span>我是父组件span>
    4.     <Children :msg="name">Children>
    5.   div>
    6. template>
    7. <script>
    8. import Children from "./Children.vue";
    9. export default {
    10.   components: {
    11.     Children,
    12.   },
    13.   data() {
    14.     return {
    15.       name: "张三",
    16.     };
    17.   },
    18. };
    19. script>
    1. <template>
    2.   <div class="child">我是子组件,父组件传递过来的数据是:{{ msg }}div>
    3. template>
    4. <script>
    5. export default {
    6.   props: {
    7.     msg: String,
    8.   },
    9.   data() {
    10.     return {};
    11.   },
    12. };
    13. script>

    实现结果为:   

    $emit

    适用任意组件通信,通常用于子组件向父组件传递数据。$emit 绑定一个自定义事件,当这个事件被执行的时候就会将参数传递给父组件,而父组件通过v-on监听并接收参数(v-on可以缩写成@)。

    1. <template>
    2.   <div class="father">
    3.     <Children :list="list" @onEmitIndex="onEmitIndex">Children>
    4.     <p>子组件传递过来的index数据为:{{ index }}p>
    5.   div>
    6. template>
    7. <script>
    8. import Children from "./Children.vue";
    9. export default {
    10.   components: {
    11.     Children,
    12.   },
    13.   data() {
    14.     return {
    15.       index: -1,
    16.       list: ["第一", "第二", "第三"],
    17.     };
    18.   },
    19.   methods: {
    20.     onEmitIndex(id) {
    21.       this.index = id;
    22.     },
    23.   },
    24. };
    25. script>
    1. <template>
    2.   <div>
    3.     <div v-for="(item, index) in list" :key="index" @click="emitIndex(index)">
    4.       {{ item }}
    5.     div>
    6.   div>
    7. template>
    8. <script>
    9. export default {
    10.   props: ["list"], //子组件先获取父组件chuan'gu
    11.   data() {
    12.     return {};
    13.   },
    14.   methods: {
    15.     emitIndex(index) {
    16.       this.$emit("onEmitIndex", index); //触发父组件方法onEmitIndex,传递参数index
    17.     },
    18.   },
    19. };
    20. script>

    实现结果: 

    ref和$ref实现父子组件之间的通信

    在父组件中使用ref注册要引用的子组件信息,再使用$ref获取所有注册的引用信息。

    1. <template>
    2.   <Children ref="child">Children>
    3. template>
    4. <script>
    5. import Children from "./Children.vue";
    6. export default {
    7.   components: { Children },
    8.   mounted() {
    9.     console.log(this.$refs.child.name); //获取子组件中的数据name
    10.     this.$refs.child.sayHello(); //获取子组件中的方法
    11.   },
    12. };
    13. script>
    1. <template>
    2.   <div>div>
    3. template>
    4. <script>
    5. export default {
    6.   data() {
    7.     return {
    8.       name: "JavaScript",
    9.     };
    10.   },
    11.   methods: {
    12.     sayHello() {
    13.       console.log("hello");
    14.     },
    15.   },
    16. };
    17. script>

    全局事件总线bus

    适用于任意组件之间的通信,在vue中类似桥梁,是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所有组件都可以通知其他组件。使用$emit发布事件,$on订阅事件。

    在用这个传值方法时有一个问题,尤其是在父子组件之间用的时候,从一个组件中使用$emit触发事件之后,另一个组件的监听事件$on不生效,所以在使用bus传值时,$on一定要在$emit事件触发之前创建,否则在触发$emit事件时,$on是监听不到的(因为这个时候$on压根就没有创建) 。

    创建一个事件总线bus

    1. import Vue from "vue";
    2. export default new Vue();

    组件间传值(这里用于兄弟组件传值)

    1. <template>
    2.   <div>
    3.     <Children1>Children1>
    4.     <Children2>Children2>
    5.   div>
    6. template>
    7. <script>
    8. import Children1 from "./Children1.vue";
    9. import Children2 from "./Children2.vue";
    10. export default {
    11.   components: { Children1, Children2 },
    12. };
    13. script>
    1. <template>
    2.   <div>
    3.     <button @click="add">将子组件1中的num发送给子组件2button>
    4.   div>
    5. template>
    6. <script>
    7. import bus from "../bus/bus.js"; //引入事件总线
    8. export default {
    9.   data() {
    10.     return {
    11.       num: 0,
    12.     };
    13.   },
    14.   methods: {
    15.     add() {
    16.       bus.$emit("addition", {
    17.         num: this.num++,
    18.       });
    19.     },
    20.   },
    21. };
    22. script>
    1. <template>
    2.   <div>求和:{{ count }}div>
    3. template>
    4. <script>
    5. import bus from "../bus/bus.js"; //引入事件总线
    6. export default {
    7.   data() {
    8.     return {
    9.       count: 0,
    10.     };
    11.   },
    12.   mounted() {
    13.     bus.$on("addition", (param) => {
    14.       this.count = this.count + param.num;
    15.     });
    16.   },
    17. };
    18. script>

    实现结果:

    依赖注入(provide/inject)

    用于父子、祖孙组件之间的通信,适用于层数很深情况下的传值。provide和inject是vue的两个钩子,provide用来发送事件,inject用来接收事件。

    假设A组件中引入B组件(A为B的父组件),B组件中引入C组件(B为C的父组件,A为C的爷爷组件),则A,C通过provide/inject通信。

    1. <template>
    2.   <div>
    3.     <C>C>
    4.   div>
    5. template>
    6. <script>
    7. import C from "./C.vue";
    8. export default {
    9.   components: { C },
    10.   provide() {
    11.     return {
    12.       name: "哈利波特",
    13.     };
    14.   },
    15. };
    16. script>
    1. <template>
    2.   <div>{{ name }}div>
    3. template>
    4. <script>
    5. export default {
    6.   inject: ["name"],
    7. };
    8. script>

    输出为: 

    $parent/$children

    使用$parent可以访问上一级父组件;使用$children可以访问子组件,获得的是数组,不能保证所访问的子组件顺序,数据不是响应式。

    1. <template>
    2.   <div class="hello_world">
    3.     <div>Father组件中的值为:{{ msg }}div>
    4.     <Children>Children>
    5.     <button @click="change">点击改变子组件值button>
    6.   div>
    7. template>
    8. <script>
    9. import Children from "./Children.vue";
    10. export default {
    11.   components: { Children },
    12.   data() {
    13.     return {
    14.       msg: "Welcome",
    15.     };
    16.   },
    17.   methods: {
    18.     change() {
    19.       this.$children[0].message = "JavaScript"; //获取到第一层子组件
    20.     },
    21.   },
    22. };
    23. script>
    1. <template>
    2.   <div>
    3.     <span>Children组件值为(点击后改变):{{ message }}span>
    4.     <p>获取父组件的msg为: {{ parentVal }}p>
    5.   div>
    6. template>
    7. <script>
    8. export default {
    9.   data() {
    10.     return {
    11.       message: "Vue",
    12.     };
    13.   },
    14.   computed: {
    15.     parentVal() {
    16.       return this.$parent.msg;
    17.     },
    18.   },
    19. };
    20. script>

    实现结果: 

    vuex通信

    适用任意组件间的通信,主要实现多个组件共享数据,是进行数据状态管理的一个插件。

    创建文件:src/store/index.js(创建vue项目时选择vuex会自动生成并配置此文件)

    如果创建时未选择可以使用它进行安装:npm install --save vuex@3.6.2

    src/store/index.js的文件内容为:

    1. import Vue from "vue";
    2. import Vuex from "vuex";
    3. Vue.use(Vuex); //安装插件
    4. export default new Vuex.Store({
    5.   state: {}, //定义全局共享的数据
    6.   getters: {}, //vuex的计算属性,所有组件共享,访问方式:this.$store.getters.函数名
    7.   mutations: {}, //用于修改state数据(同步函数),使用方式如:state.count++
    8.   actions: {}, //用来接收异步请求数据,接收到数据后要把数据先拿到mutations,用mutations把数据存入state,访问方式:this.$store.dispatch(“函数名”,参数) 函数名为actions中定义的函数名
    9.   modules: {},
    10. });

    在main.js中挂载使用:

    插槽slot

    匿名插槽(默认插槽)

    不需要设置name属性,默认为default。

    1. <template>
    2.   <div class="father">
    3.     <h1>我是父组件h1>
    4.     <Children>
    5.      
    6.       <p>我是默认的插槽p>
    7.     Children>
    8.   div>
    9. template>
    10. <script>
    11. import Children from "./Children.vue";
    12. export default {
    13.   components: { Children },
    14. };
    15. script>
    1. <template>
    2.   <div>
    3.     <h2>我是子组件h2>
    4.     <slot>slot>
    5.   div>
    6. template>
    7. <script>
    8. export default {};
    9. script>

    slot所实现的地方:

    实现结果:  

    具名插槽

    slot是带有name的,要用一个template标签包裹,多个具名插槽中所实现插槽的位置是按照在定义的时候的位置来替换的。Vue3中将v-slot简写为:#

    1. <template>
    2.   <div class="father">
    3.     <h1>我是父组件h1>
    4.     <Children>
    5.      
    6.       <p>我是默认的插槽p>
    7.     Children>
    8.   div>
    9. template>
    10. <script>
    11. import Children from "./Children.vue";
    12. export default {
    13.   components: { Children },
    14. };
    15. script>
    1. <template>
    2.   <div>
    3.     <h2>我是子组件h2>
    4.     <slot name="peopleName">slot>
    5.   div>
    6. template>
    7. <script>
    8. export default {};
    9. script>

    实现结果:    

    作用域插槽

    用来传递数据的插槽,v-solt可以解构接收,解构接收的字段要和传的字段一样,例如 :one 对应 v-slot="{one}"

    1. <template>
    2.   <div class="father">
    3.     <h1>我是父组件h1>
    4.     <Children>
    5.       <template v-slot="{ one }">
    6.         <p>我是匿名插槽:{{ one.name }}p>
    7.       template>
    8.       <template v-slot:footer="slotProps">
    9.         <p>我是底部具名插槽:{{ slotProps.users.name }}p>
    10.       template>
    11.     Children>
    12.   div>
    13. template>
    14. <script>
    15. import Children from "./Children.vue";
    16. export default {
    17.   components: { Children },
    18. };
    19. script>
    1. <template>
    2.   <div>
    3.     <h2>我是子组件h2>
    4.     <slot :one="user1">slot>
    5.     <slot name="footer" v-bind:users="user">slot>
    6.   div>
    7. template>
    8. <script>
    9. export default {
    10.   data() {
    11.     return {
    12.       user1: {
    13.         name: "哈利波特",
    14.       },
    15.       user: {
    16.         name: "赫敏",
    17.       },
    18.     };
    19.   },
    20. };
    21. script>

    实现结果: 

  • 相关阅读:
    【吴恩达笔记】卷积神经网络
    网络协议三要素
    关于脑部的基础知识
    Springboot启动流程核心知识点(二):bean的实例化过程
    PHP 中传值与传引用的区别,什么时候传值什么时候传引用?
    负载均衡反向代理下的webshell上传
    C++项目实战-先把项目跑起来看看
    量化、蒸馏、分解、剪枝
    EMPU、EMCU与CPU的比较
    vtk 绘制等高线
  • 原文地址:https://blog.csdn.net/TangJing_/article/details/126350233