日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

【Vue.js】vue2组件间通信方式总结

發(fā)布時(shí)間:2025/3/20 vue 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Vue.js】vue2组件间通信方式总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

一.props傳參

1.父組件 ==> 子組件

2.子組件 ==> 父組件

二.組件的自定義事件

三.全局事件總線?

四.消息訂閱和發(fā)布?

五.vuex

六.插槽

1.默認(rèn)插槽

2.具名插槽

3.作用域插槽

七.v-model

八.sync修飾符?

九.$attrs和$listeners屬性

十.$children和$parent屬性


? ? vue項(xiàng)目中大量采用組件化開(kāi)發(fā),組件之間的通信傳遞數(shù)據(jù)是必不可少的一個(gè)環(huán)節(jié),并且隨著需求的不同,需要進(jìn)行不同關(guān)系的組件之間的值傳遞,從而出現(xiàn)各種組件通信的方式。

? ? 組件和組件之間的關(guān)系常見(jiàn)有父子組件,兄弟組件,兩類(lèi)關(guān)系的組件通信適用的方法是不同的,方法使用的不當(dāng),極有可能事倍功半;最常見(jiàn)的父子組件通信方式有props傳參,常用的兄弟組件通信方式有自定義事件全局事件總線;較大型的項(xiàng)目,一般采用的是vuex統(tǒng)一管理數(shù)據(jù);此外,在一些組件庫(kù)中,也經(jīng)常會(huì)使用到其它幾種通信方式,比如element-ui中,當(dāng)你需要在一個(gè)el-table-column中插入一張圖片時(shí),就需要使用作用域插槽,將要展現(xiàn)的頁(yè)面結(jié)構(gòu)傳遞給子組件;再比如,在el-dialog彈出框組件中,會(huì)使用sync修飾符,獲取控制組件顯示或隱藏的標(biāo)志符等等。以下10種組件通信方式總結(jié)如下。

一.props傳參

適用于父子組件之間傳遞參數(shù)

? (1).父組件 ==> 子組件 通信

