v-model一些理解
用過vue同學,都知道v-model可以實現雙向繫結,方便我們的賦值和獲取。
<input v-model="value"/>
使用v-model可以輕鬆的獲取我們輸入的值。下面我們就來研究下其中的原理:
通常我們寫一個元件,子元件要獲取父元件的值,通過props傳值,父元件要獲取子元件要通過$emit繫結一個方法,通過呼叫這個方法獲取相應的值。
子元件:zInput
<template> <input type="text" @input="changValue" /> </template> <script> export default { props: { value: { type: String, default: '' } }, methods: { changValue(e) { this.$emit('input', e.target.value) } } } </script>
父元件:
<template> <div class="test"> <zInput :value="value" @input="getInput" /> </div> </template> <script> import zInput from './zInput' export default { components: { zInput }, data() { return { value: '' } }, methods: { // 獲取子元件的值 getInput(val) { console.log(val) } } } </script>
這是一般的寫法,我們該怎麼用v-model實現資料的雙向繫結呢,首先我們要弄清楚model的原理:
一個元件上的 v-model 預設會利用名為 value 的 prop 和名為 input 的事件
v-model 相當於 :value="value" @input="getInput" 那我我們就可以這樣寫父元件了:
<template> <div class="test"> <zInput v-model="value"/> </div> </template> <script> import zInput from './zInput' export default { components: { zInput }, data() { return { value: '' } }, watch:{ value(val){ console.log(val) } } } </script>
現在是不是清晰了很多,v-model就是父元件預設傳一個預設為value的值給子元件,並且預設獲取input事件。如果你理解了就可以動手改造我們的程式碼,就可以解決之前的來回傳值和獲取的煩惱了。
如果你還是覺得這樣滿足不了你的需求,你可以嘗試下自定義v-model:
vue2.2.0+ 新增
一個元件上的 v-model 預設會利用名為 value 的 prop 和名為 input 的事件,但是像單選框、複選框等型別的輸入控制元件可能會將 value attribute 用於不同的目的。model 選項可以用來避免這樣的衝突:
先看下官網的例子:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
我們可以自定義prpo傳入的值和$emit的事件,這樣我們可以更加靈活的使用v-model,實現我們的需求。
我們可以用computed中的get和set更好的實現的我們的自定義的雙向繫結,如果不是太瞭解,可以看下:計算屬性 vs 偵聽屬性
下面我們用elment-ui中的單選框舉例:
子元件zRadio
<template>
<div>
<el-radio-group v-model="radioValue">
<el-radio-button label="上海"></el-radio-button>
<el-radio-button label="北京"></el-radio-button>
<el-radio-button label="廣州"></el-radio-button>
<el-radio-button label="深圳"></el-radio-button>
</el-radio-group>
</div>
</template>
<script>
export default {
props: {
radio: { type: String, default: '' }
},
model: {
props: 'radio',// 自定義傳入的值
event: 'change'// 自定義我們的事件
},
computed: {
radioValue: {
get() {
return this.radio // 接收傳進來的值
},
set(value) {
// 設定radio的值並通過model的change的事件傳出改變的值
this.$emit('change', value)
}
}
}
}
</script>
父元件:我們可以直接獲取radio的繫結的值,也可以用chang獲取事件
<template>
<div class="test">
<zRadio v-model="value" :radio="value" @change="getValue" />
</div>
</template>
<script>
import zRadio from './zRadio'
export default {
components: { zRadio },
data() {
return {
value: ''
}
},
watch: {
value(val) {
console.log(val)
}
},
methods: {
getValue(val) {
console.log(val)
}
}
}
</script>
這樣我們精簡了我們的程式碼,也簡化了我們的複雜的傳值,自己動手改造下自己的程式碼吧。