組件系統(tǒng)作為Vue最重要的部分之一,多人協(xié)作開發(fā)的時候,寫好一個可復用的組件灰常重要,別的同事用到你寫的組件的時候會覺得:“誒,這個小伙汁有點東西!”
- 如果不用v-model,在原生input標簽上怎么實現(xiàn)雙向綁定呢?
<template>
<input :value="text" @input="handler" />
</template>
<script>
export default {
name: 'customInput',
data () {
return {
text: 'message'
}
},
methods: {
handler (event) {
// 這里有個點要注意一下,v-model不會處理輸入法組合文字過程中得到更新
if (event.target.composing) return
this.text = event.target.value
}
}
}
</script>
這里有個點要注意一下,對于input標簽,v-model不會處理輸入法組合文字過程中得到更新
文檔地址,如果對源碼感興趣可以參考這里
v-model就是上面操作的語法糖
- 下面我們來實現(xiàn)一個簡單的星級組件并兼容v-model
<template>
<div class="component-star" @click.stop="">
<ul class="star-list">
<li v-for="(item, index) in list" :key="index" @click="change(index)">{{item}}</li>
</ul>
<span class="label">{{label}}</span>
</div>
</template>
<script>
export default {
name: 'myStar',
props: {
value: { // 必須是value屬性,名字不能變
type: [Number, String],
required: true
}
},
data () {
return {
}
},
computed: {
list () {
return '★★★★★☆☆☆☆☆'.slice(5 - this.value, 10 - this.value).split('')
},
label () {
const arr = ['1星', '2星', '3星', '4星', '5星']
return arr[this.value - 1]
}
},
watch: {
},
methods: {
// 當星級變化
change (val) {
let num = val + 1
this.$emit('input', num) // 必須是input事件
}
}
}
</script>
<style lang="less">
.component-star {
.star-list {
display: inline-flex;
font-size: 20px;
li {
cursor: pointer;
margin-right: 5px;
color: #f7ba2a;
transform: scale(1);
transition: transform .1s linear;
&:hover {
transform: scale(1.3);
}
}
}
}
</style>
有兩個關(guān)鍵的地方:
1、組件的props中必須要定義value屬性
2、當值變化后,一定要用input事件回傳修改后的值
寫好注冊就可以在任意組件中使用了
<template>
<div class="parent">
<my-star v-model="star"></my-star>
</div>
</template>
<script>
export default {
name: 'parent',
data () {
return {
star: 3
}
},
watch: {
star (val) {
console.log(val)
}
}
}
</script>
那么問題來了:如果我編寫的組件內(nèi)部還有一個使用v-model的組件怎么辦呢?
比如剛才的組件我想在element提供的el-rate組件基礎(chǔ)上做一層封裝,只需要把"v-model"替換為":value",這樣功能即可正常使用。(當然,如果你是按需加載element組件的話,不要忘了先注冊組件)
<template>
<div class="component-star" @click.stop="">
<!--只需要把v-model替換為:value-->
<el-rate :value="value" @change="change" ref="rate"></el-rate>
</div>
</template>
如果報了這個錯:
[Vue warn]: Invalid prop: type check failed for prop "value". Expected Number, got String.說明你傳進來的value是個String類型的值,el-rate的value參數(shù)只接受Number類型的值,把組件v-model綁定的變量改成數(shù)字類型就好了。