


Introduction to 8 ways to communicate with Vue components (Collection)
vue is a framework for data-driven view updates, so data communication between components is very important for vue. So how do data communication occur between components? First of all, we need to know what kind of relationship exists between components in Vue, so that it is easier to understand their communication methods.
Relationship description in the vue component:
As shown in the picture above, A and B, A and C, B and D, The relationship between components C and E is a father-son relationship; the relationship between B and C is a brother; the relationship between A and D, and A and E is a generational relationship; the relationship between D and E is a cousin (not an immediate relative). For the above relationships, we The class is:
Communication between parent and child components
Communication between non-parent and child components (sibling components, generation-separated components, etc.)
1. props / $emit
The parent component passes data to the child component through props, and through $emit Child components can communicate with parent components.
1. Parent component passes value to child component
How the parent component passes data to the child component: How to get the parent component section.vue in the child component article.vue Data in articles
// section父组件 <template> <p class="section"> <com-article :articles="articleList"></com-article> </p> </template> <script> import comArticle from './test/article.vue' export default { name: 'HelloWorld', components: { comArticle }, data() { return { articleList: ['one', 'two', 'three','four','fives'] } } } </script> // 子组件 article.vue <template> <p> <span v-for="(item, index) in articles" :key="index">{{item}}</span> </p> </template> <script> export default { props: ['articles'] } </script>
Summary: prop can only be passed from the upper-level component to the lower-level component (parent-child component), which is the so-called one-way data flow. Moreover, prop is read-only and cannot be modified. All modifications will be invalid and a warning will be issued.
2. The child component passes the value to the parent component
My own understanding of $emit is this: $emit binds a custom event, When this statement is executed, the parameter arg will be passed to the parent component, and the parent component listens and receives the parameters through v-on. Through an example, explain how the child component passes data to the parent component. Based on the previous example, click on the ariticle item rendered by the page, and the subscript
// 父组件中 <template> <p class="section"> <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article> <p>{{currentIndex}}</p> </p> </template> <script> import comArticle from './test/article.vue' export default { name: 'HelloWorld', components: { comArticle }, data() { return { currentIndex: -1, articleList: ['one', 'two', 'three','four','fives'] } }, methods: { onEmitIndex(idx) { this.currentIndex = idx } } } </script> <template> <p> <p v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</p> </p> </template> <script> export default { props: ['articles'], methods: { emitIndex(index) { this.$emit('onEmitIndex', index) } } } </script>
// 父组件中 <template> <p class="hello_world"> <p>{{msg}}</p> <com-a></com-a> <button @click="changeA">点击改变子组件值</button> </p> </template> <script> import ComA from './test/comA.vue' export default { name: 'HelloWorld', components: { ComA }, data() { return { msg: 'Welcome' } }, methods: { changeA() { // 获取到子组件A this.$children[0].messageA = 'this is new value' } } } </script> // 子组件中 <template> <p class="com_a"> <span>{{messageA}}</span> <p>获取父组件的值为: {{parentVal}}</p> </p> </template> <script> export default { data() { return { messageA: 'this is old' } }, computed:{ parentVal(){ return this.$parent.msg; } } } </script>
in the parent component is displayed in the array. Pay attention to boundary conditions, such as taking $parent on #app What you get is an instance of new Vue(). If you take $parent on this instance, you get undefined, and if you take $children on the bottom child component, it is an empty array. Also note that the values of $parent and $children are different. The value of $children is an array, and $parent is an object.
Summary
The above two methods are used for communication between parent and child components, and props are used for communication. Parent-child component communication is more common; neither can be used for communication between non-parent-child components.
3. provide/ inject
Concept:
provide/ inject is a new API of vue2.2.0, simple In other words, the parent component provides variables through provide, and then injects variables into the child component through inject.
Note: No matter how deeply the sub-component is nested here, as long as inject is called, the data in provide can be injected, and it is not limited to returning data from the props attribute of the current parent component
Example verification
Next, use an example to verify the above description: Suppose there are three components: A.vue, B.vue, C.vue, where C is a subcomponent of B, and B is a subcomponent of A.
// A.vue <template> <p> <comB></comB> </p> </template> <script> import comB from '../components/test/comB.vue' export default { name: "A", provide: { for: "demo" }, components:{ comB } } </script> // B.vue <template> <p> {{demo}} <comC></comC> </p> </template> <script> import comC from '../components/test/comC.vue' export default { name: "B", inject: ['for'], data() { return { demo: this.for } }, components: { comC } } </script> // C.vue <template> <p> {{demo}} </p> </template> <script> export default { name: "C", inject: ['for'], data() { return { demo: this.for } } } </script>
4. ref / refs
ref: If used on a normal DOM element, the reference points to the DOM element; if used On a subcomponent, the reference points to the component instance. You can directly call the component's method or access data through the instance. Let's look at an example of accessing the component using ref:
// 子组件 A.vue export default { data () { return { name: 'Vue.js' } }, methods: { sayHello () { console.log('hello') } } } // 父组件 app.vue <template> <component-a ref="comA"></component-a> </template> <script> export default { mounted () { const comA = this.$refs.comA; console.log(comA.name); // Vue.js comA.sayHello(); // hello } } </script>
5 , eventBus
eventBus is also called event bus. It can be used as a communication bridge concept in vue. It is like all components share the same event center and can register with the center. Send events or receive events, so components can notify other components.
EventBus also has inconveniences. When the project is large, it can easily cause disasters that are difficult to maintain.
How to use eventBus to achieve data communication between components in Vue projects? Specifically Through the following steps
1. Initialization
First you need to create an event bus and export it so that other modules can use or monitor it.
// event-bus.js import Vue from 'vue' export const EventBus = new Vue()
2. Send events
Suppose you have two components: additionNum and showNum. These two components can be sibling components or parent-child components; here we use sibling components as Example:
<template> <p> <show-num-com></show-num-com> <addition-num-com></addition-num-com> </p> </template> <script> import showNumCom from './showNum.vue' import additionNumCom from './additionNum.vue' export default { components: { showNumCom, additionNumCom } } </script> // addtionNum.vue 中发送事件 <template> <p> <button @click="additionHandle">+加法器</button> </p> </template> <script> import {EventBus} from './event-bus.js' console.log(EventBus) export default { data(){ return{ num:1 } }, methods:{ additionHandle(){ EventBus.$emit('addition', { num:this.num++ }) } } } </script>
3. Receive the event
// showNum.vue 中接收事件 <template> <p>计算和: {{count}}</p> </template> <script> import { EventBus } from './event-bus.js' export default { data() { return { count: 0 } }, mounted() { EventBus.$on('addition', param => { this.count = this.count + param.num; }) } } </script>
This way, click the add button in the component additionNum.vue, in showNum. In vue, the passed num is used to display the summation result.
4. Remove the event listener
If you want to remove the event listener, you can do as follows Operation:
import { eventBus } from 'event-bus.js' EventBus.$off('addition', {})
6. Vuex
##1. Introduction to Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. Vuex 解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上
2、Vuex各个模块
state:用于数据的存储,是store中的唯一数据源
getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护
3、Vuex实例应用
// 父组件 <template> <p id="app"> <ChildA/> <ChildB/> </p> </template> <script> import ChildA from './components/ChildA' // 导入A组件 import ChildB from './components/ChildB' // 导入B组件 export default { name: 'App', components: {ChildA, ChildB} // 注册A、B组件 } </script> // 子组件childA <template> <p id="childA"> <h1 id="我是A组件">我是A组件</h1> <button @click="transform">点我让B组件接收到数据</button> <p>因为你点了B,所以我的信息发生了变化:{{BMessage}}</p> </p> </template> <script> export default { data() { return { AMessage: 'Hello,B组件,我是A组件' } }, computed: { BMessage() { // 这里存储从store里获取的B组件的数据 return this.$store.state.BMsg } }, methods: { transform() { // 触发receiveAMsg,将A组件的数据存放到store里去 this.$store.commit('receiveAMsg', { AMsg: this.AMessage }) } } } </script> // 子组件 childB <template> <p id="childB"> <h1 id="我是B组件">我是B组件</h1> <button @click="transform">点我让A组件接收到数据</button> <p>因为你点了A,所以我的信息发生了变化:{{AMessage}}</p> </p> </template> <script> export default { data() { return { BMessage: 'Hello,A组件,我是B组件' } }, computed: { AMessage() { // 这里存储从store里获取的A组件的数据 return this.$store.state.AMsg } }, methods: { transform() { // 触发receiveBMsg,将B组件的数据存放到store里去 this.$store.commit('receiveBMsg', { BMsg: this.BMessage }) } } } </script> vuex的store,js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const state = { // 初始化A和B组件的数据,等待获取 AMsg: '', BMsg: '' } const mutations = { receiveAMsg(state, payload) { // 将A组件的数据存放于state state.AMsg = payload.AMsg }, receiveBMsg(state, payload) { // 将B组件的数据存放于state state.BMsg = payload.BMsg } } export default new Vuex.Store({ state, mutations })
七、localStorage / sessionStorage
这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。 通过window.localStorage.getItem(key)获取数据 通过window.localStorage.setItem(key,value)存储数据
注意用JSON.parse() / JSON.stringify() 做数据格式转换 localStorage / sessionStorage可以结合vuex, 实现数据的持久保存,同时使用vuex解决数据和状态混乱问题.
八 $attrs与 $listeners
现在我们来讨论一种情况, 我们一开始给出的组件关系图中A组件与D组件是隔代关系, 那它们之前进行通信有哪些方式呢?
使用props绑定来进行一级一级的信息传递, 如果D组件中状态改变需要传递数据给A, 使用事件系统一级级往上传递
使用eventBus,这种情况下还是比较适合使用, 但是碰到多人合作开发时, 代码维护性较低, 可读性也低
使用Vuex来进行数据管理, 但是如果仅仅是传递数据, 而不做中间处理,使用Vuex处理感觉有点大材小用了.
在vue2.4中,为了解决该需求,引入了$attrs 和$listeners , 新增了inheritAttrs 选项。 在版本2.4以前,默认情况下,父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外),将会“回退”且作为普通的HTML特性应用在子组件的根元素上。接下来看一个跨级通信的例子:
// app.vue // index.vue <template> <p> <child-com1 :name="name" :age="age" :gender="gender" :height="height" title="程序员成长" ></child-com1> </p> </template> <script> const childCom1 = () => import("./childCom1.vue"); export default { components: { childCom1 }, data() { return { name: "zhang", age: "18", gender: "女", height: "158" }; } }; </script> // childCom1.vue <template class="border"> <p> <p>name: {{ name}}</p> <p>childCom1的$attrs: {{ $attrs }}</p> <child-com2 v-bind="$attrs"></child-com2> </p> </template> <script> const childCom2 = () => import("./childCom2.vue"); export default { components: { childCom2 }, inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性 props: { name: String // name作为props属性绑定 }, created() { console.log(this.$attrs); // { "age": "18", "gender": "女", "height": "158", "title": "程序员成长" } } }; </script> // childCom2.vue <template> <p class="border"> <p>age: {{ age}}</p> <p>childCom2: {{ $attrs }}</p> </p> </template> <script> export default { inheritAttrs: false, props: { age: String }, created() { console.log(this.$attrs); // { "gender": "女", "height": "158", "title": "程序员成长指北" } } }; </script>
总结
常见使用场景可以分为三类:
父子组件通信: props; $parent / $children; provide / inject ; ref ; $attrs / $listeners
兄弟组件通信: eventBus ; vuex
跨级通信: eventBus;Vuex;provide / inject 、$attrs / $listeners
The above is the detailed content of Introduction to 8 ways to communicate with Vue components (Collection). For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Using Bootstrap in Vue.js is divided into five steps: Install Bootstrap. Import Bootstrap in main.js. Use the Bootstrap component directly in the template. Optional: Custom style. Optional: Use plug-ins.

