search
HomeWeb Front-endFront-end Q&AHow vue instructions implement component communication

Vue instructions implement component communication methods: 1. The parent component passes data to the child component through "props", and the child component can communicate with the parent component through "$emit"; 2. Through "ref/ $refs" attribute to realize component communication; 3. To realize component communication through eventBus event bus; 4. To realize component communication using Vuex; 5. To realize component communication through "$attrs" and "$listeners", etc.

How vue instructions implement component communication

The operating environment of this tutorial: Windows 10 system, Vue version 3, DELL G3 computer

How do vue instructions realize component communication?

Seven ways Vue implements communication between components

1. props / $emit

The parent component passes data to the child component through props, and the child component can communicate with the parent component through $emit:

    ##Parent Passing to children: The parent component introduces the child component through import and registers it. Add the attributes to be passed on the child component label. The child component receives it through props. There are two forms of reception. One is through the array form ['properties to be received']. The second is to pass the object form { }
  • from child to parent: the parent component passes the event method to the child component, and the child component triggers the event through
  • $emit and calls back to the parent component
Characteristics of props:

    props can only pass values ​​from parent components to child components. Props form a one-way downstream binding between parent and child components. The data of the child component will be updated responsively as the parent component is updated; however, the child component cannot cause the data of the parent component to be updated.
  • props can display one or more data. The received data can be of various data types, and it can also pass an object or function.
  • props attribute name rules: If you use camel case in props, the tags in the template need to be written in the form of dashes.

Code example:

Pass from father to son (prop usage)

Parent component:

<template>
    <div>
        <son></son>
    </div>
</template>

<script>
import son from "./son.vue";
export default {
    name: "father",
    components: {
        son
    },
    data() {
        msg: "我是父组件";
    },
    methods: {
        myFunc() {
            console.log("我是父组件的方法");
        }
    }
};
</script>

Child component:

<template>
    <div>
        <p>{{msg}}</p>
        <button>按钮</button>
    </div>
</template>
<script>
export default {
    name: "son",
    props: ["msg", "fn"]
};
</script>
Pass from son to parent (usage of $emit)

$emit binds a self Define an event. When this event is executed, parameters will be passed to the parent component, and the parent component listens and receives parameters through v-on

Parent component:

<template>
  <div>
    <son></son>
    <p>{{currentIndex}}</p>
  </div>
</template>

<script>
import son from &#39;./son.vue&#39;
export default {
  name: &#39;father&#39;,
  components: { son},
  data() {
    return {
      currentIndex: -1,
      arrList: [&#39;龙族&#39;, &#39;绘梨衣&#39;, &#39;前端&#39;,&#39;后端&#39;]
    }
  },
  methods: {
    changeIndex(index) {
      this.currentIndex = index
    }
  }
}
</script>
Child component:

<template>
  <div>
    <div>{{item}}</div>
  </div>
</template>

<script>
export default {
  props: [&#39;arrList&#39;],
  methods: {
    emitIndex(index) {
      this.$emit(&#39;changeIndex&#39;, index) // 触发父组件的方法,并传递参数index
    }
  }
}
</script>
2.ref / $refs

ref: This attribute is used on subcomponents, and its reference points to the instance of the subcomponent. The data and methods of the component can be accessed through the instance. ; If used on a normal DOM element, the reference points to DOM element

.

Parent component:

<template>
  <child>
</child></template>
<script>
  import child from &#39;./child.vue&#39;
  export default {
    components: { child },
    mounted () {
      console.log(this.$refs.child.name);  // mySon
      this.$refs.child.sayHello();  // Hello father!
    }
  }
</script>
Child component:

<template>
  <div></div>
</template>
<script>
export default {
  name:&#39;child&#39;,
  data () {
    return {
      name: &#39;mySon&#39;
    }
  },
  methods: {
    sayHello () {
      console.log(&#39;Hello father!&#39;)
    }
  }
}
</script>
3.eventBus (event bus)

The principle is: event subscription publishing,

eventBus Also known as 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 to send events or receive events to the center, so components can notify other components.

The steps are as follows:

(1) Create an event center to manage communication between components

// event-bus.js

import Vue from 'vue'
export const EventBus = new Vue()

(2) Send an event Suppose there are two sibling components firstCom and secondCom:

Parent components of firstCom and secondCom:

<template>
  <div>
    <first-com></first-com>
    <second-com></second-com>
  </div>
</template>

<script>
import firstCom from &#39;./firstCom.vue&#39;
import secondCom from &#39;./secondCom.vue&#39;
export default {
  components: { firstCom, secondCom }
}
</script>
Send events in the firstCom component:

<template>
  <div>
    <button>点击增加</button>    
  </div>
</template>

<script>
import {EventBus} from &#39;./event-bus.js&#39; // 引入事件中心

export default {
  data(){
    return{
      num:0
    }
  },
  methods:{
    add(){
      EventBus.$emit(&#39;addition&#39;, {
        num:this.num++
      })
    }
  }
}
</script>
(3) Receive events

Receive in the secondCom component Event:

<template>
  <div>求和: {{count}}</div>
</template>

<script>
import { EventBus } from &#39;./event-bus.js&#39;
export default {
  data() {
    return {
      count: 0
    }
  },
  mounted() {
    EventBus.$on(&#39;addition&#39;, param => {
      this.count = this.count + param.num;
    })
  }
}
</script>
In the above code, this is equivalent to storing the num value in the event bus, which can be directly accessed in other components. The event bus is equivalent to a bridge, and components do not communicate through it. Although it seems relatively simple, this method also has its constants. If the project is too large, using this method to communicate will be difficult to maintain later.

4.Vuex

Vuex is a state management pattern developed specifically for Vue.js applications. 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.

Vuex solves the problem of multiple views relying on the same state and The problem that behaviors from different views need to change the same state focuses the developer's energy on the update of data instead of the transfer of data between components

Vuex modules:

  • state:用于数据的存储,是store中的唯一数据源
  • getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
  • mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
  • actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
  • modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

Vuex使用步骤:

(1)这里我们先新建 store文件夹, 对Vuex进行一些封装处理

在 store 文件夹下添加 index.js 文件

// index.js
 
// 自动挂载指定目录下的store
import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
let modules = {}
 
// @/store/module 目录下的文件自动挂载为 store 模块
const subModuleList = require.context('@/store/modules', false, /.js$/)
subModuleList.keys().forEach(subRouter => {
  const moduleName = subRouter.substring(2, subRouter.length - 3)
  modules[moduleName] = subModuleList(subRouter).default
})
//也可自己手动挂载(自行选择)
 
export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules
})

