通過v-model‘實現’元件雙向資料繫結
阿新 • • 發佈:2019-05-12
單向資料流
- 單向資料流是Vue元件一個非常明顯的特徵,不應該在子元件中直接修改props的值
- 如果傳遞的prop僅僅用作展示,不涉及修改,則在模板中直接使用即可
- 如果需要對prop的值進行轉化然後展示,則應該使用computed計算屬性
- 如果prop的值用作初始化,應該定義一個子元件的data屬性並將prop作為其初始值
元件之間的通訊
- 父子元件的關係可以總結為
prop
向下傳遞,事件event
向上傳遞 - 祖先元件和後代元件(跨多代)的資料傳遞,可以使用
provide
和inject
來實現 - 跨元件或者兄弟元件之間的通訊,可以通過
eventBus
或者vuex
等方式來實現
封裝的元件如何實現v-model的資料雙綁的效果
以下兩種通常是我們的實現方式, 看著就很麻煩
- 通過emit將事件派發到父元件,prop將資料傳到子元件
每個父元件都要實現
changeValue
方法來接收資料並更新資料
// 子元件 <template> <div> <van-button @click="add" type="default">加一</van-button> <div> {{countsVal}} </div> <van-button @click="reduce" type="default">減一</van-button> </div> </template> <script> export default { props: { value: Number }, data () { return { // props的初始化比data的初始化要靠前 countsVal: this.value } }, methods: { add () { this.countsVal++ this.$emit('add', this.countsVal) }, reduce() { this.countsVal-- this.$emit('reduce', this.countsVal) } } }; </script> // 父元件 <template> <div> <counter :value='value' @add='changeValue' @reduce='changeValue'/> </div> </template> <script> export default { data () { return { value: 10 } }, methods: { changeValue (data) { this.value = data } } }; </script>
- 將加減執行的回到函式通過父元件傳到子元件中實現改變資料
每個父元件都要實現
add
和reduce
兩個方法
// 子元件 <template> <div> <van-button @click="add" type="default">加一</van-button> <div> {{countsVal}} </div> <van-button @click="reduce" type="default">減一</van-button> </div> </template> <script> export default { props: { value: Number, add: Function, reduce: Function } }; </script> // 父元件 <template> <div> <counter :value='value' :add='add' :reduce='reduce'/> </div> </template> <script> export default { data () { return { value: 10 } }, methods: { add (data) { this.value++ }, reduce (data) { this.value-- } } }; </script>
通過v-model
語法糖實現,父子組價的資料雙綁
Vue內建了v-model指令,v-model 是一個語法糖,可以拆解為 props: value 和 events: input。就是說元件只要提供一個名為 value 的 prop,以及名為 input 的自定義事件,滿足這兩個條件,使用者就能在自定義元件上使用 v-model,戳這裡看model配置
// 子元件
<template>
<div>
<van-button @click="changeVal(1)" type="default">加一</van-button>
<div>
{{countsVal}}
</div>
<van-button @click="changeVal(-1)" type="default">減一</van-button>
</div>
</template>
<script>
export default {
props: {
value: Number
},
data () {
return {
// props的初始化比data的初始化要靠前
countsVal: this.value
}
},
methods: {
changeVal (data) {
this.countsVal += parseInt(data)
this.$emit('input', this.countsVal)
}
}
}
</script>
// 父元件只需要通過v-model將資料傳進去就好了
<template>
<div>
<counter v-model='counts'/>
</div>
</template>
<script>
import counter from './base/counter'
export default {
components: {
counter
},
data () {
return {
counts: 10
}
}
}
<