Vue2组件通信方式

Vue2组件通信方式包括如下几种方式

  • props、$emit(父传子props,子传父$emit)
  • $emit、$on(即EventBus传值,依赖全局Vue干线)
  • provide、inject(父组件通过provide提供参数,子孙组件通过inject注入参数)
  • $attrs、$listeners(创建高层次组件时使用,attrs包含了父组件中没有被props声明的参数,listeners包含了父组件中不含.native修饰器的事件监听器)
  • Vuex通信

1、父子传参(props和$emit)

父组件

//父组件
<template>
	<div class="main-panel">
        //子组件
		<banner-module :lang="test" @textFun="textFun" />
		<ensure-module :lang="test" />
	</div>
</template>

<script>
//引入子组件
import bannerModule  from './tabs/banner/index.vue'						
import ensureModule from './tabs/ensure/index.vue'						
export default {
    data () {
        return {
            test: 1    
        }
    },
    //声明子组件
    components :{
		bannerModule,
		ensureModule
	},
    methods:{
        textFun(val){
            console.log(val)
        }
    }    
}
</script>

<style>
	
</style>

子组件不可直接改变父组件的值,需要定义新的变量接受父组件的传递值,将新值使用$emit返回给父组件

<template>
	<div class="product-banner">
		<div class="product-notice">
			<p>{{num}}</p>
		</div>
        <van-button @click="addtest">新增</van-button>
	</div>
</template>

<script>
export default {
    //props接受
	props :{
		lang : {
			type : Number,
			default : 1
		}
	},
    data(){
        return{
            num: this.lang
        }
    },
    methods: {
        addtest(){
            //不可以直接改变父组件的值,需要定义新的变量
            this.num ++
            //通知父组件接受新值
            this.$emit("textFun", this.num)
        }
    }
}
</script>
<style scoped>
</style>

2、$emit和$on(全局组件通信)

利用Vue实例作为中央事件总线,来触发和监听事件。实现父子、兄弟、跨级之间的通信

//A组件
<template>
	<div class="main-panel">
        {{test}}
        <div @click="sendBData">发送</div>
	</div>
</template>

<script>
import eventBus from './utils/bus.js'					
export default {
    data () {
        return {
            test: 1    
        }
    },
    methods:{
        sendBData(){
            this.test ++ 
            //发送receiptData方法到全局Vue
            eventBus.$emit("receiptData", this.test)
        }
    }    
}
</script>
//B组件
<template>
	<div class="main-panel">
        {{number}}
	</div>
</template>

<script>
import eventBus from './utils/bus.js'					
export default {
    data () {
        return {
            number: 0  
        }
    },
    created(){
        //监听receiptData方法
        eventBus.$on("receiptData", (val)=>{
            this.number = val
        })
    },
    methods:{
    }    
}
</script>

bus.js 

import Vue from "vue"
var eventBus  =  new Vue()
export default eventBus

3、provide、inject

provide是一个对象,或者是一个返回对象的函数;inject 是一个字符串数组,或者是一个对象

provideinject绑定不是响应的,所以A组件中值改变,B组件中是不会改变的。

//A组件
<template>
	<div class="main-panel">
        {{text}}
        <p @click="changeText">修改</p>
	</div>
</template>

<script>				
export default {
    provide() {
       return: {
           name: "A组件", //无法修改
           app: this,
           test: this.text
       }     
    },
    data () {
        return {
            text: 1,
            name: 'A',    
        }
    },
    methods: {
        changeText(){
            this.text++  //修改后B组件视图不更新
            this.name = 'C' //修改后B组件视图会更新
        }
    }    
}
</script>
//B组件
<template>
	<div class="main-panel">
        <p>组件A的名称:{{app.name}}</p>
        <p>组件A的text:{{text}},组件B的text:{{num}}</p>
	</div>
</template>

<script>
import eventBus from './utils/bus.js'					
export default {
    inject: ['name', 'app', 'text'],
    data () {
        return {
            num: 1    
        }
    }    
}
</script>

4、$attrs、$listeners

A组件向B(子组件)使用props传递了message参数,C组件是B组件的子组件,这时候如果A向C传递参数的话就用到$attrs 监听C返回的变化就用到了listeners

//A组件
<template>
	<div class="main-panel">
      <B :message="message" @getCData="getCData" @getBData="getBData"></B>
	</div>
</template>

<script>
import B from '...B.vue'				
export default {
    data () {
        return {
            message:'hello',
            messageC:'hello C',
        }
    },
    components: {
        B
    },
    methods:{
        getCData(val){
            console.log("这是C的参数",val)
        },
        getBData(val){
            console.log("这是B的参数",val)
        }
    }    
}
</script>

