VUE前端工程化( 一)(掌握組件的多種通信及數(shù)據(jù)同步)

組件通信

父子組件通信
父傳子 props屬性
子傳父 $emit事件

這兩種官方文檔里有很詳細(xì)的介紹就不解釋了
還是舉個(gè)栗子:

//parent.vue父組件
<template>
    <div>
        parent: {{money}}
        <Son1 v-model="money"></Son1>
        <!-- <Son1 :value.sync = "money"></Son1> -->
        //兩種寫法都可以截碴,是語法躺捌显;.sync表示同步欢摄,如果只傳value 用v-model即可
        
    </div>
</template>

<script>
import Son1 from './Son1'
export default {
    components:{
        Son1
    },
    data(){
        return{
            money:100
        }
    }
}
</script>
//子組件SON
//單項(xiàng)數(shù)據(jù)流廊移,父給子綁定一個(gè)事件
<template>
    <div>
        son:{{value}}
        <button @click="change">點(diǎn)擊</button>
    </div>
    
</template>
<script>
export default {
    methods:{
        change(){
            this.$emit('input', this.value+100)
        }
    },
    props:{
        value:{
            type:Number,
            default:1
        }
    },
    data(){
        return{

        }
    }
}
</script>

多層級傳遞數(shù)據(jù)
$dispatch 和 $broadcast (Vue1中可以用來實(shí)現(xiàn)基于組件樹結(jié)構(gòu)的事件流通信扭粱,vue2中已經(jīng)被移除)

(父要傳到孫舵鳞;孫要傳到父;)
dispatch 是一個(gè)事件琢蛤,首先會在自己實(shí)例本身上觸發(fā)蜓堕,然后沿父鏈向上傳播抛虏。
broadcast 是一個(gè)事件,它向下傳播到當(dāng)前實(shí)例的所有后代套才。由于后代擴(kuò)展為多個(gè)子樹迂猴,事件傳播將會遵循許多不同的“路徑”。 除非回調(diào)返回 true背伴,否則在沿該路徑觸發(fā)偵聽器回調(diào)時(shí)沸毁,每個(gè)路徑的傳播將會停止。

//grandoon.vue組件
<template>
    <div>
        grandson:{{value}}
        <button @click="changeParent">修改parent</button>
    </div>
    
</template>
<script>
export default {
    methods:{
        changeParent(){
            // this.$parent.$emit('input',300)
            // this.$parent.$parent.$emit('input',300)
            this.$dispatch('input',300)
        }
    },
    props:{
        value:{
            type:Number
        }
    }
}
</script>
//dispatch實(shí)現(xiàn)
/**
 * Recursively propagate an event up the parent chain.
 * 遞歸地在父鏈上傳播事件挂据。
 * @param {String} event
 * @param {...*} additional arguments
 */
// $dispatch 方法是定義在 Vue 的 prototype 上的
// 接受一個(gè)字符串類型的事件名稱
Vue.prototype.$dispatch = function (event) {
 // 首先執(zhí)行 $emit 觸發(fā)事件,將返回值保存在 shouldPropagate 中
 var shouldPropagate = this.$emit.apply(this, arguments)
  
 // 如果首次執(zhí)行的 $emit 方法返回的值不是 true 就直接返回
 // 如果返回值不是 true 就說明組件邏輯不希望事件繼續(xù)往父組件進(jìn)行傳遞
 if (!shouldPropagate) return
  
 // 如果首次執(zhí)行 $emit 方法返回值是 true 就獲取當(dāng)前組件的 parent 組件實(shí)例
 var parent = this.$parent
  
 // 將函數(shù)接受的參數(shù)轉(zhuǎn)換成數(shù)組
 var args = toArray(arguments)
  
 // use object event to indicate non-source emit on parents
 // 根據(jù)傳入的事件名稱的參數(shù)組裝成 object
 args[0] = { name: event, source: this }
  
 // 循環(huán)知道組件的父組件
 while (parent) {
 // 在父組件中執(zhí)行 $emit 觸發(fā)事件
 shouldPropagate = parent.$emit.apply(parent, args)
  
 // 如果父組件 $emit 返回的是 true 就繼續(xù)遞歸祖父組件儿普,否則就停止循環(huán)
 parent = shouldPropagate ? parent.$parent : null
 }
  
 // 最后返回當(dāng)前組件實(shí)例
 return this
}

