成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Vue.js 父子組件通信的十種方式

網(wǎng)絡(luò) 通信技術(shù)
無可否認,現(xiàn)在無論大廠還是小廠都已經(jīng)用上了 Vue.js 框架,簡單易上手不說,教程詳盡,社區(qū)活躍,第三方套件還多。

 [[266702]]

面試官:Vue 中父子組件通信有哪些方式?

自己先想一分鐘。

無可否認,現(xiàn)在無論大廠還是小廠都已經(jīng)用上了 Vue.js 框架,簡單易上手不說,教程詳盡,社區(qū)活躍,第三方套件還多。

真的是前端開發(fā)人員必備技能。

而且在面試當(dāng)中也往往會問到關(guān)于 Vue 方面的各種問題,其中大部分面試官會問到如上這種問題。

最近一直在做 Vue項目代碼層面上的優(yōu)化,說實話,優(yōu)化別人的代碼真是件痛苦的事情,功能實現(xiàn)尚且不說,就說代碼規(guī)范我就能再寫出一篇文章來。

真的是無規(guī)范不成方圓,規(guī)范這個東西太重要了!

有點扯了,回到主題,咳咳,那就談?wù)勎覍ι厦娴拿嬖囶}的理解吧,文筆有限,不妥之處,歡迎在文章結(jié)尾留言斧正啊,正啊,啊!

概述

幾種通信方式無外乎以下幾種:

  • Prop(常用)
  • $emit (組件封裝用的較多)
  • .sync語法糖 (較少)
  • $attrs 和 $listeners (組件封裝用的較多)
  • provide 和 inject (高階組件/組件庫用的較多)
  • 其他方式通信

詳述

下面逐個介紹,大神請繞行。

1. Prop

英式發(fā)音:[prɒp]。

這個在我們?nèi)粘i_發(fā)當(dāng)中用到的非常多。

簡單來說,我們可以通過 Prop 向子組件傳遞數(shù)據(jù)。

用一個形象的比喻來說,父子組件之間的數(shù)據(jù)傳遞相當(dāng)于自上而下的下水管子,只能從上往下流,不能逆流。

這也正是 Vue 的設(shè)計理念之單向數(shù)據(jù)流。

而 Prop 正是管道與管道之間的一個銜接口,這樣水(數(shù)據(jù))才能往下流。說這么多,看代碼:

  1. <div id="app">  <child :content="message"></child></div> 
  2. // Js 
  3. let Child = Vue.extend({ 
  4.   template: '<h2>{{ content }}</h2>'
  5.   props: { 
  6.     content: { 
  7.       type: String, 
  8.       default: () => { return 'from child' } 
  9.     } 
  10.   } 
  11. }) 
  12.  
  13. new Vue({ 
  14.   el: '#app'
  15.   data: { 
  16.     message: 'from parent' 
  17.   }, 
  18.   components: { 
  19.     Child 
  20.   } 
  21. }) 

 

 

 

瀏覽器輸出:

  1. from parent 

2. $emit

英式發(fā)音:[iˈmɪt]。

官方說法是觸發(fā)當(dāng)前實例上的事件。

附加參數(shù)都會傳給監(jiān)聽器回調(diào)。

按照我的理解不知道能不能給大家說明白,先簡單看下代碼吧:

  1. <div id="app">  <my-button @greet="sayHi"></my-button></div> 
  2. let MyButton = Vue.extend({ 
  3.   template: '<button @click="triggerClick">click</button>'
  4.   data () { 
  5.     return { 
  6.       greeting: 'vue.js!' 
  7.     } 
  8.   }, 
  9.   methods: { 
  10.     triggerClick () { 
  11.       this.$emit('greet', this.greeting) 
  12.     } 
  13.   } 
  14. }) 
  15.  
  16. new Vue({ 
  17.   el: '#app'
  18.   components: { 
  19.     MyButton 
  20.   }, 
  21.   methods: { 
  22.     sayHi (val) { 
  23.       alert('Hi, ' + val) // 'Hi, vue.js!' 
  24.     } 
  25.   } 
  26. }) 

 

大致邏輯是醬嬸兒的:當(dāng)我在頁面上點擊按鈕時,觸發(fā)了組件 MyButton 上的監(jiān)聽事件 greet,并且把參數(shù)傳給了回調(diào)函數(shù) sayHi 。

