zoukankan      html  css  js  c++  java
  • vue-quill-editor富文本编辑器 中文翻译组件,编辑与展示

    vue项目中用到了富文本编辑器,网上找了一些,觉得vue-quill-editor最好用,

    ui简洁,功能也好配,够用了,文档不好读,有些小细节需要自己注意,我懒得分析,就封装成了组件

    大家用的时候直接cope组件,但是不要cope文章呀~~~

    需要注意的是编辑器保存的格式,我们在用div展示的时候,有些格式无效,所以我也同样封装了供页面展示的组件

    首先安装包

    npm 安装 vue-quill-editor

    这是编辑器效果图:

    这是编辑器的组件代码:

    代码比较多,我折叠起来了

      1 <template>
      2   <div class="editor_wrap">
      3     <!-- 图片上传组件辅助-->
      4     <el-upload
      5       class="avatar-uploader"
      6       :action="serverUrl"
      7       name="image"
      8       :headers="header"
      9       multiple
     10       :show-file-list="false"
     11       :on-success="uploadSuccess"
     12       :on-error="uploadError"
     13       :before-upload="beforeUpload"
     14     ></el-upload>
     15     <quill-editor
     16       v-loading="quillUpdateImg"
     17       class="editor"
     18       v-model="content"
     19       ref="myQuillEditor"
     20       :options="editorOption"
     21       @blur="onEditorBlur($event)"
     22       @focus="onEditorFocus($event)"
     23       @change="onEditorChange($event)"
     24     ></quill-editor>
     25   </div>
     26 </template>
     27 <script>
     28 import { quillEditor } from "vue-quill-editor";
     29 import "quill/dist/quill.core.css";
     30 import "quill/dist/quill.snow.css";
     31 import "quill/dist/quill.bubble.css";
     32 // 工具栏配置
     33 const toolbarOptions = [
     34   ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
     35   ["blockquote", "code-block"], // 引用  代码块
     36   // [{ header: 1 }, { header: 2 }], // 1、2 级标题
     37   [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
     38   [{ script: "sub" }, { script: "super" }], // 上标/下标
     39   [{ indent: "-1" }, { indent: "+1" }], // 缩进  2
     40   [{ color: [
     41     '#ffffff', '#ffd7d5', '#ffdaa9', '#fffed5', '#d4fa00', '#73fcd6', '#a5c8ff', '#ffacd5', '#ff7faa',
     42     '#d6d6d6', '#ffacaa', '#ffb995', '#fffb00', '#73fa79', '#00fcff', '#78acfe', '#d84fa9', '#ff4f79',
     43     '#b2b2b2', '#d7aba9', '#ff6827', '#ffda51', '#00d100', '#00d5ff', '#0080ff', '#ac39ff', '#ff2941',
     44     '#888888', '#7a4442', '#ff4c00', '#ffa900', '#3da742', '#3daad6', '#0052ff', '#7a4fd6', '#d92142',  
     45     '#000000', '#7b0c00', '#ff0000', '#d6a841', '#407600', '#007aaa', '#021eaa', '#797baa', '#ab1942'
     46   ] }, { background: [
     47     '#ffffff', '#ffd7d5', '#ffdaa9', '#fffed5', '#d4fa00', '#73fcd6', '#a5c8ff', '#ffacd5', '#ff7faa',
     48     '#d6d6d6', '#ffacaa', '#ffb995', '#fffb00', '#73fa79', '#00fcff', '#78acfe', '#d84fa9', '#ff4f79',
     49     '#b2b2b2', '#d7aba9', '#ff6827', '#ffda51', '#00d100', '#00d5ff', '#0080ff', '#ac39ff', '#ff2941',
     50     '#888888', '#7a4442', '#ff4c00', '#ffa900', '#3da742', '#3daad6', '#0052ff', '#7a4fd6', '#d92142',  
     51     '#000000', '#7b0c00', '#ff0000', '#d6a841', '#407600', '#007aaa', '#021eaa', '#797baa', '#ab1942'
     52   ] }], // 字体颜色、字体背景颜色
     53   [{ size: ["small", false, "large", "huge"] }], // 字体大小 2
     54   [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
     55   [{ font: [] }], // 字体种类 2
     56   [{'direction': 'rtl'}],               // 文本方向  2
     57   [{ align: [] }], // 对齐方式 2
     58   ["clean"], // 清除文本格式
     59   ["link", "image", "video"] // 链接、图片、视频
     60 ];
     61 export default {
     62   props: {
     63     /*编辑器的内容*/
     64     value: null,
     65     /*图片大小*/
     66     maxSize: {
     67       type: Number,
     68       default: 4000 //kb
     69     }
     70   },
     71 
     72   components: {
     73     quillEditor
     74   },
     75   watch: {
     76     value(val) {
     77       this.content = this.value
     78     }
     79   },
     80 
     81   data() {
     82     return {
     83       content: this.value,
     84       quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
     85       editorOption: {
     86         theme: "snow", // or 'bubble'
     87         placeholder: "您想说点什么?",
     88         modules: {
     89           toolbar: {
     90             container: toolbarOptions,
     91             handlers: {
     92               image: function(value) {
     93                 if (value) {
     94                   // 触发input框选择图片文件
     95                   document.querySelector(".avatar-uploader input").click();
     96                 } else {
     97                   this.quill.format("image", false);
     98                 }
     99               },
    100               // link: function(value) {
    101               //   if (value) {
    102               //     var href = prompt('请输入url');
    103               //     this.quill.format("link", href);
    104               //   } else {
    105               //     this.quill.format("link", false);
    106               //   }
    107               // },
    108             }
    109           }
    110         }
    111       },
    112       serverUrl: process.env.VUE_APP_API_URL + "config/upload", // 这里写你要上传的图片服务器地址
    113       header: {
    114         token: localStorage.getItem("token")
    115       } 
    116     };
    117   },
    118 
    119   methods: {
    120     onEditorBlur() {
    121       //失去焦点事件
    122     },
    123     onEditorFocus() {
    124       //获得焦点事件
    125     },
    126     onEditorChange({ editor, html, text }) {
    127       this.content = html;
    128       //内容改变事件
    129       this.$emit("textareaData", this.content);
    130     },
    131 
    132     // 富文本图片上传前
    133     beforeUpload() {
    134       // 显示loading动画
    135       this.quillUpdateImg = true;
    136     },
    137 
    138     uploadSuccess(res, file) {
    139       // res为图片服务器返回的数据
    140       // 获取富文本组件实例
    141       let quill = this.$refs.myQuillEditor.quill;
    142       // 如果上传成功
    143       if (res.error == 0) {
    144         // 获取光标所在位置
    145         let length = quill.getSelection().index;
    146         // 插入图片  res.url为服务器返回的图片地址
    147         quill.insertEmbed(length, "image", res.info.img_url);
    148         // 调整光标到最后
    149         quill.setSelection(length + 1);
    150       } else {
    151         this.$message.error("图片插入失败");
    152       }
    153       // loading动画消失
    154       this.quillUpdateImg = false;
    155     },
    156     // 富文本图片上传失败
    157     uploadError() {
    158       // loading动画消失
    159       this.quillUpdateImg = false;
    160       this.$message.error("图片插入失败");
    161     }
    162   }
    163 };
    164 </script> 
    165 
    166 <style scoped>
    167 .editor_wrap /deep/ .avatar-uploader {
    168   display: none;
    169 }
    170 .editor_wrap /deep/ .editor {
    171   line-height: normal !important;
    172   height: 270px;
    173   margin-bottom: 60px;
    174 }
    175 .editor_wrap /deep/ .editor .ql-bubble .ql-editor a {
    176   color: #136ec2;
    177 }
    178 .editor_wrap /deep/ .editor img {
    179   max- 720px;
    180   margin:10px;
    181 }
    182 .editor_wrap /deep/ .ql-snow .ql-color-picker .ql-picker-options {
    183   padding: 3px 5px;
    184    192px;
    185 }
    186 .editor_wrap /deep/ .ql-snow .ql-tooltip[data-mode="link"]::before {
    187   content: "请输入链接地址:";
    188 }
    189 .editor_wrap /deep/ .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    190   border-right: 0px;
    191   content: "保存";
    192   padding-right: 0px;
    193 }
    194 
    195 .editor_wrap /deep/ .ql-snow .ql-tooltip[data-mode="video"]::before {
    196   content: "请输入视频地址:";
    197 }
    198 
    199 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label::before,
    200 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item::before {
    201   content: "14px";
    202 }
    203 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
    204 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
    205   content: "10px";
    206 }
    207 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
    208 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
    209   content: "18px";
    210 }
    211 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
    212 .editor_wrap /deep/ .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
    213   content: "32px";
    214 }
    215 
    216 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label::before,
    217 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item::before {
    218   content: "文本";
    219 }
    220 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
    221 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
    222   content: "标题1";
    223 }
    224 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
    225 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
    226   content: "标题2";
    227 }
    228 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
    229 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
    230   content: "标题3";
    231 }
    232 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
    233 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
    234   content: "标题4";
    235 }
    236 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
    237 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
    238   content: "标题5";
    239 }
    240 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
    241 .editor_wrap /deep/ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
    242   content: "标题6";
    243 }
    244 
    245 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label::before,
    246 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item::before {
    247   content: "标准字体";
    248 }
    249 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
    250 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
    251   content: "衬线字体";
    252 }
    253 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
    254 .editor_wrap /deep/ .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
    255   content: "等宽字体";
    256 }
    257 </style>
    View Code

    这是供页面展示的效果图:

    这是供页面展示的组件代码:

    代码比较多,同样我折叠起来了

     1 <template>
     2   <div class="editor_wrap">
     3     <quill-editor
     4       class="editor"
     5       v-model="content"
     6       ref="myQuillEditor"
     7       :options="editorOption"
     8       @focus="onEditorFocus($event)"
     9     ></quill-editor>
    10   </div>
    11 </template>
    12 <script>
    13 // 工具栏配置
    14 const toolbarOptions = [];
    15 
    16 import { quillEditor } from "vue-quill-editor";
    17 import "quill/dist/quill.core.css";
    18 import "quill/dist/quill.snow.css";
    19 import "quill/dist/quill.bubble.css";
    20 
    21 export default {
    22   props: {
    23     /*编辑器的内容*/
    24     value: null
    25   },
    26   components: {
    27     quillEditor
    28   },
    29   watch: {
    30     value(val) {
    31       this.content = this.value;
    32     }
    33   },
    34   computed: {
    35     editor() {
    36       return this.$refs.myQuillEditor.quill;
    37     }
    38   },
    39   data() {
    40     return {
    41       content: this.value,
    42       editorOption: {
    43         theme: "bubble", // or 'bubble'
    44         placeholder: "您想说点什么?",
    45         modules: {
    46           toolbar: {
    47             container: toolbarOptions,
    48             handlers: {}
    49           }
    50         }
    51       }
    52     };
    53   },
    54   methods: {
    55     onEditorFocus(editor) {
    56       // 富文本获得焦点时的事件
    57       editor.enable(false); // 在获取焦点的时候禁用
    58     }
    59   }
    60 };
    61 </script> 
    62 
    63 <style scoped>
    64 .editor_wrap /deep/ .editor img {
    65   max- 720px;
    66   margin:10px;
    67 }
    68 .editor_wrap /deep/ .editor .ql-bubble .ql-editor a {
    69   color: #136ec2;
    70 }
    71 </style>
    View Code

     值得注意的是页面展示的时候,会有一个鼠标光标出现,目前我没有处理,欢迎大神们留言指导

  • 相关阅读:
    linux学习(一)
    Linux学习(用户管理)
    anyproxy mac安装
    python mitmproxy 代理
    Js常用方法map, sort
    echarts常用配置项【持续更新】
    【转】moment js 使用
    js Cannot assign to read only property 'exports' of object '#<Object>' at Modul,import 与module.exports混用问题
    a标签跳转referer漏洞
    element ui rate评分组建使用
  • 原文地址:https://www.cnblogs.com/jun-qi/p/11075836.html
Copyright © 2011-2022 走看看