broadcast 實(shí)現(xiàn)
Vue.prototype.$broadcast = function (event) {
 // 獲取傳入事件的類型崎逃,判斷是否為字符串
 var isSource = typeof event === 'string'
  
 // 校正 event 的值,當(dāng)接受 event 的類型為字符串時(shí)就直接使用眉孩,如果不是字符串就使用 event 上的 name 屬性 
 event = isSource ? event : event.name
  
 // if no child has registered for this event,
 // then there's no need to broadcast.
 // 如果當(dāng)前組件的子組件沒有注冊該事件个绍,就直接返回,并不用 broadcast
 if (!this._eventsCount[event]) return
  
 // 獲取當(dāng)前組件的子組件
 var children = this.$children
  
 // 將函數(shù)接受的參數(shù)轉(zhuǎn)換成數(shù)組
 var args = toArray(arguments)
  
 // 如果傳入事件為字符串
 if (isSource) {
  // use object event to indicate non-source emit
  // on children
  // 根據(jù)傳入的事件名稱的參數(shù)組裝成 object
  args[0] = { name: event, source: this }
 }


組件傳值浪汪,尤其是祖孫組件有跨度的傳值巴柿。

現(xiàn)在我們來討論一種情況,A組件與C組件怎么通信死遭,我們有多少種解決方案广恢?

  1. 我們使用VueX來進(jìn)行數(shù)據(jù)管理,但是如果項(xiàng)目中多個(gè)組件共享狀態(tài)比較少呀潭,項(xiàng)目比較小钉迷,并且全局狀態(tài)比較少,那使用VueX來實(shí)現(xiàn)該功能,并沒有發(fā)揮出VueX的威力钠署。
  2. 使用B來做中轉(zhuǎn)站糠聪,當(dāng)A組件需要把信息傳給C組件時(shí),B接受A組件的信息谐鼎,然后利用屬性傳給C組件舰蟆,這是一種解決方案,但是如果嵌套的組件過多狸棍,會導(dǎo)致代碼繁瑣身害,代碼維護(hù)比較困難;如果C中狀態(tài)的改變需要傳遞給A, 使用事件系統(tǒng)一級級往上傳遞 。
  3. 自定義一個(gè)Vue 中央數(shù)據(jù)總線草戈,這個(gè)情況適合碰到組件跨級傳遞消息题造,但是使用VueX感覺又有點(diǎn)浪費(fèi)的項(xiàng)目中,但是缺點(diǎn)是猾瘸,碰到多人合作時(shí)界赔,代碼的維護(hù)性較低丢习,代碼可讀性低
attrslisteners

在vue2.4中,為了解決該需求淮悼,引入了attrs 和listeners 咐低, 新增了inheritAttrs 選項(xiàng)。

$attrs  (屬性集合)
$listeners (方法集合)
v-bind="$attrs", v-on="$listeners"

$attrs包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)
provide inject

1.provide就相當(dāng)于加強(qiáng)版父組件prop
2.inject就相當(dāng)于加強(qiáng)版子組件的props

因?yàn)橐陨蟽烧呖梢栽诟附M件與子組件袜腥、孫子組件见擦、曾孫子...組件數(shù)據(jù)交互,也就是說不僅限于prop的父子組件數(shù)據(jù)交互羹令,只要在上一層級的聲明的provide鲤屡,那么下一層級無論多深都能夠通過inject來訪問到provide的數(shù)據(jù)

//父組件
<template>
    <div class="test">
        <son prop="data"></son>
    </div>
</template>
 