(2)在 store 文件夹下添加 module 文件夹,在module文件夹再新建 user.js 文件

// user.js
 
import user from '@/utils/user.js'
import userApi from '@/apis/user'
import { OPEN_ACCOUNT_STAGE, STAGE_STATUS } from '@/constant'
 
let getUserPromise = null
 
export default {
  namespaced: true,
  state() {
    return {
      userInfo: null, // 用户信息
      isLogined: !!user.getToken(), // 是否已经登录
    }
  },
  mutations: {
    // 更新用户信息
    updateUser(state, payload) {
      state.isLogined = !!payload
      state.userInfo = payload
    },
  },
  actions: {
    // 获取当前用户信息
     getUserInfo(context, payload) {
      //相关代码
    },
 
    // 登出
     logout(context, payload = {}) {
      // 是否手动退出
      const { manual } = payload
      if (manual) {
        await userApi.postLogout()
      }
      user.clearToken()
      context.commit('updateUser', null)
    },
  }
}

(3)然后在项目的 main.js 文件中引入

import Vue from 'vue'
import App from '@/app.vue'
import { router } from '@/router'
import store from '@/store/index'
 
const vue = new Vue({
  el: '#app',
  name: 'root',
  router,
  store,
  render: h => h(App),
})

(4)封装很愉快结束了了,然后就正常操作即可

this.$store.state.user.isLogined
this.$store.state.user.userInfo
this.$store.commit('user/updateUser', {})
 await this.$store.dispatch('user/logout', { manual: true })

5.$attrs与 $listeners

现在我们来讨论另一种情况:如果我们给出的组件关系图中A组件与D组件是隔代关系, 那它们之前进行通信有哪些方式呢?

  1. 使用props绑定来进行一级一级的信息传递, 如果D组件中状态改变需要传递数据给A, 使用事件系统一级级往上传递
  2. 使用eventBus,这种情况下还是比较适合使用, 但是碰到多人合作开发时, 代码维护性较低, 可读性也低
  3. 使用Vuex来进行数据管理, 但是如果仅仅是传递数据, 而不做中间处理,使用Vuex处理感觉有点大材小用了.

所以就有了 $attrs / $listeners ,通常配合 inheritAttrs 一起使用。

inheritAttrs

默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。

通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。

注意:这个选项不影响 class 和 style 绑定,Vue对class和style做了特殊处理

简单来说就是

  • inheritAttrs:true 时继承除props之外的所有属性
  • inheritAttrs:false 只继承class 和 style属性
  • $attrs:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。当一个组件没有声明任何 props 时,它包含所有父作用域的绑定 (class 和 style 除外)。
  • $listeners:包含了父作用域中的 (不含 .native 修饰符) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件。它是一个对象,里面包含了作用在这个组件上的所有事件监听器,相当于子组件继承了父组件的事件。

代码示例:

父组件:

<template>
   <child></child>
