react都這麼無情了,vue還是那麼有義,4種父子元件資料雙向傳遞大法

混元霹靂手發表於2017-09-21

原本想放張老尤的照片的,燒三根香膜拜一下的,可惜圖片和不上去,在前端這麼mmp的時代,天天有那麼多B事,在資料驅動的時候,大家都推崇資料的走向都是單向資料流,都是通過父元件去向子元件傳遞資料,還是那句話,那來這麼多B事,只要注意點就可以了,合理的運用雙向繫結,無論對業務和元件開發來說,都是一件雙贏的事,裝B可以,但是不能過份!

好了,講重點,今天我就給大家講講VUE四種資料雙向傳遞有那些用法

一.通過$on , $emit 來進行雙向通訊

使用 $on(eventName) 監聽事件
使用 $emit(eventName) 觸發事件

這種用法,其實是我接下來三種用法的根基

先來說說$on 是用來幹麻的,是用來監聽的事件的,就是監聽$emit裡(eventName)事件的,一量$emit觸發事件,則$on會接收到,則執行函式事件

那我們基本資料單向傳遞我們都用props來進行傳遞,那一旦子元件想改變props傳過來的資料,我們是不能直接改變Props裡的資料,我們還是要改變父元件的資料,用$on和$emit是如何實現的呢

children元件

<template lang="pug">
  .demo
    .demo-example(@click="changePropsValue") {{msg}}
</template>


<script>
export default {
  props: ['msg'],
  methods: {
    changePropsValue () {
      this.$emit('changeMsg', '通過$emit觸發事件了')
    }
  }
}
</script>複製程式碼

1.msg是通過父元件傳遞過來的,我們先前可肯定要在props裡宣告好
2.在點選的時候,我們觸發了changeMsg事件,第二個引數是,你想要傳到父元件的引數

parent元件

<template lang="pug">
  div
    demo(:msg="msg" v-on:changeMsg='onChange')
</template>

<script>
import Demo from './demo.vue'
export default {
  data () {
    return {
      msg: '首次資料傳遞'
    }
  },
  components: {
    Demo
  },
  methods: {
    onChange (msg) {
      this.msg = msg
    }
  }
}
</script>複製程式碼

我們隨後把demo引入,傳入子元件的msg我們事先在data資料裡面定義好,同時在demo元件上進行一個$on的監聽
1.$on :(冒號)後面跟的第一個值是$emit觸發的事件,也是$on所要監聽的事件,一量$emit有觸發,則馬上執行了onChange函式,但本質上vue還是單向資料流的,雖然props不能改變,但是data裡的資料是可以進行改變的,一但data的資料和子元件有傳遞關係,一旦父data資料有變動,子元件props所對應的資料則同時跟著變動

二.通過 v-model 來進行雙父子通訊

在vue進入到2.0的時候,取消了.sync的功能,導致了一堆元件庫大動腦子,基本都用了v-model去進行雙向繫結,本質上v-model適用場景是用在表單上面的,但是既然可以自定義了,那就有它的靈活性

官方說法:

自定義事件可以用來建立自定義的表單輸入元件,使用 v-model 來進行資料雙向繫結。看看這個:input v-model="something"

那語法糖則是這樣的

input
v-bind:value="something"
v-on:input="something = $event.target.value"

這說明了

1.v-model裡的something這個變數值在語法糖裡代表的是value值,在表單上我們可以看作是input的value值,那在其它標籤可以看成一個將要傳入的Props資料,那唯一不可變的是這個props的Key必須是value
2.v-on:input="something = $event.target.value"
其實v-model內建也是通過$on和$emit來進行傳遞的,進行了input輸入事件的監聽,然後拿到事件上$event.target.value最新的改變something

現在老版本的元件庫,當2.0取消.sync的時候,自定義元件的時候,如何巧用v-model來進行雙向通訊

children元件

<template lang="pug">
  .demo
    .demo-example(@click="changePropsValue") {{value}}