<script>
export default {
    name: 'Test',
    provide: {
        name: 'Garrett'
    }

//孫組件  (父組件--子組件--根組件)
<template>
    <div>
        {{name}}
    </div>
</template>
 
<script>
export default {
    name: 'Grandson',
    inject: [name]
}
</script>

缺點(diǎn)
這么做也是有明顯的缺點(diǎn)的,在任意層級都能訪問導(dǎo)致數(shù)據(jù)追蹤比較困難福侈,不知道是哪一個(gè)層級聲明了這個(gè)或者不知道哪一層級或若干個(gè)層級使用了酒来,因此這個(gè)屬性通常并不建議使用能用vuex的使用vuex,不能用的多傳參幾層肪凛,但是在做組件庫開發(fā)時(shí)堰汉,不對vuex進(jìn)行依賴,且不知道用戶使用環(huán)境的情況下可以很好的使用

event bus

實(shí)現(xiàn)途徑是在要相互通信的兄弟組件之中伟墙,都引入一個(gè)新的vue實(shí)例翘鸭,然后通過分別調(diào)用這個(gè)實(shí)例的事件觸發(fā)和監(jiān)聽來實(shí)現(xiàn)通信和參數(shù)傳遞。

有了eventbus后

發(fā)送組件中
EventBus.$emit("hello", this.number);

接受組件中
EventBus.$on("hello", (number) = > { console.log(number) });

使用case

注意

  1. $bus.on應(yīng)該在created鉤子內(nèi)使用戳葵,如果在mounted使用就乓,有可能接收不到其他組件來自created鉤子內(nèi)發(fā)出的事件。
  2. 使用了bus.on拱烁,在beforeDestroy鉤子里應(yīng)該再使用bus.off解除档址,因?yàn)榻M件銷毀后,沒有必要把監(jiān)聽句柄存儲在vue-bus里了邻梆。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末守伸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子浦妄,更是在濱河造成了極大的恐慌尼摹,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂娄,死亡現(xiàn)場離奇詭異蠢涝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阅懦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門和二,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耳胎,你說我怎么就攤上這事惯吕√杷” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵废登,是天一觀的道長淹魄。 經(jīng)常有香客問我,道長堡距,這世上最難降的妖魔是什么甲锡? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮羽戒,結(jié)果婚禮上缤沦,老公的妹妹穿的比我還像新娘。我一直安慰自己易稠,他們只是感情好缸废,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缩多,像睡著了一般呆奕。 火紅的嫁衣襯著肌膚如雪养晋。 梳的紋絲不亂的頭發(fā)上衬吆,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音绳泉,去河邊找鬼逊抡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛零酪,可吹牛的內(nèi)容都是我干的冒嫡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼四苇,長吁一口氣:“原來是場噩夢啊……” “哼孝凌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起月腋,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蟀架,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后榆骚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體片拍,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年妓肢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捌省。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碉钠,死狀恐怖纲缓,靈堂內(nèi)的尸體忽然破棺而出卷拘,到底是詐尸還是另有隱情,我是刑警寧澤色徘,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布恭金,位于F島的核電站,受9級特大地震影響褂策,放射性物質(zhì)發(fā)生泄漏横腿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一斤寂、第九天 我趴在偏房一處隱蔽的房頂上張望耿焊。 院中可真熱鬧,春花似錦遍搞、人聲如沸罗侯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钩杰。三九已至,卻和暖如春诊县,著一層夾襖步出監(jiān)牢的瞬間讲弄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工依痊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留避除,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓胸嘁,卻偏偏與公主長得像瓶摆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子性宏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言 組件是 vue.js最強(qiáng)大的功能之一群井,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    用技術(shù)改變世界閱讀 2,152評論 1 3
  • vue是數(shù)據(jù)驅(qū)動(dòng)視圖更新的框架, 所以對于vue來說組件間的數(shù)據(jù)通信非常重要毫胜,那么組件之間如何進(jìn)行數(shù)據(jù)通信的呢书斜?首...
    云翼飛閱讀 540評論 0 0
  • 摘要: 總有一款合適的通信方式。 作者:浪里行舟 Fundebug經(jīng)授權(quán)轉(zhuǎn)載指蚁,版權(quán)歸原作者所有菩佑。 前言 組件是 v...
    Fundebug閱讀 15,571評論 3 57
  • 前言 組件是 vue.js最強(qiáng)大的功能之一,而組件實(shí)例的作用域是相互獨(dú)立的凝化,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    浪里行舟閱讀 8,221評論 0 49
  • 前言 組件是 vue.js最強(qiáng)大的功能之一稍坯,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    7abbcd54a89d閱讀 707評論 0 1