</template>
<script>
    import Child from &#39;../components/child.vue&#39;
    export default {
        name: &#39;father&#39;,
        components: { Child },
        data () {
            return {
                name: &#39;绘梨衣&#39;,
                age: 22,
                infoObj: {
                    from: &#39;河北&#39;,
                    job: &#39;superman&#39;,
                    hobby: [&#39;reading&#39;, &#39;writing&#39;, &#39;eating&#39;]
                }
            }
        },
        methods: {
            updateInfo() {
                console.log(&#39;update info&#39;);
            },
            delInfo() {
                console.log(&#39;delete info&#39;);
            }
        }
    }
</script>

 儿子组件:

<template>
    <!-- 通过 $listeners 将父作用域中的事件,传入 grandSon 组件,使其可以获取到 father 中的事件 -->
    <grand-son></grand-son>
</template>
<script>
    import GrandSon from &#39;../components/grandSon.vue&#39;
    export default {
        name: &#39;child&#39;,
        components: { GrandSon },
        props: [&#39;name&#39;],
        data() {
          return {
              height: &#39;170cm&#39;,
              weight: &#39;55kg&#39;
          };
        },
        created() {
            console.log(this.$attrs); 
       // 结果:age, infoObj, 因为父组件共传来name, age, infoObj三个值,由
             //于name被 props接收了,所以只有age, infoObj属性
            console.log(this.$listeners); // updateInfo: f, delInfo: f
        },
        methods: {
            addInfo () {
                console.log(&#39;add info&#39;)
            }
        }
    }
</script>

孙子组件:

<template>
    <div>
        {{ $attrs }} --- {{ $listeners }}
    <div>

<script>
    export default {
        props: [&#39;weight&#39;],
        created() {
            console.log(this.$attrs); // age, infoObj, height 
            console.log(this.$listeners) 
          // updateInfo: f, delInfo: f, addInfo: f
            this.$emit(&#39;updateInfo&#39;) 
          // 可以触发 father 组件中的updateInfo函数
        }
    }
</script><h2 id="parent-children">6.$parent / $children</h2>
<ul>
<li>使用$parent可以让组件访问父组件的实例(访问的是上一级父组件的属性和方法)。</li>
<li>使用 $children 可以让组件访问子组件的实例,但是, $children 并不能保证顺序,并且访问的数据也不是响应式的。</li>
</ul>
<p><strong>注意:</strong></p>
<blockquote><ul>
<li>通过 $parent 访问到的是上一级父组件的实例,可以使用 $root 来访问根组件的实例</li>
<li>在组件中使用$children拿到的是所有的子组件的实例,它是一个数组,并且是无序的</li>
<li>在根组件 #app 上拿 $parent 得到的是 new Vue()的实例,在这实例上再拿 $parent 得到的是undefined,而在最底层的子组件拿 $children 是个空数组</li>
<li>$children 的值是数组,而 $parent是个对象</li>
</ul></blockquote>
<h3>
<a name="t13"></a><a id="_291"></a>用法:</h3>
<p>子组件:</p>
<pre class="brush:php;toolbar:false"><template>
  <div>
    <span>{{message}}</span>
    <p>父组件的值为:  {{parentVal}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: &#39;Vue&#39;
    }
  },
  computed:{
    parentVal(){
      return this.$parent.msg;
    }
  }
}
</script>

父组件:

<template>
  <div>
    <div>{{msg}}</div>
    <child></child>
    <button>点击改变子组件值</button>
  </div>
</template>

<script>
import child from &#39;./child.vue&#39;
export default {
  components: { child },
  data() {
    return {
      msg: &#39;Hello&#39;
    }
  },
  methods: {
    change() {
      // 获取到子组件
      this.$children[0].message = &#39;JavaScript&#39;
    }
  }
}
</script>

7.依赖注入(provide / inject)

这种方式就是vue中依赖注入,该方法用于 父子组件之间 的通信。当然这里所说的父子不一定是真正的父子,也可以是祖孙组件,在层数很深的情况下,可以使用这种方式来进行传值。就不用一层一层的传递数据了。

provide和inject是vue提供的两个钩子,和data、methods是同级的。并且provide的书写形式和data一样。

  • provide 钩子用来发送数据或方法
  • inject钩子用来接收数据或方法

注意: 依赖注入所提供的属性是非响应式的。

用法:

父组件:

provide() { 
    return {     
        num: this.num  
    };
}

子组件:

inject: ['num']

还有另一种写法,这种写法可以访问父组件中的所有属性:

provide() {
 return {
    app: this
  };
}
data() {
 return {
    num: 111
  };
}

inject: ['app']
console.log(this.app.num)

总结

1.父子组件间通信

  • 子组件通过 props 属性来接受父组件的数据,然后父组件在子组件上注册监听事件,子组件通过 emit 触发事件来向父组件发送数据。
  • 通过 ref 属性给子组件设置一个名字。父组件通过 $refs 组件名来获得子组件,子组件通过 $parent 获得父组件,这样也可以实现通信。
  • 使用 provide/inject,在父组件中通过 provide提供变量,在子组件中通过 inject 来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provide中的数据

2.跨代组件间通信

跨代组件间通信其实就是多层的父子组件通信,同样可以使用上述父子组件间通信的方法,只不过需要多层通信会比较麻烦。

3.兄弟组件间通信

通过 $parent + $refs 以父组件为中间人来获取到兄弟组件,也可以进行通信。

4.任意组件间通信

使用 eventBus ,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。它的本质是通过创建一个空的 Vue 实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过在这个实例上监听和触发事件,来实现消息的传递。

推荐学习:《vue.js视频教程

The above is the detailed content of How vue instructions implement component communication. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
HTML and React's Integration: A Practical GuideHTML and React's Integration: A Practical GuideApr 21, 2025 am 12:16 AM

HTML and React can be seamlessly integrated through JSX to build an efficient user interface. 1) Embed HTML elements using JSX, 2) Optimize rendering performance using virtual DOM, 3) Manage and render HTML structures through componentization. This integration method is not only intuitive, but also improves application performance.

React and HTML: Rendering Data and Handling EventsReact and HTML: Rendering Data and Handling EventsApr 20, 2025 am 12:21 AM

React efficiently renders data through state and props, and handles user events through the synthesis event system. 1) Use useState to manage state, such as the counter example. 2) Event processing is implemented by adding functions in JSX, such as button clicks. 3) The key attribute is required to render the list, such as the TodoList component. 4) For form processing, useState and e.preventDefault(), such as Form components.

