摘要:當(dāng)一個組件沒有聲明任何時,這里會包含所有父作用域的綁定和除外,并且可以通過傳入內(nèi)部組件在創(chuàng)建高級別的組件時非常有用。
寫在前面
組件間的通信是是實際開發(fā)中非常常用的一環(huán),如何使用對項目整體設(shè)計、開發(fā)、規(guī)范都有很實際的的作用,我在項目開發(fā)中對此深有體會,總結(jié)下vue組件間通信的幾種方式,討論下各自的使用場景
文章對相關(guān)場景預(yù)覽
父->子組件間的數(shù)據(jù)傳遞
子->父組件間的數(shù)據(jù)傳遞
兄弟組件間的數(shù)據(jù)傳遞
組件深層嵌套,祖先組件與子組件間的數(shù)據(jù)傳遞
文章相關(guān)技術(shù)預(yù)覽
prop、emit、bus、vuex、路由URL、provide/inject、$attrs/inheritAttrs
注:以下介紹與代碼環(huán)境:vue2.0+、vue-cli2
父->子組件間的數(shù)據(jù)傳遞父子組件的通信是開發(fā)是最常用的也是最重要的,你們一定知道父子通信是用prop傳遞數(shù)據(jù)的,像這樣:
//父組件,傳遞數(shù)據(jù)
//子組件,接受數(shù)據(jù),定義傳遞數(shù)據(jù)的類型type與默認值default props: { inputIndex: { type: Object, default: function(){ return {} } }, inputName: { type: String, default: "" },
注意項:
父組件傳遞數(shù)據(jù)時類似在標簽中寫了一個屬性,如果是傳遞的數(shù)據(jù)是data中的自然是要在傳遞屬性前加v-bind:,如果傳遞的是一個已知的固定值呢
字符串是靜態(tài)的可直接傳入無需在屬性前加v-bind
數(shù)字,布爾,對象,數(shù)組,因為這些是js表達式而不是字符串,所以即使這些傳遞的是靜態(tài)的也需要加v-bind,把數(shù)據(jù)放到data中引用,
如果prop傳到子組件中的數(shù)據(jù)是一個對象的話,要注意傳遞的是一個對象引用,雖然父子組件看似是分離的但最后都是在同一對象下
如果prop傳到子組件的值只是作為初始值使用,且在父組件中不會變化賦值到data中使用
如果傳到子組件的prop的數(shù)據(jù)在父組件會被改變的,放到計算屬性中監(jiān)聽變化使用。因為如果傳遞的是個對象的話,只改變下面的某個屬性子組件中是不會響應(yīng)式更新的,如果子組件需要在數(shù)據(jù)變化時響應(yīng)式更新那只能放到computed中或者用watch深拷貝deep:true才能監(jiān)聽到變化
當(dāng)然如果你又需要在子組件中通過prop傳遞數(shù)據(jù)的變化做些操作,那么寫在computed中會報警告,因為計算屬性中不推薦有任何數(shù)據(jù)的改變,最好只進行計算。如果你非要進行數(shù)據(jù)的操作那么可以把監(jiān)聽寫在watch(注意deep深拷貝)或者使用computed的get和set如下圖:
但問題又來了,如果你傳進來的是個對象,同時你又需要在子組件中操作傳進來的這個數(shù)據(jù),那么在父組件中的這個數(shù)據(jù)也會改變,因為你傳遞的只是個引用, 即使你把prop的數(shù)據(jù)復(fù)制到data中也是一樣的,無論如何賦值都是引用的賦值,你只能對對象做深拷貝創(chuàng)建一個副本才能繼續(xù)操作,你可以用JSON的方法先轉(zhuǎn)化字符串在轉(zhuǎn)成對象更方便一點,
所以在父子傳遞數(shù)據(jù)時要先考慮好數(shù)據(jù)要如何使用,否則你會遇到很多問題或子組件中修改了父組件中的數(shù)據(jù),這是很隱蔽并且很危險的
子->父組件間的數(shù)據(jù)傳遞在vue中子向父傳遞數(shù)據(jù)一般用$emit自定義事件,在父組件中監(jiān)聽這個事件并在回調(diào)中寫相關(guān)邏輯
// 父組件監(jiān)聽子組件定義的事件
// 子組件需要返回數(shù)據(jù)時執(zhí)行,并可以傳遞數(shù)據(jù) this.$emit("editorEmit", data)
那么問題來了,我是不是真的有必要去向父組件返回這個數(shù)據(jù),用自定義事件可以在當(dāng)子組件想傳遞數(shù)據(jù)或向子組件傳遞的數(shù)據(jù)有變化需要重新傳遞時執(zhí)行,那么另外一種場景,父組件需要子組件的一個數(shù)據(jù)但子組件并不知道或者說沒有能力在父組件想要的時候給父組件,那么這個時候就要用到組件的一個選項ref:
父組件在標簽中定義ref屬性,在js中直接調(diào)用this.$refs.editor就是調(diào)用整個子組件,子組件的所有內(nèi)容都能通過ref去調(diào)用,當(dāng)然我們并不推薦因為這會使數(shù)據(jù)看起來非?;靵y,
所以我們可以在子組件中定義一種專供父組件調(diào)用的函數(shù),,比如我們在這個函數(shù)中返回子組件data中某個數(shù)據(jù),當(dāng)父組件想要獲取這個數(shù)據(jù)就直接主動調(diào)用ref執(zhí)行這個函數(shù)獲取這個數(shù)據(jù),這樣能適應(yīng)很大一部分場景,邏輯也更清晰一點
另外,父向子傳遞數(shù)據(jù)也可以用ref,有次需要在一個父組件中大量調(diào)用同一個子組件,而每次調(diào)用傳遞的prop數(shù)據(jù)都不同,并且傳遞數(shù)據(jù)會根據(jù)之后操作變化,這樣我需要在data中定義大量相關(guān)數(shù)據(jù)并改變它,我可以直接用ref調(diào)用子組件函數(shù)直接把數(shù)據(jù)以參數(shù)的形式傳給子組件,邏輯一下子清晰了
如果調(diào)用基礎(chǔ)組件可以在父組件中調(diào)用ref執(zhí)行基礎(chǔ)組件中暴露的各種功能接口,比如顯示,消失等
兄弟組件間的數(shù)據(jù)傳遞vue中兄弟組件間的通信是很不方便的,或者說不支持的,那么父子組件中都有什么通信方式呢
路由URL參數(shù)
在傳統(tǒng)開發(fā)時我們常常把需要跨頁面?zhèn)鬟f的數(shù)據(jù)放到url后面,跳轉(zhuǎn)到另外頁面時直接獲取url字符串獲取想要的參數(shù)即可,在vue跨組件時一樣可以這么做,
// router index.js 動態(tài)路由 { path:"/params/:Id", component:Params, name:Params }
// 跳轉(zhuǎn)路由跳轉(zhuǎn)路由
在跳轉(zhuǎn)后的組件中用$route.params.id去獲取到這個id參數(shù)為12,但這種只適合傳遞比較小的數(shù)據(jù),數(shù)字之類的
Bus通信
在組件之外定義一個bus.js作為組件間通信的橋梁,適用于比較小型不需要vuex又需要兄弟組件通信的
bus.js中添加如下
import Vue from "vue" export default new Vue
組件中調(diào)用bus.js通過自定義事件傳遞數(shù)據(jù)
import Bus from "./bus.js" export default { methods: { bus () { Bus.$emit("msg", "我要傳給兄弟組件們") } } }
兄弟組件中監(jiān)聽事件接受數(shù)據(jù)
import Bus from "./bus.js" export default { mounted() { Bus.$on("msg", (e) => { console.log(e) }) } }
注:以上兩種使用場景并不高所以只是簡略提一下,這兩點都是很久以前寫過,以上例子網(wǎng)上直接搜集而來如有錯誤,指正
Vuex集中狀態(tài)管理
vuex是vue的集中狀態(tài)管理工具,對于大型應(yīng)用統(tǒng)一集中管理數(shù)據(jù),很方便,在此對vuex的用法并不過多介紹只是提一下使用過程中遇到的問題
規(guī)范:對于多人開發(fā)的大型應(yīng)用規(guī)范的制定是至關(guān)重要的,對于所有人都會接觸到的vuex對其修改數(shù)據(jù)調(diào)用數(shù)據(jù)都應(yīng)有一個明確嚴格的使用規(guī)范
vuex分模塊:項目不同模塊間維護各自的vuex數(shù)據(jù)
限制調(diào)用:只允許action操作數(shù)據(jù),getters獲取數(shù)據(jù),使用mapGetters,mapActions輔助函數(shù)調(diào)用數(shù)據(jù)
對于vuex的使用場景也有一些爭論,有人認為正常組件之間就是要用父子組件傳值的方式,即使子組件需要使vuex中的數(shù)據(jù)也應(yīng)該由父組件獲取再傳到子組件中,但有的時候組件間嵌套很深,只允許父組件獲取數(shù)據(jù)并不是一個方便的方法,所以對于祖先元組件與子組件傳值又有了新問題,vue官網(wǎng)也有一些方法解決,如下
祖先組件與子組件間的數(shù)據(jù)傳遞provide/inject
除了正常的父子組件傳值外,vue也提供了provide/inject
這對選項需要一起使用,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時間里始終生效
官網(wǎng)實例
// 父級組件提供 "foo" var Provider = { provide: { foo: "bar" }, // ... } // 子組件注入 "foo" var Child = { inject: ["foo"], created () { console.log(this.foo) // => "bar" } }
provide 選項應(yīng)該是一個對象或返回一個對象的函數(shù)。該對象包含可注入其子孫的屬性。
一個字符串?dāng)?shù)組,或
一個對象,對象的 key 是本地的綁定名,value 是:
在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol),或
一個對象,該對象的:
from 屬性是在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol)
default 屬性是降級情況下使用的 value
提示:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個可監(jiān)聽的對象,那么其對象的屬性還是可響應(yīng)的。
具體細節(jié)移步vue相關(guān)介紹https://cn.vuejs.org/v2/api/#...
provide/inject還未在項目中應(yīng)用過,后面會做嘗試
補充 $attrs/inheritAttrs經(jīng)小伙伴們提醒補充$attrs的使用
場景:祖先組件與子組件傳值
如果是props的話,就必須在子組件與祖先組件之間每個組件都要prop接受這個數(shù)據(jù),再傳到下一層子組件,這就很麻煩,耦合深程序臃腫
如果用vuex確實顯得有點小題大做了,所以用$attrs直接去獲取祖先數(shù)據(jù)也不錯
包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。當(dāng)一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級別的組件時非常有用。
以上是官網(wǎng)對$attrs的解釋,我剛看我也是一臉懵逼,回去試了一下其實并不難,而且比較適用組件深層嵌套場景下,祖先組件向子組件傳值的問題
意思就是父組件傳向子組件傳的,子組件不prop接受的數(shù)據(jù)都會放在$attrs中,子組件直接用this.$attrs獲取就可以了。如過從父->孫傳,就在子組件中添加v-bind="$attrs",就把父組件傳來的子組件沒props接收的數(shù)據(jù)全部傳到孫組件,具體看以下代碼
使用:
祖先組件
// 祖先組件 // 在祖先組件中直接傳入output和input
子組件
{{input}}
孫組件
{{$attrs.output.name}}
看起來還是挺好用的,還沒在具體項目中用過,相信不久會用到的,如果還有什么問題歡迎留言
$children/$parent
當(dāng)然你可以直接用$children/$parent獲取當(dāng)前組件的子組件實例或父組件實例(如果有的話),也能對其做些操作,不過并不推薦這么做
你還可以放到localStorage,sessionStorage,cooikes之類的存在本地當(dāng)然也能做到組件間的通信
文章只是整理一下筆記,談一談遇到的問題和經(jīng)驗,并沒有嚴謹?shù)拇朕o和詳細的過程,如有錯誤望指正
原創(chuàng)文章轉(zhuǎn)載引用請注明原文鏈接http://blog.wwenj.com/index.p...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/98231.html
摘要:本文總結(jié)了組件間通信的幾種方式,如和,以通俗易懂的實例講述這其中的差別及使用場景,希望對小伙伴有些許幫助。狀態(tài)改變提交操作方法。 前言 組件是 vue.js最強大的功能之一,而組件實例的作用域是相互獨立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引用。一般來說,組件可以有以下幾種關(guān)系:showImg(https://segmentfault.com/img/remote/146000001...
摘要:本文總結(jié)了組件間通信的幾種方式,如和,以通俗易懂的實例講述這其中的差別及使用場景,希望對小伙伴有些許幫助。狀態(tài)改變提交操作方法。前言 組件是 vue.js最強大的功能之一,而組件實例的作用域是相互獨立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引用。一般來說,組件可以有以下幾種關(guān)系: showImg(https://user-gold-cdn.xitu.io/2019/5/17/16ac35bf...
摘要:上圖是二月份前端框架排名,位居第一,排名第三。我們認為前端模板和組件代碼是緊密相連的。直到最近看了文檔,才發(fā)現(xiàn)另有蹊蹺。 歡迎大家關(guān)注騰訊云技術(shù)社區(qū)-segmentfault官方主頁,我們將持續(xù)在博客園為大家推薦技術(shù)精品文章哦~ 紀俊,從事Web前端開發(fā)工作,2016年加入騰訊OMG廣告平臺產(chǎn)品部,喜歡研究前端技術(shù)框架。 這里要討論的話題,不是前端框架哪家強,因為在 Vue 官網(wǎng)就已經(jīng)...
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個網(wǎng)址:http://www.kancloud.cn/jsfron... 03月份前端資源分享 1. Javascript 175453545 Redux compose and middleware 源碼分析 深入 Promise(二)——進擊的 Promise Effective JavaScript leeheys blog -...
平日學(xué)習(xí)接觸過的網(wǎng)站積累,以每月的形式發(fā)布。2017年以前看這個網(wǎng)址:http://www.kancloud.cn/jsfron... 03月份前端資源分享 1. Javascript 175453545 Redux compose and middleware 源碼分析 深入 Promise(二)——進擊的 Promise Effective JavaScript leeheys blog -...
閱讀 1929·2021-09-14 18:03
閱讀 2325·2019-08-30 15:48
閱讀 1195·2019-08-30 14:09
閱讀 579·2019-08-30 12:55
閱讀 2795·2019-08-29 11:29
閱讀 1549·2019-08-26 13:43
閱讀 2371·2019-08-26 13:30
閱讀 2434·2019-08-26 12:17