vue環境下基於contenteditable實現高度自適應多行文字域(div模擬)
1、在web應用中,常用的多行文字輸入<textarea>,滿足了我們絕大部分的需求,唯一不足之處就是文字高度不能隨內容自適應,如果需要高度自適應需要通過js指令碼實現
2、div有天然的高度自適應,在加上個contenteditable屬性,就可以變成一個文字內容自適應的多行文字輸入框
<div contenteditable="true"></div>
2.1新增雙向繫結功能:
<div contenteditable="true" v-text="contentText"></div>
//頁面載入時,將接收到的value設定到innerText
this.$nextTick(function(){
if($this.value){
$this.contentText=$this.value
}
})
//使用者輸入時,頁面的的值變化需要回傳給繫結的屬性,增加個input事件來處理,完成基本檢視和資料的雙向繫結
<div contenteditable="true" v-text="contentText" @input="handleInput"></div>
handleInput:function(e){
var $this=this;
if(e&&e.target&&e.target.textContent){
if(e.target.textContent<=this.maxLength){
this.$emit('change',e.target.textContent)
}
}
}
2.2為空提示
當輸入框內容為空時,一般都要求有一個輸入提示,div不支援設定placeholder屬性,這時,可藉助css的empty偽類來實現
<div contenteditable="true" v-text="contentText" @input="handleInput" :placeholder=placeholder class="edit-font edit-content" id="edit-content"></div>
.edit-content:empty:before{
content:attr(placeholder)
color:#A5A5A9
}
.edit-content:focus:before{
content:none;
}
2.3字數限制
<textarea>通過maxlength來達到效果,這裡如果使用input事件來觸發,截斷多餘的輸入,這樣會帶來一個比較大的問題,游標會移動到文字最前面,如果使用keypress事件,當用戶輸入的字數超過最大字元數時,阻止預設事件。對於貼上事件,同樣需要控制
<div contenteditable="true" v-text="contentText" @input="handleInput" :placeholder=placeholder class="edit-font edit-content" id="edit-content" @keypress="checkSize" @paste="checkSize"></div>
checkSize:function(e){
if(e.which!=8&&this.$el.textContent.length>=this.maxLength){e.preventDefault();}
}
這時英文和數字輸入是可以根據maxLength來限制了,但是 中文卻還是可以輸入的,這就需要用到DOM提供的composition事件api,規範規定,輸入 開始時觸發compositionstart,選擇字詞開始時觸發compositionend,使用這兩個事件來判斷使用者有沒有完成一次 中文輸入,當compositionstart觸發時,標記為false,當compositionend時,標記為true,然後在input事件觸發,判斷使用者已經完成了輸入,則 將字數截斷,並失焦,避免游標移到最前面,導致輸入混亂
<div contenteditable="true" v-text="contentText" @input="handleInput" :placeholder=placeholder class="edit-font edit-content" id="edit-content" @keypress="checkSize" @paste="checkSize" @compositionStart="handleStart" @compositionend
="handleEnd"></div>
handleStart:function(){
this.finish=false;
},
handleEnd:function(){
this.finish=true;
},
handleInput:function(e){
var $this=this;
if(e&&e.target&&e.target.textContent){
if(e.target.textContent<=this.maxLength){
this.$emit('change',e.target.textContent)
}else{
setTimeout(function(){
if($this.finish){
$this.$el.textContent=$this.$el.textContent.substring(0,$this.maxLength);
$this.$el.blur();
}
},500)
}
}
}
如果業務中還需要什麼功能,也可以基於此進行擴充套件