大家好,我是半虹,这篇文章来讲如何在 Vue 中引入 Quill \text{Quill} Quill


1、背景介绍

在前端开发中,富文本编辑器是一个重要的功能组件,方便用户创建和编辑格式丰富的文本内容

目前在市面上有着很多富文本编辑器组件,其中 Quill \text{Quill} Quill 凭着易于上手、功能丰富逐渐地成为主流选择之一


最近做项目时遇到一个紧急的需求,那就是一天之内在原有项目当中,增加一个富文本编辑功能

经过调研之后最终还是选择 Quill \text{Quill} Quill ,并且在网上搜集了很多资料,踩了很多坑后才能够最终完成


这篇文章将会从零开始,介绍如何在 Vue2Vue3 中引入 Quill \text{Quill} Quill ,并介绍 Quill \text{Quill} Quill 的最基本配置

这里之所以要从零开始,就是希望能最快速地带大家上手用 Quill \text{Quill} Quill ,以避免踩各种奇奇怪怪的坑


2、在 Vue2 中引入 Quill

在这部分,我们首先通过 Vue 脚手架 @vue/cli 新建 Vue2 项目 ,然后在该项目中引入 Quill \text{Quill} Quill

在此之前,先说一下环境 :

  • Node12.18.2
  • NPM6.14.5
  • @vue/cli4.5.12

准备就绪,下面正式开始:

  1. 创建项目

    我们可以在命令行中通过以下命令新创建一个 Vue2 项目

    > vue create vue2-quill-demo
    

    输入上述的命令后,会有三个选项,这里我们选择第一个,创建默认的 Vue2 项目

    ? Please pick a preset: (Use arrow keys)
    > Default ([Vue 2] babel, eslint)
      Default ([Vue 3] babel, eslint)
      Manually select features
    

    执行上述的选择后,等待完成即可,新建的目录结构如下:

    + vue2-quill-demo
        + node_modules      // 外部模块目录
        + public            // 项目资源目录
        + src               // 源码目录
            + assets        // 组件资源目录
            + components    // 公共组件目录
            - App.vue       // 根组件
            - main.js       // 主入口
        - babel.config.js   // 编译配置文件
        - package-lock.json // 项目配置文件 (自动生成)
        - package.json      // 项目配置文件 (手动维护)
        - README.md         // 项目描述文件
    
  2. 安装模块

    我们既可以直接安装 quill ,也可以选择安装其在 Vue2 之上的封装 vue-quill-editor

    在这里我们选择后者,下面以 npm 的方式安装,安装后的模块存放在 node_modules 目录

    > npm install --save vue-quill-editor@3.0.6
    
  3. 注册模块

    使用组件之前要先进行注册,注册组件的方式有两种 ,分别是全局注册和局部注册

    全局注册:在主入口文件添加以下代码,即 main.js,之后可以在任意页面中使用

    import Vue from 'vue'
    import App from './App.vue'
    
    // 新增:导入组件
    import VueQuillEditor from 'vue-quill-editor' // 导入 VueQuillEditor,不带 {}
    
    // 新增:导入样式
    import 'quill/dist/quill.core.css'
    import 'quill/dist/quill.snow.css'
    import 'quill/dist/quill.bubble.css'
    
    // 新增:注册组件
    Vue.use(VueQuillEditor) // 这里用的是 use
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    

    局部注册:在需要的页面添加以下代码,如 xxx.vue,之后只能在当前页面中使用

    <script>
    // 新增:导入组件
    import { quillEditor } from 'vue-quill-editor' // 导入 quillEditor,带有 {}
    
    // 新增:导入样式
    import 'quill/dist/quill.core.css'
    import 'quill/dist/quill.snow.css'
    import 'quill/dist/quill.bubble.css'
    
    export default {
      // 新增:注册组件
      components : {
        quillEditor
      }
    }
    </script>
    
  4. 使用模块

    之后,在需要引入组件的页面,添加以下代码即可,为了演示方便,以下示例直接在 App.vue 中引入

    <template>
      <div id="app">
        <quill-editor
          ref="QuillEditor"
          v-model="content"
          v-bind:options="options"
        />
        <button v-on:click="print">Print Content In Console</button>
      </div>
    </template>
    
    <script>
    // 默认已全局注册
    // 如果是局部注册,则需要按照上述所说,在当前页面添加代码
    
    export default {
      name: 'App',
      data() {
        return {
          content: "", // 内容
          options: {}, // 配置
        }
      },
      methods: {
        print: function() {
          console.log(this.content)
        }
      }
    }
    </script>
    
    

    最后,可通过以下命令在本地上运行项目

    > npm run serve
    

    此时,在浏览器中打开指定端口即可看到渲染效果如下

    渲染效果

3、在 Vue3 中引入 Quill