</template>


<script>
export default {
  props: ['value'],
  methods: {
    changePropsValue () {
      this.$emit('input', '通過$emit觸發input事件了')
    }
  }
}
</script>複製程式碼

1.這裡的value前面說過了就是v-model傳過來的value ( v-bind:value="something"),但是隻能用value去接收
2.這裡主要巧用了一點,平時我們改變input輸入框的時候,input事件是自己主動觸發的,但是,我們也同時可以給他手動觸發,我們用$emit進行了手動觸發(input)事件

parent元件

<template lang="pug">
  div
    demo(v-model ='msg')
</template>

<script>
import Demo from './demo.vue'
export default {
  data () {
    return {
      msg: '首次資料傳遞'
    }
  },
  components: {
    Demo
  }
}
</script>複製程式碼

這個我們直接用v-model像表單那樣繫結就直接可以進行父子元件雙向繫結了。在v-model的語法糖裡封裝了v-on:input 去進行監聽事件

3.在2.3迴歸的特性.sync

迴歸的.sync與1.0版本的寫法有所改變,改來改去,不離其實中,還是要通過$emit去顯式地觸發一個更新事件;

但是相比v-model來說語法上更加直觀,更加簡潔,畢鏡v-model是主要給表單進行又向繫結適用的

如果再進一步往底層說,.sync還是進行了$on進行了監聽封裝,跟v-model一樣也同樣是一種語法糖

children元件

<template lang="pug">
  .demo
    .demo-example(@click="changePropsValue") {{msg}}
</template>


<script>
export default {
  props: ['msg'],
  methods: {
    changePropsValue () {
      this.$emit('update:msg', '通過$emit顯示觸發了更新事件')
    }
  }
}
</script>複製程式碼

1.通過props來進行msg的資料接收
2.通過$emit來進行觸發,第一個引數則是顯示觸發,update:msg (msg)則是你需要改變的props裡從父元件裡接收的值,第二個引數,還是你要更新的值,從語意上設計的也很有感覺,有木有

parent

<template lang="pug">
  div
    demo(:msg.sync="msg")
</template>

<script>
import Demo from './demo.vue'
export default {
  data () {
    return {
      msg: '首次資料傳遞'
    }
  },
  components: {
    Demo
  }
}
</script>複製程式碼

主要看demo(:msg.sync="msg") 這裡直接在向子元件傳遞的時候還是像1.0的時候加一個.sync,本質上還是它會被擴充套件為一個自動更新父元件屬性的 v-on 偵聽器
(推薦用法,一般對一個模態框進行封裝的時候很有用,有了.sync不建議用v-model)

4.$parent用法

這在一些顯示操作的時候,向外部暴露props和event的時候是不推薦用的,那有人要問了$$parent什麼時候用呢,在一些自己內部邏輯操用的時候可以用一下,不用很繁瑣的來進行雙向來回導,節省程式碼和邏輯,有時候也可以讓人一目瞭然

children元件

<template lang="pug">
  .demo
    .demo-example(@click="changePropsValue") 點選按鈕
</template>


<script>
export default {
  methods: {
    changePropsValue () {
      this.$parent.msg = '通過$parent顯改變了更新事件'
    }
  }
}
</script>複製程式碼

1.子元件,通過點選按鈕,顯示的改變了父元件的parent.msg裡面的資料

parent

<template lang="pug">
  div
    demo
    p {{msg}}
</template>

<script>
import Demo from './demo.vue'
export default {
  data () {
    return {
      msg: '第一次寫入資料'
    }
  },
  components: {
    Demo
  }
}
</script>複製程式碼

在這種四種方法裡,我還是推薦用.sync來進行雙向通訊,一量旦通訊機制深了,元件的嵌到超過3層的話,我還是建議用vuex來進行資料的共享,不然一層一層傳,再一層一層的向上導,到最後你頁面會把控不住,業務程式碼也就不直觀了

相關文章