1. 程式人生 > >工作筆記四——vueJS在移動端使用富文字編輯器

工作筆記四——vueJS在移動端使用富文字編輯器

本文主要介紹vue移動端使用富文字編輯器的使用及常見問題處理。參考元件vue-html5-editor。

1.專案建立與初始化

建立一個vue-cli專案,建議在安裝的時候不要使用ESLINT做程式碼檢查,練習的專案不需要這種檢查機制,會很浪費時間。還有一些自動化測試的外掛也最好不要裝,影響效率。

在安裝好腳手架的依賴後,要執行 npm install vue-html5-editor -S 來安裝這個富文字外掛,由於這個富文字外掛的圖示是依賴font-awesome.css的,所以要npm install font-awesome.css 安裝這個css然後在main.js中引入這個css   import   "font-awesome/css/font-awesome.css"

2.使用vue-html5-editor富文字編輯器

           新建一個common資料夾用於存放我們的工具類js檔案,然後將下面的程式碼copy進去:

/**
 * author: Joker
 * creationDate: 2018/1/22
 * usage:
 */
import Vue from 'vue'
import VueHtml5Editor from 'vue-html5-editor'
export default function () {
  let opt = {
    // 全域性元件名稱,使用new VueHtml5Editor(options)時該選項無效
    name: "vue-html5-editor",
    // 是否顯示模組名稱,開啟的話會在工具欄的圖示後臺直接顯示名稱
    showModuleName: true,
    // 自定義各個圖示的class,預設使用的是font-awesome提供的圖示
    icons: {
      text: "fa fa-pencil",
      color: "fa fa-paint-brush",
      font: "fa fa-font",
      align: "fa fa-align-justify",
      list: "fa fa-list",
      link: "fa fa-chain",
      unlink: "fa fa-chain-broken",
      tabulation: "fa fa-table",
      image: "fa fa-file-image-o",
      hr: "fa fa-minus",
      eraser: "fa fa-eraser",
      undo: "fa-undo fa",
      "full-screen": "fa fa-arrows-alt",
      info: "fa fa-info",
    },
    // 配置圖片模組
    image: {
      // 檔案最大體積,單位位元組  
      sizeLimit: 512 * 1024 * 10,
      // 上傳引數,預設把圖片轉為base64而不上傳
      // upload config,default null and convert image to base64
      upload: {
        url: null,
        headers: {},
        params: {},
        fieldName: {}
      },
      // 壓縮引數,預設使用localResizeIMG進行壓縮,設定為null禁止壓縮
      // width和height是檔案的最大寬高
      compress: {
        width: 600,
        height: 600,
        quality: 80
      },
      // 響應資料處理,最終返回圖片連結
      uploadHandler(responseText){
        //default accept json data like  {ok:false,msg:"unexpected"} or {ok:true,data:"image url"}
        var json = JSON.parse(responseText);
        console.info(json);
        if (!json.ok) {
          alert(json.msg)
        } else {
          return json.data
        }
      }
    },
    // 語言,內建的有英文(en-us)和中文(zh-cn)
    language: "zh-cn",
    // 自定義語言
    i18n: {
      "zh-cn": {
        "align": "對齊方式",
        "image": "圖片",
        "list": "列表",
        "link": "連結",
        "unlink": "去除連結",
        "table": "表格",
        "font": "文字",
        "full screen": "全屏",
        "text": "排版",
        "eraser": "格式清除",
        "info": "關於",
        "color": "顏色",
        "please enter a url": "請輸入地址",
        "create link": "建立連結",
        "bold": "加粗",
        "italic": "傾斜",
        "underline": "下劃線",
        "strike through": "刪除線",
        "subscript": "上標",
        "superscript": "下標",
        "heading": "標題",
        "font name": "字型",
        "font size": "文字大小",
        "left justify": "左對齊",
        "center justify": "居中",
        "right justify": "右對齊",
        "ordered list": "有序列表",
        "unordered list": "無序列表",
        "fore color": "前景色",
        "background color": "背景色",
        "row count": "行數",
        "column count": "列數",
        "save": "確定",
        "upload": "上傳",
        "progress": "進度",
        "unknown": "未知",
        "please wait": "請稍等",
        "error": "錯誤",
        "abort": "中斷",
        "reset": "重置"
      }
    },
    // 隱藏不想要顯示出來的模組
    hiddenModules: [],
    // 自定義要顯示的模組,並控制順序
    visibleModules: [
      "text",
      "color",
      "font",
      "align",
      "list",
      "link",
      "unlink",
      "tabulation",
      "image",
      "hr",
      "eraser",
      "undo",
      "full-screen",
      "info",
    ],
    // 擴充套件模組,具體可以參考examples或檢視原始碼
    // extended modules
    modules: {
      //omit,reference to source code of build-in modules
    }
  };
  Vue.use(VueHtml5Editor, opt);
}