在这部分,我们还是通过 Vue 脚手架 @vue/cli 新建 Vue3 项目 ,然后在该项目中引入 Quill \text{Quill} Quill

与上类似,环境还是一样 :

  • Node12.18.2
  • NPM6.14.5
  • @vue/cli4.5.12

不仅如此,步骤也差不多:

  1. 创建项目

    我们还是在命令行中通过相同命令新创建一个 Vue3 项目

    > vue create vue3-quill-demo
    

    输入上述的命令后,会有三个选项,这里我们选择第二个,创建默认的 Vue3 项目

    ? Please pick a preset: (Use arrow keys)
      Default ([Vue 2] babel, eslint)
    > Default ([Vue 3] babel, eslint)
      Manually select features
    

    执行上述的选择后,等待完成即可,目录结构也是一样的

    + vue3-quill-demo
        + node_modules      // 外部模块目录
        + public            // 项目资源目录
        + src               // 源码目录
            + assets        // 组件资源目录
            + components    // 公共组件目录
            - App.vue       // 根组件
            - main.js       // 主入口
        - babel.config.js   // 编译配置文件
        - package-lock.json // 项目配置文件 (自动生成)
        - package.json      // 项目配置文件 (手动维护)
        - README.md         // 项目描述文件
    
  2. 安装模块

    我们既可以直接安装 quill,也可以选择安装其在 Vue3 之上的封装 @vueup/vue-quill

    同样的我们选择后者 ,但是要注意,其在 Vue2Vue3 之上的封装是不同的,不要装错

    > npm install --save @vueup/vue-quill@1.2.0
    
  3. 注册模块

    使用组件之前要先进行注册,注册组件的方式有两种 ,分别是全局注册和局部注册

    全局注册:在主入口文件添加以下代码,即 main.js,之后可以在任意页面中使用

    import { createApp } from 'vue'
    import App from './App.vue'
    
    // 新增:导入组件
    import { QuillEditor } from '@vueup/vue-quill' // 导入 QuillEditor,带有 {}
    
    // 新增:导入样式
    import '@vueup/vue-quill/dist/vue-quill.snow.css'
    import '@vueup/vue-quill/dist/vue-quill.bubble.css'
    
    const app = createApp(App)
    
    // 新增:注册组件
    app.component('QuillEditor', QuillEditor) // 这里用的是 component
    
    app.mount('#app')
    

    局部注册:在需要的页面添加以下代码,如 xxx.vue,之后只能在当前页面中使用

    <script>
    // 新增:导入组件
    import { QuillEditor } from '@vueup/vue-quill' // 导入 QuillEditor,带有 {}
    
    // 新增:导入样式
    import '@vueup/vue-quill/dist/vue-quill.snow.css'
    import '@vueup/vue-quill/dist/vue-quill.bubble.css'
    
    export default {
      // 新增:注册组件
      components : {
        QuillEditor
      }
    }
    </script>
    
  4. 使用模块

    之后,在需要引入组件的页面,添加以下代码即可,为了演示方便,以下示例直接在 App.vue 中引入

    <template>
      <div>
        <!-- 注意区别,content 和 contentType -->
        <quill-editor
          ref="QuillEditor"
          v-model:content="content"
          v-bind:options="options"
          contentType="html"
        />
        <button v-on:click="print">Print Content In Console</button>
      </div>
    </template>
    
    <script>
    // 默认已全局注册
    // 如果是局部注册,则需要按照上述所说,在当前页面添加代码
    
    export default {
      name: 'App',
      data() {
        return {
          content: "", // 内容
          options: {}, // 配置
        }
      },
      methods: {
        print: function() {
          console.log(this.content)
        }
      }
    }
    </script>
    
    

    最后,可通过以下命令在本地上运行项目,并打开浏览器验证效果

    > npm run serve
    

    注意,你可能遇到下面的报错:

    Error: @vitejs/plugin-vue requires vue (>=3.2.13) or @vue/compiler-sfc to be present in the dependency tree.
    

    那么只要按照要求去升级就行:

    > npm install vue@3.2.26
    

4、进阶配置

好了,最后说一下 Quill \text{Quill} Quill 的一些基础配置,首先要说的是 Quill \text{Quill} Quill 绑定的 options 配置项

<script>

