表單可以通過簡單的v-model實現(xiàn)數(shù)據(jù)的雙向綁定(value 的單向綁定 + onChange 事件偵聽),實現(xiàn)所見即所得,但表單是限高的,在文本的輸入過程中不能自增高度,因此想到使用div進行數(shù)據(jù)雙向綁定;
為了實現(xiàn)View=>Model,需要一個可編輯的div,這里使用了contenteditable屬性:
<!-- EditableDiv.vue -->
<template>
<div ref="div" contenteditable="true"></div>
<template/>
v-model并不能直接在div上使用,我們通過mounted周期來模擬插值的過程:
// EditableDiv.vue
export default {
props: ['value'], // 組件接受一個 value 屬性用來在 div 中展示
mounted() {
this.setVal(this.value) // 將 value 注入 div 中
},
methods: {
setVal(val) {
this.$refs.div.innerHTML = val
}
},
watch: {
// 當(dāng) props.value 發(fā)生改變時 更新 div 中的值
value(val) {
this.setVal(this.value)
}
}
}
這樣就實現(xiàn)了視圖向數(shù)據(jù)的綁定。
在實現(xiàn)Model=>View的過程中,會有較多頭疼的問題,這篇文章做了很好的總結(jié),但最終還是無法做到像input一樣真實的綁定,只是模擬了行為。
以下是通過blur事件實現(xiàn)的綁定,同樣也是妥協(xié)后的結(jié)果:
<!-- EditableDiv.vue -->
<!-- 為 div 綁定 blur 事件以更新value -->
<template>
<div
ref="div"
contenteditable="true"
@blur="$emit('update:value', $event.target.innerHTML)"
></div>
</template>
在使用時通過sync修飾符:
<!-- Home.vue -->
<editable-div :value.sync="content" />