C组件可以直接触发getCData在于B在调用C的时候使用v-on绑定了$listeners属性
通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的

上面这句话的意思是:如果我们在给B传递数据时,多传递一个名字叫做messageB的参数,但是在B组件中没有去接受messageB参数,那么在C组件中也可以访问到messageB,而message是访问不到的

//B组件
<template>
	<div class="main-panel">
      <p>A组件传给B组件的参数: {{message}}</p>
      <button @click="sendBData">和A交互</button>
      <C v-bind="$attrs" v-on="$listeners"></C>
	</div>
</template>

<script>
import C from '...C.vue'				
export default {
    props: {
        messsage: {
            type: String,
            default: ''
        } 
    },
    data () {
        return {
            b: 1
        }
    },
    components: {
        C
    },
    methods:{
        sendBData(){
            this.$emit("getBData", this.b++)
        }
    }    
}
</script>
//C组件
<template>
	<div class="main-panel">
      <p>A组件传给C组件的参数: {{$attrs.messageC}}</p>
      <button @click="sendCData">和A交互</button>
	</div>
</template>

<script>			
export default {
    data () {
        return {
            c: '我是C组件'
        }
    },
    components: {
        C
    },
    methods:{
        sendCData(){
            this.$emit("getCData", this.c)
        }
    }    
}
</script>

5、Vuex

Vuex是专为 Vue.js 应用程序开发的状态管理模式,收集管理应用的所有组件状态。解决了多个视图依赖同一状态和来自不同视图的行为更改同一个状态的问题

Vuex包含5大模块(state,getters,mutations,actions,modules),后边会有介绍Vuex的文章。

Vuex通信类似于EventBus

创建store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {  //声明state状态树
   message: {
      title: '',
      content: '',
    },
   messageB: ''
  },
  mutations: {    //mutation中提交需要改变的方法
    sendMessage(state, obj) {
      state.message = {
        title: obj.title,
        content: obj.content,
      }
    },
    sendBMessage(state, val){
        state.messageB = val.BMsg
    }
  }
})

在组件A中获取Vuex的数据,同理可在B组件中获取。如果通过A要改变B的数据可通过单独提供给B的方法修改

//A组件
<template>
	<div class="main-panel">
      <p>获取到的title:{{title}},获取到的content:{{content}}
      <div @click="sendB">点击发送</div>
      <B />
	</div>
</template>