說白了,當(dāng)我們從子組件 Emit(派發(fā)) 一個事件之前,其內(nèi)部都提前在事件隊列中 On(監(jiān)聽)了這個事件及其監(jiān)聽回調(diào)。其實相當(dāng)于下面這種寫法:

  1. vm.$on('greet'function sayHi (val) {  console.log('Hi, ' + val)})vm.$emit('greet''vue.js')// => "Hi, vue.js" 

3. .sync 修飾符

這個家伙在 vue@1.x 的時候曾作為雙向綁定功能存在,即子組件可以修改父組件中的值。

因為它違反了單向數(shù)據(jù)流的設(shè)計理念,所以在 vue@2.0 的時候被干掉了。

但是在 vue@2.3.0+ 以上版本又重新引入了這個 .sync 修飾符。

但是這次它只是作為一個編譯時的語法糖存在。

它會被擴展為一個自動更新父組件屬性的 v-on 監(jiān)聽器。

說白了就是讓我們手動進行更新父組件中的值了,從而使數(shù)據(jù)改動來源更加的明顯。

下面引入自官方的一段話:

在有些情況下,我們可能需要對一個 prop 進行“雙向綁定”。

不幸的是,真正的雙向綁定會帶來維護上的問題,因為子組件可以修改父組件,且在父組件和子組件都沒有明顯的改動來源。

既然作為一個語法糖,肯定是某種寫法的簡寫形式,哪種寫法呢,看代碼:

  1. <text-document  v-bind:title="doc.title"  v-on:update:title="doc.title = $event"></text-document> 

于是我們可以用 .sync 語法糖簡寫成如下形式:

  1. <text-document v-bind:title.sync="doc.title"></text-document> 

廢話這么多,如何做到“雙向綁定” 呢?

讓我們進段廣告,廣告之后更加精彩!

... 好的,歡迎回來。

假如我們想實現(xiàn)這樣一個效果:改變子組件文本框中的值同時改變父組件中的值。

怎么做?列位不妨先想想。先看段代碼:

  1. <div id="app">  <login :name.sync="userName"></login> {{ userName }}</div> 
  2. let Login = Vue.extend({ 
  3.   template: ` 
  4.     <div class="input-group"
  5.       <label>姓名:</label> 
  6.       <input v-model="text"
  7.     </div> 
  8.   `, 
  9.   props: ['name'], 
  10.   data () { 
  11.     return { 
  12.       text: '' 
  13.     } 
  14.   }, 
  15.   watch: { 
  16.     text (newVal) { 
  17.       this.$emit('update:name', newVal) 
  18.     } 
  19.   } 
  20. }) 
  21.  
  22. new Vue({ 
  23.   el: '#app'
  24.   data: { 
  25.     userName: '' 
  26.   }, 
  27.   components: { 
  28.     Login 
  29.   } 
  30. }) 

 

下面劃重點,代碼里有這一句話:

  1. this.$emit('update:name', newVal) 

官方語法是:update:myPropName 其中 myPropName 表示要更新的 prop 值。

當(dāng)然如果你不用 .sync 語法糖使用上面的 .$emit 也能達到同樣的效果。僅此而已!

4. $attrs 和 $listeners

  • 官網(wǎng)對 $attrs 的解釋如下:

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

當(dāng)一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級別的組件時非常有用。

  • 官網(wǎng)對 $listeners 的解釋如下:

包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。

它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時非常有用。

我覺得 $attrs 和 $listeners 屬性像兩個收納箱,一個負責(zé)收納屬性,一個負責(zé)收納事件,都是以對象的形式來保存數(shù)據(jù)。

看下面的代碼解釋:

  1. <div id="app">  <child    :foo="foo"    :bar="bar"    @one.native="triggerOne"    @two="triggerTwo">  </child></div> 

 

 

