1. 程式人生 > >vue環境下基於contenteditable實現高度自適應多行文字域(div模擬)

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)

          }

      }

    }

如果業務中還需要什麼功能,也可以基於此進行擴充套件