接著在main.js中引入這個初始化的函式:

import initRichText from './common/initHTMLEditor';  
initRichText();

準備工作已經完成了,我們可以使用這個元件了:

    <template>  
      <div class="content">  
        <vue-html5-editor :content="content" :height="400"  
                          @change="updateData"></vue-html5-editor>  
      
      </div>  
    </template>  
    <style scoped>  
      
    </style>  
    <script>  
      export default {  
        data(){  
          return {content: '請輸入文章內容'}  
        },  
        methods: {  
          updateData(e = ''){  
            this.content = e;  
            console.info(e);  
          }  
        }  
      }  
    </script>  

這個height屬性是設定內容區的高度,content是內容區的資料內容,@change事件是內容區的監聽事件,會在發生變化時觸發,該函式接收一個引數,表示當前編輯器中的內容。執行結果如下(這裡對圖片的操作是轉成base64的字串):


 

3.常見問題解決

a.自定義工具欄的模組

如果不想要顯示這麼多的工具,則只要配置visibleModules即可:

b.工具欄的樣式修改

在移動端我們通常希望工具欄可以固定不動,並且顯示在頁面最下方,這時候我們要修改該元件的核心js裡面的樣式程式碼:

主要是將

    var template$9 = "<div class=\"vue-html5-editor\" :class=\"{'full-screen':fullScreen}\".......省略很長的程式碼....)  

    __$styleInject(`.vue-html5-editor,.vue-html5-editor *{box-sizing:border-box}.....省略很長的程式碼......)  

分別用下面兩個代替:

1.元件的字串模板

    var  temlate$9=`  
     <div class="vue-html5-editor" :class="{'full-screen':fullScreen}" :style="{'z-index':zIndex}">  
           
         <div class="content" ref="content" :style="contentStyle" contenteditable  
              @click="toggleDashboard(dashboard)"></div>  
                
         <div class="toolbar" :style="{'z-index':zIndex+1}" ref="toolbar">  
           <ul>  
             <template v-for="module in modules">  
               <li :title="locale[module.i18n]" @click="activeModule(module)"><span class="icon"  
                                                                                    :class="module.icon"></span>  
                 <template v-if="showModuleName === undefined ? defaultShowModuleName : showModuleName">  
                    {{locale[module.i18n]}}   
                 </template>  
               </li>  
             </template>  
           </ul>  
           <div class="dashboard" v-show="dashboard" ref="dashboard">  
             <keep-alive>  
               <div v-show="dashboard" :is="dashboard"></div>  
             </keep-alive>  
           </div>  
         </div>  
           
       </div>  
     `  

和  2.主要的樣式字串

 `
  .vue-html5-editor, .vue-html5-editor * {
    box-sizing: border-box
  }

  .vue-html5-editor {
    font-size: 14px;
    line-height: 1.5;
    background-color: #fff;
    color: #333;
    border: 1px solid #ddd;
    text-align: left;
    border-radius: 5px;
    overflow: hidden
  }

  .vue-html5-editor.full-screen {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    right: 0 !important;
    border-radius: 0
  }

  .vue-html5-editor > .toolbar {
    position: relative;
    background-color: inherit;
    border-top:1px solid #ccc
  }

  .vue-html5-editor > .toolbar > ul {
    list-style: none;
    padding: 0;
    margin: 0;
    border-bottom: 1px solid #ddd
  }

  .vue-html5-editor > .toolbar > ul > li {
    display: inline-block;
    cursor: pointer;
    text-align: center;
    line-height: 36px;
    padding: 0 10px
  }

  .vue-html5-editor > .toolbar > ul > li .icon {
    height: 16px;
    width: 16px;
    display: inline-block;
    vertical-align: middle
  }

  .vue-html5-editor > .toolbar > .dashboard {
    background-color: inherit;
    border-top: 1px solid #ddd;
    padding: 10px;
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    overflow: auto
  }

  .vue-html5-editor > .toolbar > .dashboard input[type=text], .vue-html5-editor > .toolbar > .dashboard input[type=number], .vue-html5-editor > .toolbar > .dashboard select {
    padding: 6px 12px;
    color: inherit;
    background-color: transparent;
    border: 1px solid #ddd;
    border-radius: 5px
  }

  .vue-html5-editor > .toolbar > .dashboard input[type=text]:hover, .vue-html5-editor > .toolbar > .dashboard input[type=number]:hover, .vue-html5-editor > .toolbar > .dashboard select:hover {
    border-color: #bebebe
  }

  .vue-html5-editor > .toolbar > .dashboard input[type=text][disabled], .vue-html5-editor > .toolbar > .dashboard input[type=text][readonly], .vue-html5-editor > .toolbar > .dashboard input[type=number][disabled], .vue-html5-editor > .toolbar > .dashboard input[type=number][readonly], .vue-html5-editor > .toolbar > .dashboard select[disabled], .vue-html5-editor > .toolbar > .dashboard select[readonly] {
    background-color: #eee;
    opacity: 1
  }

  .vue-html5-editor > .toolbar > .dashboard input[type=text][disabled], .vue-html5-editor > .toolbar > .dashboard input[type=number][disabled], .vue-html5-editor > .toolbar > .dashboard select[disabled] {
    cursor: not-allowed
  }

  .vue-html5-editor > .toolbar > .dashboard button {
    color: inherit;
    background-color: inherit;
    padding: 6px 12px;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    border: 1px solid #ddd;
    border-radius: 5px;
    margin-right: 4px;
    margin-bottom: 4px
  }

  .vue-html5-editor > .toolbar > .dashboard button:hover {
    border-color: #bebebe
  }

  .vue-html5-editor > .toolbar > .dashboard button[disabled] {
    cursor: not-allowed;
    opacity: .68
  }

  .vue-html5-editor > .toolbar > .dashboard button:last-child {
    margin-right: 0
  }

  .vue-html5-editor > .toolbar > .dashboard label {
    font-weight: bolder
  }

  .vue-html5-editor > .content {
    overflow: scroll;
    padding: 10px;
    max-height:500px
  }

  .vue-html5-editor > .content:focus {
    outline: 0
  }`

修改的地方不多,請參照具體的樣式自己配置自定義的模板。

我這個修改完以後顯示如下。而且輸入很長的資料後,只是內容區變成上下滾動的,工具欄不動。

c.移動端圖片上傳的處理

這裡我沒有配置服務端的上傳檔案的介面,所以我就直接將圖片轉成base64的來處理。但是這樣會有問題,在PC端圖片是可以修改大小的,但是在移動端上傳的圖片上是原圖,也就是很大,圖文混排的時候非常不好看,也不好編輯。這時候我做的處理挺投機取巧的,但是也是可行的方法。我們知道change函式是在內容發生變化時觸發的,這時候我們只要將獲取到的內容做一下修改即可,看程式碼:

    updateData(e = ''){  
       let c1 = e.replace(/<img width="100%"/g, '<img');  
       let c2 = c1.replace(/<img/g, '<img width="100%"');  
       this.content = c2;  
     }  

這樣就OK了。

看移動端的效果圖:圖片是按寬100%自適應縮放的。效果達到。

主要參考  /src/pages/tool/RichTextTest.vue (使用),/src/init-plugins.js(配置) 

如果有bug歡迎指正,不勝感激;如果對您有幫助,給個star,謝謝~~