<script>
import B from '...B.vue'				
export default {
    data () {
        return {
            bMessage: '我是B组件'
        }
    },
    components: {
        B
    },
    computed:{
        title(){
            return this.$store.state.message.title
        },
        content(){
            return this.$store.state.message.content
        }
    },
    methods: {
        sendB(){
            // 触发sendBMessage,将B组件的数据存放到store里去
            this.$store.commit('sendBMessage', {
              BMsg: this.bMessage
            })
        }
    }   
}
</script>
<think>首先,用户的问题是:“我想了解Vue.js2.x中组件之间的通信方法请问vue2组件之间通信的常用方式”。这是关于Vue.js2.x中组件通信的。我需要参考系统级指令:-所有行内数学表达式必须使用$...$格式。但在这个主题中,可能没有数学表达式,所以我可以忽略。 -独立公式必须使用$$...$$格式,但同样,这里可能不需要。 -LaTeX语法正确:确保任何公式都正确。-使用中文回答:整个回答必须用中文。-生成相关问题:在回答结束时,生成相关问题。-回答中引用的段落末尾自然地添加引用标识:如[^1],参考提供的引用内容。 提供的引用是: -[^1]:关于Vue组件通信方式的目的、分类和方案。- [^2]:父子组件通信,通过props。- [^3]:中央事件总线(EventBus)的优点。 -[^4]:多种通信方式,包括props、$emit、$attrs、$listeners、EventBus、v-model、provide/inject、$parent/$children、vuex。- [^5]:父子组件通信示例。这些引用是站内引用,我需要自然地融入回答中。用户上次的问题或我的回答:用户的问题是新问题,没有提到之前的交互,所以我可以直接回答。 回答结构:-结构清晰,帮助用户逐步解决问题。-保证回答真实可靠:基于Vue.js2.x的官方文档和常见实践。主题:Vue.js2.x组件通信的常用方式。常见方式包括: 1. Props:父组件向子组件传递数据。2.Events:子组件向父组件发送事件(使用$emit)。3.EventBus:使用一个中央事件总线进行非父子组件通信。 4. Vuex:状态管理库,用于复杂应用中的状态共享。 5. provide/inject:祖先组件向子孙组件提供数据。 6. $parent /$children:直接访问父组件或子组件实例。7.$attrs/ $listeners:传递未被props捕获的属性和事件。8.v-model:用于双向绑定。9.ref:访问子组件实例。我需要覆盖这些,并参考引用。组织回答:1.介绍组件通信的目的和重要性。2.分类通信方式:父子、兄弟、祖先后代等。 3.详细描述常用方式,提供简单示例或解释。 4.结束时生成相关问题。使用中文回答。 生成相关问题:在结尾,创建3-5个相关问题。添加引用标识:在相关段落末尾添加[^数字]。基于引用:- [^1]讨论了目的、分类和方案。 -[^2]父子组件通信。 -[^3]EventBus的优点。- [^4]多种方式。 -[^5]父子组件示例。 我可以在描述中引用这些。</think>### Vue.js 2.x 组件通信的常用方式Vue.js 2.x 中,组件通信是构建复杂应用的核心问题。组件通信的目的是实现数据共享和交互逻辑的解耦,确保不同组件能高效协作[^1]。根据组件关系(如父子、兄弟、祖先后代),通信方式可分为三类:**父子组件通信**、**非父子组件通信**(如兄弟组件)和**跨层级组件通信**。以下详细介绍 Vue.js 2.x 中最常用的通信方式,基于官方文档和最佳实践,确保回答真实可靠。 #### 1. **父子组件通信** 父子通信是最常见的场景,通常通过 props 和事件机制实现。 - **Props(父组件向子组件传递数据)**:父组件通过属性绑定将数据传递给子组件,子组件通过 `props` 选项接收。这种方式是单向数据流,确保数据可预测性。 - 示例:父组件使用 `:title="myTitle"` 传递数据,子组件在 `props` 中声明 `title` 接收[^2][^5]。 - **`$emit`(子组件向父组件触发事件)**:子组件通过 `this.$emit('event-name', data)` 触发自定义事件,父组件使用 `v-on` 监听并处理。这适用于子组件需要更新父组件状态时。 - 示例:子组件输入框变化时触发 `@input="passData"`,父组件监听 `@getChildData` 执行逻辑[^4][^5]。 - **`ref`(访问子组件实例)**:父组件通过 `ref` 属性直接访问子组件的实例或方法,适合需要操作子组件 DOM 或调用其方法的情况。 - 示例:父组件使用 `<child ref="childRef"></child>`,然后通过 `this.$refs.childRef.methodName()` 调用。 #### 2. **非父子组件通信** 当组件间无直接父子关系(如兄弟组件)时,常用事件总线或状态管理。 - **EventBus(中央事件总线)**:创建一个全局事件中心(通常是一个 Vue 实例),组件通过 `$emit` 触发事件和 `$on` 监听事件。优点包括解耦合、灵活性高和简单易用[^3]。 - 示例:创建 `eventBus.js` 文件: ```javascript // eventBus.js import Vue from 'vue'; export const eventBus = new Vue(); ``` 组件 A 触发事件:`eventBus.$emit('update-data', data)` 组件 B 监听事件:`eventBus.$on('update-data', callback)` - **Vuex(状态管理库)**:适用于大型应用,通过集中式状态管理实现全局数据共享。组件通过 `mapState`、`mapActions` 等访问或修改状态。Vuex 解决了跨组件状态同步问题[^4]。 #### 3. **跨层级组件通信** 对于深层嵌套的组件(如祖先后代),推荐使用以下方式: - **`provide` 和 `inject`**:祖先组件通过 `provide` 提供数据,后代组件通过 `inject` 注入数据。这避免了逐层传递 props 的繁琐。 - 示例:祖先组件 `provide: { theme: 'dark' }`,后代组件 `inject: ['theme']` 直接使用[^4]。 - **`$attrs` 和 `$listeners`**:用于传递未被 props 捕获的属性和事件。父组件通过 `v-bind="$attrs"` 和 `v-on="$listeners"` 向下传递,适合创建高阶组件[^4]。 #### 4. **其他辅助方式** - **`$parent` 和 `$children`**:直接访问父组件或子组件实例(例如 `this.$parent.methodName()`)。但需谨慎使用,因为它增加了耦合度,不利于维护[^4]。 - **`v-model`**:实现表单元素的双向绑定,本质上是 `value` prop 和 `input` 事件的语法糖,常用于父子通信场景[^4]。 ### 小结 Vue.js 2.x 的组件通信方案多样,选择取决于组件关系和复杂度: - 简单父子交互:优先使用 **props + `$emit`**。 - 非父子通信:考虑 **EventBus** 或 **Vuex**。 - 跨层级:使用 **`provide/inject`** 或 **`$attrs/$listeners`**。 在实际开发中,推荐优先使用声明式方法(如 props/events)以保持代码清晰,复杂场景再引入 Vuex 或 EventBus 来解耦[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值