The Backend Connection: How React Interacts with ServersThe Backend Connection: How React Interacts with ServersApr 20, 2025 am 12:19 AM

React interacts with the server through HTTP requests to obtain, send, update and delete data. 1) User operation triggers events, 2) Initiate HTTP requests, 3) Process server responses, 4) Update component status and re-render.

React: Focusing on the User Interface (Frontend)React: Focusing on the User Interface (Frontend)Apr 20, 2025 am 12:18 AM

React is a JavaScript library for building user interfaces that improves efficiency through component development and virtual DOM. 1. Components and JSX: Use JSX syntax to define components to enhance code intuitiveness and quality. 2. Virtual DOM and Rendering: Optimize rendering performance through virtual DOM and diff algorithms. 3. State management and Hooks: Hooks such as useState and useEffect simplify state management and side effects handling. 4. Example of usage: From basic forms to advanced global state management, use the ContextAPI. 5. Common errors and debugging: Avoid improper state management and component update problems, and use ReactDevTools to debug. 6. Performance optimization and optimality

React's Role: Frontend or Backend? Clarifying the DistinctionReact's Role: Frontend or Backend? Clarifying the DistinctionApr 20, 2025 am 12:15 AM

Reactisafrontendlibrary,focusedonbuildinguserinterfaces.ItmanagesUIstateandupdatesefficientlyusingavirtualDOM,andinteractswithbackendservicesviaAPIsfordatahandling,butdoesnotprocessorstoredataitself.

React in the HTML: Building Interactive User InterfacesReact in the HTML: Building Interactive User InterfacesApr 20, 2025 am 12:05 AM

React can be embedded in HTML to enhance or completely rewrite traditional HTML pages. 1) The basic steps to using React include adding a root div in HTML and rendering the React component via ReactDOM.render(). 2) More advanced applications include using useState to manage state and implement complex UI interactions such as counters and to-do lists. 3) Optimization and best practices include code segmentation, lazy loading and using React.memo and useMemo to improve performance. Through these methods, developers can leverage the power of React to build dynamic and responsive user interfaces.

React: The Foundation for Modern Frontend DevelopmentReact: The Foundation for Modern Frontend DevelopmentApr 19, 2025 am 12:23 AM

React is a JavaScript library for building modern front-end applications. 1. It uses componentized and virtual DOM to optimize performance. 2. Components use JSX to define, state and attributes to manage data. 3. Hooks simplify life cycle management. 4. Use ContextAPI to manage global status. 5. Common errors require debugging status updates and life cycles. 6. Optimization techniques include Memoization, code splitting and virtual scrolling.

The Future of React: Trends and Innovations in Web DevelopmentThe Future of React: Trends and Innovations in Web DevelopmentApr 19, 2025 am 12:22 AM

React's future will focus on the ultimate in component development, performance optimization and deep integration with other technology stacks. 1) React will further simplify the creation and management of components and promote the ultimate in component development. 2) Performance optimization will become the focus, especially in large applications. 3) React will be deeply integrated with technologies such as GraphQL and TypeScript to improve the development experience.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

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

Hot Tools

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment