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