const toolbarOptions = [ // 工具栏想要显示什么,就要在这里加上什么
  ["bold", "italic", "underline", "strike"],       // 粗体、斜体、下划线、删除线
  ["blockquote", "code-block"],                    // 引用、代码
  [{ "header": 1 }, { "header": 2 }],              // 一级标题、二级标题
  [{ "list": "ordered" }, { "list": "bullet" }],   // 有序列表、无序列表
  [{ "script": "sub" }, { "script": "super" }],    // 下标、上标
  [{ "indent": "-1" }, { "indent": "+1" }],        // 左缩进、右缩进
  [{ "direction": "rtl"}],                         // 文字方向
  [{ "size": ["small", false, "large", "huge"] }], // 字体大小
  [{ "header": [1, 2, 3, 4, 5, 6, false] }],       // 标题大小
  [{ "color": [] }, { "background": [] }],         // 字体颜色、背景颜色
  [{ "font": [] }],                                // 字体种类
  [{ "align": [] }],                               // 对齐方式
  ["clean"],                                       // 清除格式
  ["link", "image", "video"],                      // 链接、图片、视频
]

export default {
  // ...
  data() {
    return {
      content: "", // 内容
      options: {   // 配置
        placeholder: "please input here",
        theme: "snow",
        modules: {
          toolbar: {
            container: toolbarOptions, // 显示配置
            handlers: {                // 逻辑配置
              // "image": this.handleImageButton, // 自定义 image 按钮的处理函数
              // "clean": this.handleCleanButton, // 自定义 clean 按钮的处理函数
              // ...
            }
          }
        }
      }
    }
  },
  // methods: {
  //   handleImageButton() {
  //     
  //   },
  //   handleCleanButton() {
  //     
  //   },
  // },
}

</script>

另外,contentType 的取值也非常重要,因为这会影响 content 保存值的类型

  1. contentType 设置为 text,则 content 保存值的类型为 text

    你可以看到富文本编辑器中添加的格式都不会保存,只有纯文本内容

    text
  2. contentType 设置为 html,则 content 保存值的类型为 html

    你可以看到富文本编辑器中添加的格式都会以 html 标签的形式保存

    html
  3. contentType 设置为 delta,则 content 保存值的类型为 Delta 对象,这是官方最推荐的形式

    delta

    关于 Delta 对象的详细说明可参考官方文档 ,下面我简单介绍一些基础概念

    Delta 对象本质上就是 JSON 格式,其只有 ops 属性,属性的值是对象数组

    其中的 每个对象可以用 insert 属性指定内容 以及用 attributes 属性指定格式

    {
      ops: [
        { insert: '加粗文字\n', attributes: { bold: true } },
        { insert: '普通文字\n' },
        { insert: '斜体文字\n', attributes: { italic: true } }
      ]
    }
    

    另外,对于非文本的内容,例如图片或者是视频,插入值可以是对象

    {
      ops: [
        { insert: { image: 'https://cdn.pixabay.com/photo/2017/08/07/22/10/lake-2608425_1280.jpg' } }
      ]
    }
    

    还有与换行符相关的格式,例如标题或者是列表,以用于描述整行的格式,这称为行级格式

    Quill \text{Quill} Quill 中,所有文档都以换行符来结尾,这样始终会有一个字符的位置用于设置当行格式

    {
      ops: [
        { insert: '标题' },
        { insert: '\n', attributes: { header: 3 } }
      ]
    }
    

    上面我们说过, Delta \text{Delta} Delta 对象 ops 属性的值是对象数组,其中的对象实际上就是以下 Op 接口的实例

    interface Op {
        insert?: string | object;  // 要插入的内容
        delete?: number;           // 要删除的字符数
        retain?: number;           // 要保留的字符数
        attributes?: AttributeMap; // 所指定的格式
    }
    
    interface AttributeMap {
        [key: string]: any;
    }
    

    那么,当我们想给 content 赋值时,我们可以采取以下方法

    import { Delta } from '@vueup/vue-quill';
    
    // Delta 对象构造方法接收 Op 对象数组作为参数
    
    this.content = new Delta([{
      insert: 'Hello', attributes: { bold: true }
    }, {
      insert: 'World', attributes: { underline: true }
    }]);
    

    另外,当我们要对 content 修改时,我们可以采取以下方法

    // 假设现在我们有一个小需求
    // 选中某段文本并将其替换为指定的内容
    
    import { Delta } from '@vueup/vue-quill';
    
    const value = '指定的内容';
    
    // 获取光标位置
    const range = this.$refs.QuillEditor.getQuill().getSelection(true);
    
    // 构造修改内容
    const todos = new Delta()
                    .retain(range.index)  // 保留光标之前的内容,其实就是将光标移动到当前位置
                    .delete(range.length) // 删除光标选中的内容
                    .insert(value);       // 插入新的指定的内容
    
    // 合并修改内容
    this.content = this.content.compose(todos);
    


好啦,本文到此结束,感谢您的阅读!

如果你觉得这篇文章有需要修改完善的地方,欢迎在评论区留下你宝贵的意见或者建议

如果你觉得这篇文章还不错的话,欢迎点赞、收藏、关注,你的支持是对我最大的鼓励 (/ω\)

Logo

前往低代码交流专区

更多推荐