您好,登錄后才能下訂單哦!
Vue如何在不同場景下實(shí)現(xiàn)組件間的數(shù)據(jù)交流?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
父子組件間的數(shù)據(jù)交流
父子組件間的數(shù)據(jù)交流可分為兩種:
1.父組件傳遞數(shù)據(jù)給子組件
2.子組件傳遞數(shù)據(jù)給父組件
父組件傳遞數(shù)據(jù)給子組件——props
這是組件數(shù)據(jù)溝通中最常見的場景:你讓父組件掌握了數(shù)據(jù)源,然后傳遞給子組件,供子組件使用
許多人會說,這很簡單!用props嘛! 對,正因如此,它不是我要講的主要內(nèi)容,不過我們還是用代碼簡單過一遍:
父組件
<template> <div id="father"> {{ '我是父組件' }} <son :text = "text"></son> </div> </template> <script> import son from './son.vue' export default { data: function () { return { text: '從父組件傳來的數(shù)據(jù)' } }, components: { son: son } } </script> <style scoped> </style>
子組件:
<template> <div> {{ '我是子組件,我接收了' + text }} </div> </template> <script> export default { props: { text: { type: String, default: '' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
demo:
在這個(gè)demo里面,我們把“從父組件傳來的數(shù)據(jù)”這一個(gè)字符串通過props傳遞給了子組件
如果我們希望在子組件中改變父組件的數(shù)據(jù)的話,可以在父組件中定義一個(gè)能改變父組件數(shù)據(jù)的函數(shù),然后通過props將該函數(shù)傳遞給子組件,并在子組件在適當(dāng)時(shí)機(jī)調(diào)用該函數(shù)——從而起到在子組件中改變父組件數(shù)據(jù)的效果
子組件傳遞數(shù)據(jù)給父組件
子組件傳遞數(shù)據(jù)給父組件 方式一:回調(diào)傳參
父組件:
<template> <div id="father"> {{ '我是父組件,名稱是' + componentName }} <son :changeComponentName = "changeComponentName"></son> </div> </template> <script> import son from './son.vue' export default { data: function () { return { componentName: '組件A' } }, methods: { changeComponentName: function (newComponentName) { this.componentName = newComponentName } }, components: { son: son } } </script> <style scoped> #father div{ padding: 10px; margin: 10px; border: 1px solid gray; } </style>
子組件:
<template> <div> <p>我是子組件:一個(gè)button</p> <button @click="() => changeComponentName(newComponentName)"> 把父組件的名稱修改為:彭湖灣的組件 </button> </div> </template> <script> export default { data: function () { return { newComponentName: '彭湖灣的組件' } }, props: { changeComponentName: { type: Function, default: () => { } } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
demo:
點(diǎn)擊前:
點(diǎn)擊后:
圖解:
點(diǎn)擊子組件(按鈕)的時(shí)候,將父組件的名稱從“A”修改為“彭湖灣的組件”
我們從父組件向子組件傳遞了一個(gè)函數(shù)(changeComponentName)。并在子組件調(diào)用這個(gè)函數(shù)的時(shí)候,以參數(shù)的形式傳遞了一個(gè)子組件內(nèi)部的數(shù)據(jù)(newComponentName)給這個(gè)函數(shù),這樣,在父組件中定義的函數(shù)(changeComponentName)就可以取得子組件傳來的參數(shù)了
【PS】 命名太長不好意思
子組件傳遞數(shù)據(jù)給父組件 方式二:自定義事件
父組件:
<template> <div id="father"> <div> {{ '我是父組件,我的名稱是:' + fatherComponentName }} <son v-on:changeComponentName = "changeComponentName"></son> </div> </div> </template> <script> import son from './son.vue' export default { data: function () { return { fatherComponentName: 'A組件' } }, methods: { changeComponentName: function (componentName) { this.fatherComponentName = componentName } }, components: { son: son } } </script> <style scoped> #father div{ padding: 10px; margin: 10px; border:1px solid grey; } </style>
子組件:
<template> <div> <p>我是子組件:一個(gè)按鈕</p> <button @click="clickCallback"> 修改父組件的名稱為:彭湖灣的組件 </button> </div> </template> <script> export default { data: function () { return { fatherComponentName: '彭湖灣的組件' } }, methods: { clickCallback: function () { this.$emit('changeComponentName', this.fatherComponentName) } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
demo:
點(diǎn)擊前:
點(diǎn)擊后:
圖解:
通過$emit(event, [...參數(shù)]),所有的參數(shù)將被傳遞給監(jiān)聽器回調(diào),也就是我們在父組件中定義的changeComponentName方法,從而實(shí)現(xiàn)從子組件中給父組件傳參
兄弟組件間的數(shù)據(jù)交流(有共同父組件的兄弟組件)
父組件:
<template> <div id="father"> <div> {{ '我是父組件:father' }} <eldest-son :text = "text"></eldest-son> <youngest-son :changeText="changeText"></youngest-son> </div> </div> </template> <script> import eldestSon from './eldestSon.vue' import youngestSon from './youngestSon.vue' export default { data: function () { return { text: '我是一行文本' } }, methods: { changeText: function () { this.text = '我是經(jīng)過改動的一行文本' } }, components: { eldestSon: eldestSon, youngestSon: youngestSon } } </script> <style> #father div{ border: 1px solid grey; padding: 10px; margin: 10px; } </style>
兄弟組件1:
<template> <div> <p>我是兄弟組件:eldestSon</p> <p>我有一個(gè)可變數(shù)據(jù)text:{{ text }}</p> </div> </template> <script> export default { props: { text: { type: String, default: '' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
兄弟組件2:
<template> <div> <p>我是兄弟組件:youngestSon</p> <button @click="changeText">更改eldestSon兄弟組件中的文本</button> </div> </template> <script> export default { props: { changeText: { type: Function, default: () => {} } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
點(diǎn)擊前:
點(diǎn)擊后:
圖解:
如果兩個(gè)兄弟組件間存在這種數(shù)據(jù)關(guān)系的話,我們可以嘗試尋找其共同的父組件,使數(shù)據(jù)和相關(guān)方法“提升”到父組件內(nèi)部,并向下傳給兩個(gè)子組件
這樣,其中一個(gè)子組件取得了數(shù)據(jù),另外一個(gè)子組件取得了改變數(shù)據(jù)的方法,便可以實(shí)現(xiàn)上述的數(shù)據(jù)溝通
【注意】這種場景存在局限性,它要求兩個(gè)組件有共同父組件。對于這種場景之外的處理方法,請看下文
全局組件間的數(shù)據(jù)交流——Vuex
我上述的許多場景里面,都運(yùn)用到了props或者函數(shù)傳參的方式去處理組件間的數(shù)據(jù)溝通。然而在稍大型的應(yīng)用里面,它們都不約而同地給我們帶來了很大的麻煩
例如:
1.通過props從父組件向子組件傳遞數(shù)據(jù)
對于直接的父子關(guān)系的組件,數(shù)據(jù)流顯得很簡潔明確,但在大型應(yīng)用里面,我們上下嵌套許多個(gè)組件的時(shí)候,這就會導(dǎo)致我們的代碼非常地繁瑣,并難以維護(hù)
2.對于沒有共同的父組件的兄弟組件,函數(shù)傳參的數(shù)據(jù)傳遞方式也無能為力了,Vue文檔里介紹到,你可以通過以$emit和$on函數(shù)為基礎(chǔ)的“事件總線”溝通數(shù)據(jù),但它無法應(yīng)對更加大型的應(yīng)用
這個(gè)時(shí)候Vuex就成為了實(shí)現(xiàn)全局組件間數(shù)據(jù)交流的最佳方案了
Vuex擁有一個(gè)包含全部頂層狀態(tài)的單一數(shù)據(jù)源(state)
1.所有的組件都可以使用這個(gè)單一數(shù)據(jù)源里面的數(shù)據(jù)
2.所有的組件都可以通過派發(fā) 動作(actions)修改這個(gè)單一數(shù)據(jù)源里的數(shù)據(jù)
原本要“走很多彎路”才能實(shí)現(xiàn)溝通的數(shù)據(jù)流,一下子就找到了最短的捷徑
實(shí)現(xiàn)View層的數(shù)據(jù)和model層的解耦
在1,2小節(jié)中處理的數(shù)據(jù)(Vue)和第三小節(jié)中處理的數(shù)據(jù)(Vuex),在很多時(shí)候是兩種不同類型的數(shù)據(jù),前者是屬于View層,僅負(fù)責(zé)單純的UI展示,而model層的大多是從后端取得后注入的數(shù)據(jù)。
一點(diǎn)建議:
1.Vue部分的代碼負(fù)責(zé)構(gòu)建View層
2.Vuex部分的代碼負(fù)責(zé)構(gòu)建model層
(上述的Vue指的是Vuex之外的框架體系)
以上述兩點(diǎn)為基礎(chǔ),決定某部分的代碼到底要寫進(jìn)Vue里面還是寫進(jìn)Vuex里面,并盡量將兩者分開,從而實(shí)現(xiàn)View層和model層的解耦,提高前端代碼的可維護(hù)性和擴(kuò)展性
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。