You can add a function to the Vue button by binding the button in the HTML template to a method. Define the method and write function logic in the Vue instance.

There are three ways to refer to JS files in Vue.js: directly specify the path using the <script> tag;; dynamic import using the mounted() lifecycle hook; and importing through the Vuex state management library.

The watch option in Vue.js allows developers to listen for changes in specific data. When the data changes, watch triggers a callback function to perform update views or other tasks. Its configuration options include immediate, which specifies whether to execute a callback immediately, and deep, which specifies whether to recursively listen to changes to objects or arrays.

Vue multi-page development is a way to build applications using the Vue.js framework, where the application is divided into separate pages: Code Maintenance: Splitting the application into multiple pages can make the code easier to manage and maintain. Modularity: Each page can be used as a separate module for easy reuse and replacement. Simple routing: Navigation between pages can be managed through simple routing configuration. SEO Optimization: Each page has its own URL, which helps SEO.

Vue.js has four methods to return to the previous page: $router.go(-1)$router.back() uses <router-link to="/" component window.history.back(), and the method selection depends on the scene.

You can query the Vue version by using Vue Devtools to view the Vue tab in the browser's console. Use npm to run the "npm list -g vue" command. Find the Vue item in the "dependencies" object of the package.json file. For Vue CLI projects, run the "vue --version" command. Check the version information in the <script> tag in the HTML file that refers to the Vue file.

Function interception in Vue is a technique used to limit the number of times a function is called within a specified time period and prevent performance problems. The implementation method is: import the lodash library: import { debounce } from 'lodash'; Use the debounce function to create an intercept function: const debouncedFunction = debounce(() => { / Logical / }, 500); Call the intercept function, and the control function is called at most once in 500 milliseconds.
