Home  >  Article  >  Web Front-end  >  Six ways to communicate with Vue components

Six ways to communicate with Vue components

hzc
hzcforward
2020-06-18 09:44:073220browse

In the normal development process, communication between father-son/sibling components is definitely encountered, so here is a summary of the communication props of 6 Vue components / $e$emit / Vuex$attrs / $ listeners

  1. $parent / $children with ref

  2. provide / inject

##Preface

Six ways to communicate with Vue components

As shown in the figure above, components A/B, B/C, and B/D are father-son relationships, and C/D is a brother relationship. So how to choose different communication methods according to different usage scenarios? So the premise is that we need to understand the functions and differences of different communication methods.

1. props / $emit

This is one of the methods we usually use more often. Parent component A passes data to child component B through the props parameter. Component B sends an event (carrying parameter data) to component A through $emit. Component A listens to the event triggered by $emit and obtains the data sent by B to A. Let’s explain its implementation steps in detail:

1: Parent component passes value to child component
// App.vue 父组件
<template>
    <a-compontent></a-compontent>
</template>
<script>
import aCompontent from &#39;./components/A.vue&#39;;
export default {
    name: &#39;app&#39;,
    compontent: { aCompontent },    
    data () {        
        return {
         dataA: &#39;dataA数据&#39;
       }
    }
}
// aCompontent 子组件
<template>
    <p>{{dataA}} // 在子组件中把父组件传递过来的值显示出来

<script>export default {
    name: &#39;aCompontent&#39;,
    props: {
        dataA: {           
              //这个就是父组件中子标签自定义名字            
              type: String,
            required: true  // 或者false
        }
    }
}
</script>

2: Child component passes value to parent component (Through events)
// 子组件
<template>
    <p>点击向父组件传递数据</p>
</template>
<script>export default {
    name: &#39;child&#39;,
    methods:{        
        changeTitle() {
              // 自定义事件,会触发父组件的监听事件,并将数据以参数的形式传递
            this.$emit(&#39;sendDataToParent&#39;,&#39;这是子组件向父组件传递的数据&#39;); 
        }
    }
}

// 父组件
<template>
    <child @sendDataToParent="getChildData">

<script>
import child from &#39;./components/child.vue&#39;;
    export default {
    name: &#39;child&#39;,
    methods:{
        getChildData(data) {
            console.log(data); // 这里的得到了子组件的值
        }
    }
}
</script>

2. $emit / $on

This method uses an instance similar to App.vue as a module Event Center, use it to trigger and listen for events. If you put it in App.vue, you can implement communication in any component. However, this method is not easy to maintain when the project is relatively large.

For example: Suppose there are 4 components now, Home.vue and A/B/C components. These three components AB are sibling components. Home.vue is equivalent to the parent component creating an empty Vue instance. Mount the communication event on the instance -

D.js
import Vue from 'vue'export default new Vue()
// 我们可以在router-view中监听change事件,也可以在mounted方法中监听
// home.vue<template>  <p>    <child-a></child-a>    <child-b></child-b>    <child-c></child-c>  </p></template>
// A组件
<template>
  <p>将A组件的数据发送给C组件 - {{name}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      name: &#39;Echo&#39;
    }
  },
  components: { Event },
  methods: {    dataA() {
      Event.$emit(&#39;data-a&#39;, this.name);
    }
  }
}
</script>
// B组件
<template>
  <p>将B组件的数据发送给C组件 - {{age}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      age: &#39;18&#39;
    }
  },
  components: { Event },
  methods: {    dataB() {
      Event.$emit(&#39;data-b&#39;, this.age);
    }
  }
}
</script>
// C组件
<template>
  <p>C组件得到的数据 {{name}} {{age}}</p>
</template>
<script>
import Event from "./D";export default {  data() {    return {
      name: &#39;&#39;,
      age: &#39;&#39;
    }
  },
  components: { Event },  mounted() {
    // 在模板编译完成后执行
    Event.$on(&#39;data-a&#39;, name => {
      this.name = name;
    })
    Event.$on(&#39;data-b&#39;, age => {
      this.age = age;
    })
  }
}
</script>
We can know from the above that the $emit event of A/B is monitored in the mounted event of the C component and the parameters passed by it are obtained ( Since we are not sure when the event is triggered, we usually listen in mounted / created)

3. Vuex

Vuex is a state management mode. It uses centralized storage to manage the state of all components of the application, and uses corresponding rules to ensure that the state changes in a predictable way. The core of the Vuex application is the store (warehouse, a container). The store contains most of the state in your application;

This part will not be introduced in detail, the official document is very detailed vuex.vuejs .org/zh/guide/st…

Four. $attrs / $listeners

As shown in the picture above, this is A multi-level component nesting, how do the A/C components communicate? We can think of the following solutions now:

    Use Vuex for data management, but the problem with using vuex is that if the project is relatively small and there is less shared state between components, then use vuex is like killing a chicken with a knife.
  1. Use B component as a transfer station. When A component needs to pass information to C component, B accepts the information of A component and then uses props to pass it to C component. However, if there are too many nested components, it will The code is cumbersome and code maintenance is difficult; if the change of state in C needs to be passed to A, the event system must be used to pass it up level by level.