從 Html 中可以看到,這里有倆屬性和倆方法,區(qū)別是屬性一個是 prop 聲明,事件一個是 .native 修飾器。

  1. let Child = Vue.extend({ 
  2.   template: '<h2>{{ foo }}</h2>'
  3.   props: ['foo'], 
  4.   created () { 
  5.     console.log(this.$attrs, this.$listeners) 
  6.     // -> {bar: "parent bar"
  7.     // -> {two: fn} 
  8.  
  9.  
  10.     // 這里我們訪問父組件中的 `triggerTwo` 方法 
  11.     this.$listeners.two() 
  12.     // -> 'two' 
  13.   } 
  14. }) 
  15.  
  16. new Vue({ 
  17.   el: '#app'
  18.   data: { 
  19.     foo: 'parent foo'
  20.     bar: 'parent bar' 
  21.   }, 
  22.   components: { 
  23.     Child 
  24.   }, 
  25.   methods: { 
  26.       triggerOne () { 
  27.       alert('one'
  28.     }, 
  29.     triggerTwo () { 
  30.       alert('two'
  31.     } 
  32.   } 
  33. }) 

 

 

可以看到,我們可以通過 $attrs 和 $listeners 進行數(shù)據(jù)傳遞,在需要的地方進行調(diào)用和處理,還是很方便的。

當(dāng)然,我們還可以通過 v-on="$listeners" 一級級的往下傳遞,子子孫孫無窮盡也!

一個插曲!

當(dāng)我們在組件上賦予了一個非Prop 聲明時,編譯之后的代碼會把這些個屬性都當(dāng)成原始屬性對待,添加到 html 原生標簽上,看上面的代碼編譯之后的樣子:

  1. <h2 bar="parent bar">parent foo</h2> 

 

這樣會很難看,同時也爆了某些東西。

如何去掉?

這正是 inheritAttrs 屬性的用武之地!

給組件加上這個屬性就行了,一般是配合 $attrs 使用。

看代碼:

  1. // 源碼let Child = Vue.extend({  ...  inheritAttrs: false, // 默認是 true  ...}) 

再次編譯:

  1. <h2>parent foo</h2> 

 

5. provide / inject

他倆是對CP, 感覺挺神秘的。

來看下官方對 provide / inject 的描述:

provide 和 inject 主要為高階插件/組件庫提供用例。

并不推薦直接用于應(yīng)用程序代碼中。

并且這對選項需要一起使用,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時間里始終生效。

看完描述有點懵懵懂懂!

一句話總結(jié)就是:小時候你老爸什么東西都先幫你存著等你長大該娶媳婦兒了你要房子給你買要車給你買只要他有的盡量都會滿足你。

下面是這句話的代碼解釋:

  1. <div id="app">  <son></son></div> 
  2. let Son = Vue.extend({ 
  3.   template: '<h2>son</h2>'
  4.   inject: { 
  5.     house: { 
  6.       default'沒房' 
  7.     }, 
  8.     car: { 
  9.       default'沒車' 
  10.     }, 
  11.     money: { 
  12.       // 長大工作了雖然有點錢 
  13.       // 僅供生活費,需要向父母要 
  14.       default'¥4500' 
  15.     } 
  16.   }, 
  17.   created () { 
  18.     console.log(this.house, this.car, this.money) 
  19.     // -> '房子''車子''¥10000' 
  20.   } 
  21. }) 
  22.  
  23. new Vue({ 
  24.   el: '#app'
  25.   provide: { 
  26.     house: '房子'
  27.     car: '車子'
  28.     money: '¥10000' 
  29.   }, 
  30.  
  31.   components: { 
  32.     Son 
  33.   } 
  34. }) 

 

6. 其他方式通信

除了以上五種方式外,其實還有:

  • EventBus

思路就是聲明一個全局Vue實例變量 EventBus , 把所有的通信數(shù)據(jù),事件監(jiān)聽都存儲到這個變量上。

這樣就達到在組件間數(shù)據(jù)共享了,有點類似于 Vuex。

但這種方式只適用于極小的項目,復(fù)雜項目還是推薦 Vuex。

下面是實現(xiàn) EventBus 的簡單代碼:

  •  
  1. <div id="app">  <child></child></div> 
  2. // 全局變量 
  3. let EventBus = new Vue() 
  4.  
  5. // 子組件 
  6. let Child = Vue.extend({ 
  7.   template: '<h2>child</h2>'
  8.   created () { 
  9.     console.log(EventBus.message) 
  10.     // -> 'hello' 
  11.     EventBus.$emit('received''from child'
  12.   } 
  13. }) 
  14.  
  15. new Vue({ 
  16.   el: '#app'
  17.   components: { 
  18.     Child 
  19.   }, 
  20.   created () { 
  21.     // 變量保存 
  22.     EventBus.message = 'hello' 
  23.     // 事件監(jiān)聽 
  24.     EventBus.$on('received'function (val) { 
  25.       console.log('received: '+ val) 
  26.       // -> 'received: from child' 
  27.     }) 
  28.   } 
  29. }) 

 

 

  • Vuex

官方推薦的,Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。

  • $parent

父實例,如果當(dāng)前實例有的話。

通過訪問父實例也能進行數(shù)據(jù)之間的交互,但極小情況下會直接修改父組件中的數(shù)據(jù)。

  • $root

當(dāng)前組件樹的根 Vue 實例。

如果當(dāng)前實例沒有父實例,此實例將會是其自己。

通過訪問根組件也能進行數(shù)據(jù)之間的交互,但極小情況下會直接修改父組件中的數(shù)據(jù)。

  • broadcast / dispatch

他倆是 vue@1.0 中的方法,分別是事件廣播 和 事件派發(fā)。

雖然 vue@2.0 里面刪掉了,但可以模擬這兩個方法。

可以借鑒 Element 實現(xiàn)。

有時候還是非常有用的,比如我們在開發(fā)樹形組件的時候等等。

總結(jié)

啰嗦了這么多,希望看到的同學(xué)或多或少有點收獲吧。

不對的地方還請留言指正,不勝感激。

父子組件間的通信其實有很多種,就看你在哪些情況下去用。

不同場景不同對待。

前提是你要心中有數(shù)才行!

通過大神之路還有很遠,只要每天看看社區(qū),看看文檔,寫寫Demo,每天進步一點點,總會有收獲的。

責(zé)任編輯:武曉燕 來源: 前端大牛愛好者
相關(guān)推薦

2024-01-09 08:34:56

Vue3.js組件通信

2019-11-27 15:30:32

人工智能機器人技術(shù)

2018-12-04 21:05:51

2011-12-21 21:16:58

2022-06-15 10:44:12

通貨膨脹IT

2017-06-30 08:51:12

組件模板勒索軟件項目管理

2020-09-12 16:22:27

Vue

2019-04-10 08:24:06

vue組件通信

2019-08-14 10:00:08

vue組件通信前端

2021-09-15 08:09:43

前端技術(shù)編程

2020-09-16 06:12:30

Vue.js 3.0Suspense組件前端

2020-11-26 20:54:23

AI人工智能建筑

2022-08-26 16:44:40

智慧城市AI人工智能

2022-07-15 08:48:07

IT通貨膨脹IT支出

2021-11-11 14:31:11

大數(shù)據(jù)人工智能

2017-07-11 18:00:21

vue.js數(shù)據(jù)組件

2014-12-12 10:29:28

SaaS云服務(wù)

2017-12-11 16:25:25

2017-07-03 16:03:49

IT技術(shù)周刊

2020-06-30 10:10:08

CIO首席信息官IT
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久久免费看 | 男女视频在线免费观看 | 黑人巨大精品欧美一区二区免费 | 五月天天色 | 国产欧美一区二区三区在线播放 | 91免费在线视频 | 免费黄视频网站 | 中文字幕亚洲一区二区va在线 | 国外成人在线视频网站 | h视频在线观看免费 | av在线天天 | 伊人网综合 | 日韩在线精品视频 | 一区二区在线不卡 | 成人在线观看欧美 | 久久网一区二区三区 | 久久久久国产精品 | 亚洲性综合网 | 欧美精品在线一区二区三区 | 另类二区| 国产精品久久久久久久久婷婷 | 国产精品高潮呻吟久久aⅴ码 | www.9191| 日韩最新网址 | 欧美日本在线观看 | 免费看日韩视频 | 国产在线观看一区二区 | 日韩欧美一区在线 | 一级黄a视频 | 久久爱综合 | 久久久噜噜噜久久中文字幕色伊伊 | 韩国精品在线观看 | 6080yy精品一区二区三区 | 草草草网站 | 欧美全黄 | 亚洲一区二区三区四区在线观看 | 二区三区av| 综合国产| 国产精品乱码一区二区三区 | 亚洲一区二区三区桃乃木香奈 | 99热这里都是精品 |