1. 程式人生 > >Vue2.4元件間通訊新姿勢

Vue2.4元件間通訊新姿勢

Vue應用在元件化之後,通常存在著 父子元件、兄弟元件、跨級元件 等元件關係,那麼元件之間如何進行通訊;Vue2.4提供了兩種新的元件通訊方法。

在 Vue 中,父子元件的關係可以總結為 props down、events up。

  • 父子元件通訊 :父元件通過 props 向下傳遞資料給子元件
  • 子父元件通訊 :子元件通過 events 給父元件傳送訊息 
    -使用 $on(eventName) 監聽事件 
    -使用 $emit(eventName) 觸發事件
  • 非父子元件通訊 :使用一個空的 Vue 例項作為中央事件匯流排

在Vue 2.4 版本引入了元件通訊的新方式。

1. 重新引入 .sync 修飾符

熟悉 Vue1.x 的朋友一定對 .sync 修飾器並不陌生。在Vue1.x 中我們可能會需要對一個 prop 進行『雙向繫結』。當一個 子元件 改變了一個 prop的值時,這個變化也會 同步到父元件中 所繫結的值。

因為它破壞了『單向資料流』的假設, .sync 在2.0版本被移除,引起了廣泛的討論。在2.3.0版本 .sync 又回來了,不過與1.x不同。

這次只是原有語法的語法糖(syntax sugar)包裝而成,其背後實現原理是,在元件上自動擴充一個額外的 v-on 監聽器:

程式碼如下:

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

會被擴充為:

<child:bar="foo"@update:bar="e => foo = e">

對於子元件,如果想要更新 foo 的值,則需要顯式地觸發一個事件,而不是直接修改 prop:

this.$emit('update:bar', newValue)

2. $attrs 與 $listeners

多級元件巢狀需要傳遞資料時,通常使用的方法是通過vuex。如果僅僅是傳遞資料,而不做中間處理,使用 vuex 處理,未免有點殺雞用牛刀。Vue 2.4 版本提供了另一種方法,使用 v-bind=”$attrs”, 將父元件中不被認為 props特性繫結的屬性傳入子元件中,通常配合 interitAttrs 選項一起使用。

2.1 interitAttrs

在版本 2.4 之前,預設情況下父作用域的不被作為props特性繫結的屬性,將會作為普通的 HTML 屬性,應用在跟元素上。

 // parent.vue
<template>
    <child-commpent:foo="f":boo="b"></child-comment>
</template>

<script>
const childComment = ()=> import('./childCom.vue')
export default {
    data () {
      return {
        f: 'Hello world!'
        b: 'Hello Vue!'
      }  
    }
}
</script>
// childComment.vue
<template>
    <div>{{ foo }}<div>
</template>

<script>
export default {
    props: ['foo'] //父作用域的boo不被作為props繫結
}
</script>

最後會被渲染為:

//boo會作為普通的 HTML 屬性,應用在跟元素上。
<divboo="Hello Vue!">Hello world!</div>

設定 interitAttrs 為 false,之後,不會應用到跟元素上。

// childCom.vue
<template>
    <div>{{ foo }}</div>
</template>

<script>
  export default {
    props: ['foo'],
    inheritAttrs: false
  }
</script>

最後會被渲染為:

//boo會作為普通的 HTML 屬性,應用在跟元素上。
<div>Hello world!</div>

2.2 $attrs, $listeners

在Vue 2.4 版本,配合 interitAttrs選項, 父元件中未被props(v-on)繫結的屬性(事件) 可以在子元件中,通過 $attrs , $listeners 獲取。

// demo.vue
  <template>
    <div>
      <child-com:foo="foo":boo="boo":coo="coo":doo="doo"></child-com>
    </div>
  </tempalte>
  <script>
  const childCom = ()=> import('./childCom1.vue')
  export default {
    data () {
      return {
        foo: 'Hello World!',
        boo: 'Hello Javascript!',
        coo: 'Hello Vue',
        doo: 'Last'
      }
    },
    components: { childCom }
  }
  </script>
// childCom1.vue
<template>
  <div>
    <p>foo: {{ foo }}</p>
    <p>attrs: {{ $attrs }}</p>
    <child-com2v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = ()=> import('./childCom2.vue')
export default {
  props: ['foo'],  // foo作為props屬性繫結
  inheritAttrs: false,
  created () {
    console.log(this.$attrs) // { boo: 'Hello Javascript!', coo: 'Hello Vue', doo: 'Last' }
  }
}
</script>
// childCom2.vue
<template>
  <div>
   <p>boo: {{ boo }}</p>
   <p>attrs: {{ $attrs }}</p>
   <child-com3v-bind="$attrs"></child-com3>
  </div>
</template>

<script>
const childCom3 = ()=> import('./childCom3.vue')
export default {
  props: ['boo'] // boo作為props屬性繫結
  inheritAttrs: false,
  created () {
    console.log(this.$attrs) // { coo: 'Hello Vue', doo: 'Last' }
  }
}
</script>
// childCom3.vue
// ...

渲染為:

小結

  1. 在Vue2.0被移除的 .sync 被重新加入到2.4版本,不同的是需要顯式地觸發一個事件,而不是直接修改 prop。
  1. Vue2.4提供了 $attrs , $listeners 來傳遞資料與事件,跨級元件之間的通訊變得更簡單。
  2. 轉載http://www.tuicool.com/articles/YfiANnz