? (2).子組件 ==> 父組件 通信(要求父先給子一個(gè)函數(shù)

1.父組件 ==> 子組件

傳遞數(shù)據(jù):在子組件標(biāo)簽上寫(xiě)明傳遞的參數(shù)名=“參數(shù)”,若參數(shù)是js表達(dá)式,需要使用v-bind

<Demo :name="xxx"/>

接收數(shù)據(jù):在子組件內(nèi)部

1. 第一種方式(只接收)

props:['name']?

2. 第二種方式(限制類(lèi)型)

props:{name:String}

3. 第三種方式(限制類(lèi)型、限制必要性、指定默認(rèn)值):

props:{name:{type:String, //類(lèi)型???required:true, //必要性???default:'老王' //默認(rèn)值} }

2.子組件 ==> 父組件

? ?若使用props在父組件中獲取子組件的數(shù)據(jù):這里在父組件中將addTodo()方法傳遞給子組件

<template><div id="root"><MyHeader :addTodo="addTodo"/></div> </template><script>import MyHeader from './components/MyHeader'export default {name:'App',components:{MyHeader},data() {return {todos:[{id:'001',title:'xx',done:true},]}},methods: {//添加一個(gè)todoaddTodo(todoObj){this.todos.unshift(todoObj)},}} </script>

在子組件內(nèi)部獲取input輸入框的輸入后,將輸入信息封裝成一個(gè)對(duì)象todoObj,調(diào)用父組件傳來(lái)的addTodo()方法 ,以實(shí)參的形式將對(duì)象todoObj傳給父組件,實(shí)現(xiàn)子 --> 父?jìng)鲄?/p> <template><div class="todo-header"><input type="text" placeholder="請(qǐng)輸入你的任務(wù)名稱(chēng),按回車(chē)鍵確認(rèn)" v-model="title" @keyup.enter="add"/></div> </template><script>import {nanoid} from 'nanoid'export default {name:'MyHeader',//接收從App傳遞過(guò)來(lái)的addTodoprops:['addTodo'],data() {return {//收集用戶(hù)輸入的titletitle:''}},methods: {add(){//校驗(yàn)數(shù)據(jù)if(!this.title.trim()) return alert('輸入不能為空')//將用戶(hù)的輸入包裝成一個(gè)todo對(duì)象const todoObj = {id:nanoid(),title:this.title,done:false}//通知App組件去添加一個(gè)todo對(duì)象this.addTodo(todoObj)//清空輸入this.title = ''}},} </script>

props是只讀的,Vue底層會(huì)監(jiān)測(cè)你對(duì)props的修改,如果進(jìn)行了修改,就會(huì)發(fā)出警告,若業(yè)務(wù)需求確實(shí)需要修改,那么請(qǐng)復(fù)制props的內(nèi)容到data中一份,然后去修改data中的數(shù)據(jù)。

二.組件的自定義事件

1.是一種組件間的通信方式,適用于:子組件 => 父組件

2.使用場(chǎng)景:A是父組件,B是子組件,B想給A傳數(shù)據(jù),那么就要在A中給B綁定自定義事件。

3. 使用?

綁定事件:在父組件中使用@自定義事件名 ,不用寫(xiě)形參,事件回調(diào)的形參會(huì)自動(dòng)接收最組件傳遞的實(shí)參內(nèi)容

<template><Demo @xxx="test">或<Demo v-on:xxx="test"> </template><script>export default {methods:{test(事件參數(shù)1,...事件參數(shù)2-n){}}} </script>

或使用ref獲取子組件實(shí)例對(duì)象,調(diào)用組件實(shí)例.$on('事件名',回調(diào)函數(shù))用于監(jiān)聽(tīng)子組件中定義的xxx事件;

<template><Demo ref="demo"/></template><script>export defalut {mounted{this.$refs.demo.$on('xxx',this.test)},methods:{test(事件參數(shù)1,...事件參數(shù)2-n){}}}</script>

若想讓自定義事件只能觸發(fā)一次,可以使用once修飾符,或$once方法。

觸發(fā)事件:數(shù)據(jù)可以傳遞一個(gè)或多個(gè),多個(gè)數(shù)據(jù)可以傳遞多個(gè)實(shí)參(第二個(gè)參數(shù)開(kāi)始),或者寫(xiě)成一個(gè)對(duì)象

this.$emit('xxx',數(shù)據(jù));

解綁事件

this.$off('xxx'); // 解綁指定事件 this.$off(['a','b']); // 解綁多個(gè) this.$off(); // 解綁全部

注意:通過(guò)this.$refs.xxx.$on('aaa',回調(diào))綁定自定義事件時(shí),回調(diào)要么配置在methods中,要么用箭頭函數(shù),否則this指向會(huì)出問(wèn)題

銷(xiāo)毀了當(dāng)前的組件實(shí)例對(duì)象時(shí),其身上的所有自定義事件全部銷(xiāo)毀了;銷(xiāo)毀了vue實(shí)例時(shí),其所有的子組件全部銷(xiāo)毀了,子組件的自定義世事件也被銷(xiāo)毀了,但所有的原生事件不會(huì)銷(xiāo)毀

三.全局事件總線?

一種組件間通信的方式,適用于任意組件間通信

?安裝全局事件總線:

new Vue({......beforeCreate() {Vue.prototype.$bus = this //安裝全局事件總線,$bus就是當(dāng)前應(yīng)用的vm},...... })

由于vc.prototype.__ proto __ = vm.prototype,所以組件實(shí)例是可以訪問(wèn)到vue實(shí)例上的屬性的,可以訪問(wèn)到$bus

使用事件總線?

1. 接收數(shù)據(jù):A組件想接收數(shù)據(jù),則在A組件中給$bus綁定自定義事件,事件的回調(diào)留在A組件自身,事件的綁定一般在mounted鉤子中進(jìn)行,事件只需綁定一次即可,這和原生js中給DOM元素綁定事件的回調(diào)是一個(gè)道理。

methods(){demo(data){......} }, ...... mounted() {this.$bus.$on('xxxx',this.demo) }

2. 提供數(shù)據(jù)

this.$bus.$emit('xxxx',數(shù)據(jù))

最好在beforeDestroy鉤子中,用$off去解綁當(dāng)前組件所用到的事件。

四.消息訂閱和發(fā)布?

一種組件間通信的方式,適用于任意組件間通信;

訂閱方是數(shù)據(jù)的獲取方,而發(fā)布方是數(shù)據(jù)的提供方;

使用步驟:

? ?1. 安裝:pubsub:npm i pubsub-js

? ?2. 引入:import pubsub from 'pubsub-js'

? ?3. 接收數(shù)據(jù):A組件想接收數(shù)據(jù),則在A組件中訂閱消息,訂閱的回調(diào)留在A組件自身。

methods(){demo(data){......} } ...... mounted() {this.pid = pubsub.subscribe('xxx',this.demo) //訂閱消息 }

? 4.提供數(shù)據(jù):

pubsub.publish('xxx',數(shù)據(jù))

最好在beforeDestroy鉤子中,用PubSub.unsubscribe(pid)去取消訂閱。

五.vuex

1.概念

在Vue中實(shí)現(xiàn)集中式狀態(tài)(數(shù)據(jù))管理的一個(gè)Vue插件,對(duì)vue應(yīng)用中多個(gè)組件的共享狀態(tài)進(jìn)行集中式的管理(讀/寫(xiě)),也是一種組件間通信的方式,且適用于任意組件間通信。

2.使用場(chǎng)景

多個(gè)組件需要共享數(shù)據(jù)時(shí)

原理圖:vuex的核心主要是由Actions,Mutations和state三部分組成,vuex做的是狀態(tài)管理,實(shí)際上就是存放多個(gè)組件可以共享的數(shù)據(jù),這些數(shù)據(jù)存放在state中,一般存放的可以是服務(wù)器返回的信息。

在下圖中,Vue Components 就是vue組件,在組件中使用this.$store.dispatch('xxxAction')?調(diào)用某個(gè)action執(zhí)行,一般在action中請(qǐng)求服務(wù)器接口(Backend API),獲取請(qǐng)求得到的異步結(jié)果,但action無(wú)法直接操作state存放數(shù)據(jù),所以此時(shí)它會(huì)調(diào)用指定的mutation,在mutation的內(nèi)就可以操作state修改數(shù)據(jù),最后在各個(gè)組件內(nèi)使用this.$store.state.xxx 拿到state存放的狀態(tài);

當(dāng)然,如果沒(méi)有額外的業(yè)務(wù)邏輯需要處理,組件無(wú)需派發(fā)actions,可以在組件內(nèi)直接使用this.$store.commit('xxxmutation'),通知mutations修改狀態(tài)。


?

3.搭建vuex環(huán)境?

0. 安裝:npm i vuex

1. 創(chuàng)建文件:src/store/index.js

? ?必須得在store實(shí)例創(chuàng)建前使用Vuex插件,所以Vue.use(Vuex)必須寫(xiě)在index.js中,而不是main.js中。

//引入Vue核心庫(kù) import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //應(yīng)用Vuex插件 Vue.use(Vuex)//準(zhǔn)備actions對(duì)象——響應(yīng)組件中用戶(hù)的動(dòng)作 const actions = {} //準(zhǔn)備mutations對(duì)象——修改state中的數(shù)據(jù) const mutations = {} //準(zhǔn)備state對(duì)象——保存具體的數(shù)據(jù) const state = {} // 準(zhǔn)備getters 對(duì)state中的內(nèi)容做二次處理,類(lèi)似于計(jì)算屬性 const getters = {}//創(chuàng)建并暴露store export default new Vuex.Store({actions,mutations,state })

2. 在main.js中創(chuàng)建vm時(shí)傳入store配置項(xiàng)

//引入store import store from './store' ......//創(chuàng)建vm new Vue({el:'#app',render: h => h(App),store })

?這樣就可以在vue實(shí)例和組件實(shí)例中看到$store屬性了。

4.vuex的具體使用

1. 初始化數(shù)據(jù)、配置actions、配置mutations,操作文件store.js

//引入Vue核心庫(kù) import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //引用Vuex Vue.use(Vuex)const actions = {//響應(yīng)組件中加的動(dòng)作jia(context,value){// console.log('actions中的jia被調(diào)用了',miniStore,value)context.commit('JIA',value)},}const mutations = {//執(zhí)行加IA(state,value){// console.log('mutations中的JIA被調(diào)用了',state,value)state.sum += value} }//初始化數(shù)據(jù) const state = {sum:0 }//創(chuàng)建并暴露store export default new Vuex.Store({actions,mutations,state, })

2.組件中讀取vuex中的數(shù)據(jù):

$store.state.sum

3.組件中修改vuex中的數(shù)據(jù):

$store.dispatch('action中的方法名',數(shù)據(jù)) 或 $store.commit('mutations中的方法名',數(shù)據(jù))

備注:若沒(méi)有網(wǎng)絡(luò)請(qǐng)求或其他業(yè)務(wù)邏輯,組件中也可以越過(guò)actions,即不寫(xiě)dispatch,直接編寫(xiě)commit

action中的方法第一個(gè)參數(shù)context還包括dispatch屬性,即當(dāng)業(yè)務(wù)邏輯較多可以鏈?zhǔn)秸{(diào)用多個(gè)action方法處理一個(gè)業(yè)務(wù)?

const actions = {//響應(yīng)組件中加的動(dòng)作jia(context,value){// console.log('actions中的jia被調(diào)用了',miniStore,value)value = value + 1;context.dispatch('jia1',value)},jia1(context,value) {value = value * 2;context.dispatch('jia2',value);},jia2(context,value) {value = value * 3;context.commit('JIA',value);},}

六.插槽

作用:讓父組件可以向子組件指定位置插入html結(jié)構(gòu),也是一種組件間通信的方式,適用于

? ? ? ? ? ? 父組件 ===> 子組件 。

分類(lèi):默認(rèn)插槽、具名插槽、作用域插槽

使用方式:

1.默認(rèn)插槽

父組件中:

<Category><div>html結(jié)構(gòu)1</div> </Category>

子組件中:

<template><div><!-- 定義插槽 --><slot>插槽默認(rèn)內(nèi)容...</slot></div> </template>

2.具名插槽

?一個(gè)組件多個(gè)插槽,給每個(gè)插槽命名加以區(qū)分,子組件name屬性對(duì)應(yīng)父組件的slot屬性

父組件中:

<Category><template slot="center"><div>html結(jié)構(gòu)1</div></template><template v-slot:footer><div>html結(jié)構(gòu)2</div></template> </Category>

子組件中:

<template><div><!-- 定義插槽 --><slot name="center">插槽默認(rèn)內(nèi)容...</slot><slot name="footer">插槽默認(rèn)內(nèi)容...</slot></div></template>

3.作用域插槽

理解:數(shù)據(jù)在組件的自身,但根據(jù)數(shù)據(jù)生成的結(jié)構(gòu)需要組件的使用者來(lái)決定。(games數(shù)據(jù)在Category組件中,但使用數(shù)據(jù)所遍歷出來(lái)的結(jié)構(gòu)由App組件決定)
具體編碼:父組件通過(guò)scope屬性值獲取子組件的數(shù)據(jù),作用域插槽和具名插槽可以結(jié)合使用。

父組件中:

<Category><template scope="scopeData"><!-- 生成的是ul列表 --><ul><li v-for="g in scopeData.games" :key="g">{{g}}</li></ul></template> </Category><Category><template slot-scope="scopeData" slot="s1"><!-- 生成的是h4標(biāo)題 --><h4 v-for="g in scopeData.games" :key="g">{{g}}</h4></template> </Category>

子組件中:

<template><div><slot :games="games" name="s1"></slot></div> </template><script>export default {name:'Category',props:['title'],//數(shù)據(jù)在子組件自身data() {return {games:['紅色警戒','穿越火線','勁舞團(tuán)','超級(jí)瑪麗']}},} </script>

七.v-model

?v-model實(shí)現(xiàn)的是雙向數(shù)據(jù)綁定,常用于表單元素;但也可以用于自定義組件標(biāo)簽上,實(shí)現(xiàn)父子組件的通信,父子組件間的數(shù)據(jù)同步。

首先這里用v-bind和input事件實(shí)現(xiàn)一個(gè)v-model

</template><input type="text" :value="text" @input="text=$event.target.value"> </template><script>export default {data(){return{text:0}}, }

其能實(shí)現(xiàn)v-model一樣的效果,這里的value是input表單元素的屬性,@input是表單的輸入事件;如果一樣的寫(xiě)法,寫(xiě)在組件標(biāo)簽上那么value就是組件的props參數(shù),而@input則是自定義事件,若依舊i將@input作為原生的輸入事件需要添加事件修飾符,即@input.native

接下去創(chuàng)建一個(gè)Inputs組件,給其傳遞一個(gè)參數(shù)value,并給其綁定一個(gè)自定義事件input

</template><Inputs :value="text" @input="text=$event"/><Inputs v-model="text"/> </template><script>export default {data(){return{text:0}}, }

在組件內(nèi)部接收參數(shù)value,觸發(fā)自定義時(shí)間內(nèi)input,將表單的輸入內(nèi)容$event.target.value作為自定義事件的參數(shù)傳遞。

<template><div><span>input:</span><input type="text" :value="value" @input="$emit('input',$event.target.value)"></div> </template><script> export default {props:['value'] } </script>

其同樣可以實(shí)現(xiàn)上面一樣的雙向數(shù)據(jù)綁定的效果,并且使用v-model替換組件的:value和@input也是等價(jià)的。

八.sync修飾符?

可以實(shí)現(xiàn)父子組件數(shù)據(jù)的同步

<template><Money :money.sync="money"/><!--等價(jià)于 --><Money :money="money" @update:money="money=$event"> </template><script> import Money from './components/Money.vue' export default {data(){return {money:10000}},components:{Money} } </script>

:money.async代表父組件給子組件傳遞字符串props[money],給當(dāng)前子組件綁定一個(gè)自定義事件(update:money),子組件如下:

<template><div><span>花費(fèi)了100元</span><button @click="$emit('update:money',money-100)">花錢(qián)</button><span>還剩{{money}}元</span></div> </template><script> export default {props:['money'] } </script>

九.$attrs和$listeners屬性

$attrs是組件實(shí)例的一個(gè)屬性,可以獲取父組件傳遞過(guò)來(lái)的props數(shù)據(jù)

$listeners是組件實(shí)例的屬性,獲取父組件給子組件傳遞的自定義事件;

如果子組件通過(guò)props接收的屬性,在$attrs屬性當(dāng)中是獲取不到的;

console.log(this.$attrs):

console.log(this.$listeners)??

使用el-button封裝一個(gè)組件,使其具有提示功能

父組件:

<template><ElButton type="success" icon="el-icon-delete" size="mini" title="按鈕" @click="handler"/> </template> <script> import ElButton from './components/elButton.vue' export default {components:{ElButton},methods:{handler(){console.log('123')},} } </script>

子組件:可以采用type=”$attrs.type“ size="$attrs.size"......的寫(xiě)法,但像這樣過(guò)于繁瑣,如果傳遞的屬性名和綁定標(biāo)簽的屬性名是一致的,直接使用v-bind="$attrs"的形式,需要注意的是,不能寫(xiě)成:=''$attrs";

同理v-on不能用@進(jìn)行替換

<template><a :title="title"><el-button v-bind="$attrs" v-on="$listeners"></el-button></a> </template><script> export default {props:['title'],mounted(){console.log(this.$attrs);} } </script>

十.$children和$parent屬性

$children是組件實(shí)例的屬性,可以獲取到當(dāng)前組件的全部子組件,返回的是一個(gè)數(shù)組

$parent屬性獲取到某一組件的父組件,可以操作父組件的數(shù)據(jù)和方法

現(xiàn)在有如下示例:

?點(diǎn)擊父組件按鈕,父組件的存款要加100,同時(shí)子組件的存款要減100,父組件通過(guò)$children獲取子組件的實(shí)例,由于只存在一個(gè)子組件,所以$children的索引0就是子組件的實(shí)例,從而可以讓子組件的data中的money減少100。

<template><div><h2>爸爸有存款:{{money1}}</h2><button @click="borrowM(100)">找小明借錢(qián)100</button><Son/></div> </template><script> import Son from './components/Son.vue' export default {data(){return{money1:1000}},methods:{borrowM(money){this.money1 += money;this.$children[0].money -= money;},},components:{Son} }

如下,在子組件Son中,點(diǎn)擊按鈕,子組件中的存款減少50,同時(shí)父組件中的存款增加50,可以通過(guò)$parent獲取父組件,從而操作父組件的data中的屬性money1讓其增加50.?$parent返回的就是父組件實(shí)例對(duì)象。

<template><div><h3>兒子小明:現(xiàn)有存款:{{money}}</h3><button @click="giveMoney(50)">給爸爸50元</button></div> </template><script> export default {data(){return {money:1000}},methods:{giveMoney(money){this.money -= money;// 獲取到父組件,讓父組件的數(shù)據(jù)加50this.$parent.money1 += money;}} } </script>

總結(jié)

以上是生活随笔為你收集整理的【Vue.js】vue2组件间通信方式总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。