In Vue2.4, in order to solve this requirement, attrs and listeners were introduced, and the inheritAttrs option was added. (As shown in the picture below)

The role of $attrs, in some cases needs to be used in conjunction with inheritAttrs

There are 4 components: App.vue / child1.vue / child2.vue / child3.vue, these four components are nested in sequence.

// App.vue
<template>
  <p>
    </p>
<p>App.vue</p>
<hr>
    // 这里我们可以看到,app.vue向下一集的child1组件传递了5个参数,分别是name / age / job / sayHi / title
    <child1></child1>
  
</template>
<script>
const child1 = () => import("./components/child1.vue");
export default {
  name: &#39;app&#39;,
  components: { child1 },  data() {    return {
      name: "Echo",
      age: "18",
      job: "FE",
      say: "this is Hi~"
    };
  }
};
</script>
// child1.vue
<template>
  <p>
    </p>
<p>child1.vue</p>
    <p>name: {{ name }}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <p>可以看到,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数</p>
    <hr>
    <child2></child2>
  
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  // 这个inheritAttrs默认值为true,不定义这个参数值就是true,可手动设置为false
  // inheritAttrs的意义在用,可以在从父组件获得参数的子组件根节点上,将所有的$attrs以dom属性的方式显示
  inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    name: String // name作为props属性绑定
  },  created() {
    // 这里的$attrs就是所有从父组件传递过来的所有参数 然后 除去props中显式定义的参数后剩下的所有参数!!!
    console.log(this.$attrs); //  输出{age: "18", job: "FE", say-Hi: "this is Hi~", title: "App.vue的title"}
  }
};
</script>
// child2.vue
<template>
  <p>
    </p>
<p>child2.vue</p>
    <p>age: {{ age }}</p>
    <p>childCom2: {{ $attrs }}</p>
    <hr>
    <child3></child3>
  
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  },
  // 将inheritAttrs设置为false之后,将关闭自动挂载到组件根元素上的没有在props声明的属性
  inheritAttrs: false,
  props: {
    age: String
  },  created() {
    // 同理和上面一样,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数
    console.log(this.$attrs);
  }
};
</script>
// child3.vue
<template>
  <p>
    </p>
<p>child3.vue</p>
    <p>job: {{job}}</p>
    <p>title: {{title}}</p>
    <p>childCom3: {{ $attrs }}</p>
  
</template>
<script>export default {
  inheritAttrs: true,
  props: {
    job: String,
    title: String
  }
};
</script>
Let’s take a look at the specific display effect:

And how to use $listeners, the official document says: Contains the content in the parent scope (without .native decorator) v-on event listener. It can be passed into inner components via v-on="$listeners" - very useful when creating higher level components! From the literal meaning, it should be to add a listening event to the parent component that needs to accept the value? Not much to say, the code

is still 3 components nested in sequence

<template>
  <p>
    <child2></child2>
  </p>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  methods: {    reciveRocket() {
      console.log("reciveRocket success");
    }
  }
};
</script>复制代码
<template>
  <p>
    <child3></child3>
  </p>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  },  created() {
    this.$emit(&#39;child2&#39;, &#39;child2-data&#39;);
  }
};
</script>复制代码
// child3.vue
<template>
  <p>
    </p>
<p>child3</p>
  
</template>
<script>
export default {
  methods: {    startUpRocket() {
      this.$emit("upRocket");
      console.log("startUpRocket");
    }
  }
};
</script>复制代码

这里的结果是,当我们点击 child3 组件的 child3 文字,触发 startUpRocket 事件,child1 组件就可以接收到,并触发 reciveRocket 打印结果如下:

> reciveRocket success
> startUpRocket

五. $parent / $children 与 ref

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
  • $parent / $children:访问父 / 子实例

这两种方式都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。

我们先来看个用 ref 来访问组件的:

// child1子组件
export default {  
        data() {    
            return {
      title: 'Vue.js'
    };
  },
  methods: {    
      sayHello() {
      console.log('child1!!');
    }
  }
};
// 父组件
<template>
  <child1></child1>
</template>
<script>  
export default {
    methods: {      
        sayHi () {
        const child1 = this.$refs.child1;
        console.log(child1.title);  // Vue.js
        child1.sayHello();  // 弹窗
      }
    }
  }
</script>

六. provide/inject

provide/inject 是 Vue2.2.0 新增 API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。

由于自己对这部分的内容理解不是很深刻,所以感兴趣的可以前往官方文档查看: cn.vuejs.org/v2/api/#pro…

总结

常见使用场景可以分为三类:

  1. 父子通信:props / $emit;$parent / $children;$attrs/$listeners;provide / inject API; ref
  2. 兄弟通信:Vuex
  3. 跨级通信:Vuex;$attrs/$listeners;provide / inject API
    4.接下来我还会在我的裙里用视频讲解的方式给大家讲解【以下图中的内容有兴趣的可以来我的扣扣裙 519293536 免费交流学习,我都会尽力帮大家哦

推荐教程:《JS教程

The above is the detailed content of Six ways to communicate with Vue components. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete