vue中父子組件Props雙向綁定

事件處理方式

1. v-on指令

1.直接把 JavaScript 代碼寫(xiě)在 v-on 指令中是不可行的,v-on指令需要接收一個(gè)調(diào)用的方法名稱,

<button v-on:click="greet">Greet</button>


// 在 `methods` 對(duì)象中定義方法
methods: {
    greet: function (event) {
      // `this` 在方法里指向當(dāng)前 Vue 實(shí)例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    }
  }

2. 事件內(nèi)聯(lián)處理器

2.除此之外vue還可以使用內(nèi)聯(lián)處理器,需要在內(nèi)聯(lián)語(yǔ)句處理器中訪問(wèn)原始的 DOM 事件。可以用特殊變量 $event 把它傳入方法

  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
  <button v-on:click="warn('hello.', $event)">Submit</button>

// 在 `methods` 對(duì)象中定義方法
   methods: {
    say: function (message) {
      alert(message)
    },
    warn: function (message, event) {
    // 現(xiàn)在我們可以訪問(wèn)原生事件對(duì)象
        if (event) {
        event.preventDefault()
        }
        alert(message)
    }
  }

Props

所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中,但是反過(guò)來(lái)則不行。這樣會(huì)防止從子組件意外改變父級(jí)組件的狀態(tài),從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。

這里有兩種常見(jiàn)的試圖改變一個(gè) prop 的情形:

  1. 這個(gè) prop 用來(lái)傳遞一個(gè)初始值;這個(gè)子組件接下來(lái)希望將其作為一個(gè)本地的 prop 數(shù)據(jù)來(lái)使用。在這種情況下,最好定義一個(gè)本地的 data 屬性并將這個(gè) prop 用作其初始值:
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
  1. 這個(gè) prop 以一種原始的值傳入且需要進(jìn)行轉(zhuǎn)換。在這種情況下,最好使用這個(gè) prop 的值來(lái)定義一個(gè)計(jì)算屬性:
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

v-model

首先我們要知道v-model指令是用來(lái)在表單 <input>、<textarea> 及 <select> 元素上創(chuàng)建雙向數(shù)據(jù)綁定,但 v-model 本質(zhì)上不過(guò)是語(yǔ)法糖:value="msg" @input="msg = $event.target.value"

注意點(diǎn):v-model 會(huì)忽略所有表單元素的 value、checked、selected attribute 的初始值而總是將 Vue 實(shí)例的數(shù)據(jù)作為數(shù)據(jù)來(lái)源。你應(yīng)該通過(guò) JavaScript 在組件的 data 選項(xiàng)中聲明初始值。

image.png

實(shí)現(xiàn)組件Props雙向綁定

在Vue2中組件的props的數(shù)據(jù)流動(dòng)改為了只能單向流動(dòng),即只能由組件外(調(diào)用組件方)通過(guò)組件的DOM屬性attribute傳遞props給組件內(nèi),組件內(nèi)只能被動(dòng)接收組件外傳遞過(guò)來(lái)的數(shù)據(jù),并且在組件內(nèi),不能修改由外層傳來(lái)的props數(shù)據(jù)。

假如我現(xiàn)在需要做一個(gè)彈出層組件,需求:

  • 通過(guò)點(diǎn)擊按鈕實(shí)現(xiàn)彈出(顯示)
  • 不點(diǎn)擊按鈕,點(diǎn)擊自己隱藏,或者直接修改狀態(tài)實(shí)現(xiàn)隱藏和顯示

方案一:

由于子組件不能直接修改props的值,所以:

  1. 子組件內(nèi)的data下創(chuàng)建一個(gè)Props屬性的副本
  2. 監(jiān)聽(tīng)props屬性 賦予data副本 來(lái)同步組件外對(duì)props的修改
  3. 創(chuàng)建針對(duì)props副本的watch,通知到組件外

解釋:在第2步驟之后,我們?cè)诮M件內(nèi)修改了props的副本testShow,組件外此時(shí)不知道組件內(nèi)的props狀態(tài),所以需要再創(chuàng)建一個(gè)針對(duì)props副本testShow的監(jiān)聽(tīng),即對(duì)應(yīng)data屬性的watch

image.png

缺點(diǎn):

