可編輯非input,texrarea+vue實現雙向繫結(以div標籤為例)
阿新 • • 發佈:2021-01-06
想法來源
關於輸入,input標籤和textarea標籤可以滿足我們90%以上的需求,但有些時候有些一些特殊需求,或者在改別人的專案時,換標籤不方便,這個時候需求就沒辦法無法滿足。
此時,我們就可以使用div等一些標籤來實現
本文涉及知識點
屬性:contenteditable是一個列舉屬性,表示元素是否可被使用者編輯。 如果可以,瀏覽器會修改元素的部件以允許編輯。
當標籤加上這個屬性時,就可進行內容編輯,來實現輸入的效果。並且實現placeholder效果,如下
//html
<div>請在下方的框中輸入你喜歡的句子</div>
<div contenteditable placeholder= '請輸入文字' class="input"></div>
//css
.input {
width: 500px;
height: 24px;
line-height: 24px;
font-size: 14px;
padding: 5px 8px;
border: 1px solid #ddd;
}
.input:empty::before {
content: attr(placeholder);
}
如下
這裡由於下面會用到,這裡先直接列出
大部分知道contenteditable屬性有 true 和 false。,但是不止這些
contenteditable屬性值
contenteditable="" //表示元素是可編輯的
contenteditable="events"
contenteditable="caret"
//讓div只能鍵入文字值
//相容性不好,除了谷歌,火狐ie都不支援
contenteditable="plaintext-only"
contenteditable="true"//表示元素是可編輯的
contenteditable="false" //表示元素是不可編輯的
至於contenteditable=“events”,contenteditable="caret"我也沒有查到是什麼意思,但是下面用不上我們這裡就不深挖了
雙向繫結
我們都知道,div是無法使用 v-model,那麼該如何實現雙向繫結呢?
//html
<div id="id">
<div>請在下方的框中輸入你喜歡的句子</div>
<div contenteditable placeholder='請輸入文字' class="input" v-html="content" @input="content=$event.target.innerHTML"></div>
<div>{{content}}</div>
</div>
<div contenteditable placeholder='請輸入文字' v-html="item.content"></div>
//js
var id = new Vue({
el: "#id",
data: {
content: "",
},
})
但是有時只想複製文字,卻發現複製過來的是標籤+標籤樣式,那麼改如何處理?
這個時候就要用到contenteditable="plaintext-only"
但是實際使用上有很多問題,比如游標的問題,我們可以依靠元件來對這些問題進行處理
<div id="app">
<m-contenteditable :child="content"></m-contenteditable>
<m-contenteditable :child="content"></m-contenteditable>
<div><pre v-html="content.txt"></pre></div>
</div>
<script>
//定義一個全域性元件
Vue.component("mContenteditable",{
props:{
child:{
type:Object,
default:{
txt:""
}
}
},
//資料
data:function(){
return {
innerText:this.child.txt,
lock:false
}
},
//偵聽器
watch:{
child:{
handler(newValue, oldValue) {
if(!this.lock) {
this.innerText=this.child.txt;
};
},
deep:true
}
},
//改變的方法
methods:{
changeTxt:function(e){
this.child.txt=this.$el.innerHTML;
}
},
//模板
template:`<div class="box" contenteditable="true" v-html="innerText" @input="changeTxt" @focus="lock=true" @blur="lock=false"></div>`
});
new Vue({
el:"#app",
data:{
content:{
txt:"內容<img src=\"http://pub.idqqimg.com/lib/qqface/0.gif\" width=\"38\" height=\"38\">"
}
}
});