父組件必須有個(gè) showChange 這樣的方法,有點(diǎn)累贅。

思考:

個(gè)人認(rèn)為只有在滿足以下條件時(shí)再使用雙向綁定的props:

  • 組件內(nèi)部需要修改props。
  • 組件需要可以由外部在運(yùn)行時(shí)動(dòng)態(tài)控制,而非單純初始化。
  • 組件外部需要讀取組件內(nèi)的狀態(tài)來(lái)進(jìn)行處理
    滿足上述條件的有比如switch開(kāi)關(guān)組件,需要外部控制開(kāi)關(guān)狀態(tài);再比如Tab多標(biāo)簽頁(yè)組件的activeIndex屬性,需要可以由外部控制標(biāo)簽頁(yè)當(dāng)前打開(kāi)哪一頁(yè)等等

方案二:

v-model指令是用來(lái)在表單 <input>、<textarea> 及 <select> 元素上創(chuàng)建雙向數(shù)據(jù)綁定,但 v-model 本質(zhì)上不過(guò)是語(yǔ)法糖:value="msg" @input="msg = $event.target.value"

image.png

這種實(shí)現(xiàn)父子組件見(jiàn)v-model綁定值的方法,在我們開(kāi)發(fā)中其實(shí)是很常用的,特別是你要封裝公共組件的時(shí)候。

方案三

先看下官方文檔:vue .sync修飾符,里面說(shuō)vue .sync 修飾符以前存在于vue1.0版本里,但是在在 2.0 中移除了 .sync 。但是在 2.0 發(fā)布之后的實(shí)際應(yīng)用中,我們發(fā)現(xiàn) .sync還是有其適用之處,比如在開(kāi)發(fā)可復(fù)用的組件庫(kù)時(shí)。我們需要做的只是讓子組件改變父組件狀態(tài)的代碼更容易被區(qū)分。從 2.3.0 起我們重新引入了 .sync修飾符,但是這次它只是作為一個(gè)編譯時(shí)的語(yǔ)法糖存在。它會(huì)被擴(kuò)展為一個(gè)自動(dòng)更新父組件屬性的 v-on 監(jiān)聽(tīng)器。 .sync屬性 使用方法跟 v-model 類似

vue 修飾符sync的功能是:當(dāng)一個(gè)子組件改變了一個(gè) prop 的值時(shí),這個(gè)變化也會(huì)同步到父組件中所綁定。如果我們不用.sync,我們想做上面的那個(gè)彈窗功能,我們也可以props傳初始值,然后事件監(jiān)聽(tīng),實(shí)現(xiàn)起來(lái)也不算復(fù)雜。這里用sync實(shí)現(xiàn),只是給大家提供一個(gè)思路,讓其明白他的實(shí)現(xiàn)原理,可能有其它復(fù)雜的功能適用sync。

<comp :foo.sync="bar"></comp>

會(huì)被擴(kuò)展為:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

當(dāng)子組件需要更新 foo 的值時(shí),它需要顯式地觸發(fā)一個(gè)更新事件:

this.$emit('update:foo', newValue)
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是組件? 組件 (Component) 是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝...
    youins閱讀 9,705評(píng)論 0 13
  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對(duì)象里所有的屬性:var data = { a:...
    云之外閱讀 2,372評(píng)論 0 6
  • vue.js是什么 是一套構(gòu)建用戶界面的漸進(jìn)式框架 vue應(yīng)用組成 一個(gè) Vue 應(yīng)用由一個(gè)通過(guò)new Vue創(chuàng)建...
    多多醬_DuoDuo_閱讀 1,131評(píng)論 0 2
  • 背景 ??Vue是單頁(yè)面應(yīng)用,單頁(yè)面應(yīng)用又是由組件構(gòu)成,各個(gè)組件之間又互相關(guān)聯(lián),那么如何實(shí)現(xiàn)組件之間通信就顯得尤為...
    A鄭家慶閱讀 1,068評(píng)論 0 1
  • 組件注冊(cè) 組件名 在注冊(cè)一個(gè)組件的時(shí)候,我們始終需要給它一個(gè)名字。 該組件名就是Vue.component的第一個(gè)...
    oWSQo閱讀 454評(píng)論 0 1

友情鏈接更多精彩內(nèi)容