vue-quill-editor 使用

725 阅读2分钟

前言

使用vue-quill-editor中的一个收获

一、一些相关的文档

github仓库 官网文档 中文文档 npm包

通过在这些文档中的阅读,应该可以了解了怎么使用,如果想要在项目中自定使用,那就需要download下来跑一跑了

二、在项目使用

1、安装 vue-quill-editor

首先需要在你的终端执行下面的命令

npm install vue-quill-editor —-save

2、组件的使用

1)这里是局部引用。

import { quillEditor, Quill }  from 'vue-quill-editor';
// require styles
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

需要在局部引入样式,否则样式不生效

import { quillEditor, Quill }  from 'vue-quill-editor';
 
export default {
  components: {
    quillEditor
  }
}

需要在你的components中注册一下。

2)这里是全局引用。

import Vue from 'vue'
import QuillEditor from 'vue-quill-editor'

// require styles 必须有样式引入
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

Vue.use(QuillEditor)

在 main.js 中将 vue-quill-editor 引入项目。

详细的配置请参考 Quill 官网

3)在vue中的使用

这里以全局引入为例

// editor 组件
<template>
	<div>
		<!-- bidirectional data binding(双向数据绑定) -->
		<!-- 全局引入组建名称 必须为quill-editor -->
		<!-- style 样式是合并空格的作用,在editor中对多个连续空格换行处理,根据需求进行添加/删除 -->
		<quill-editor
			style="white-space: pre-line; word-wrap: break-word"
			:disabled="disabled" 
			v-model="content"
			ref="myQuillEditor"
			:options="editorOption"
			@blur="onEditorBlur($event)"
			@focus="onEditorFocus($event)"
			@change="onEditorChange($event)"
			@input="handleModel"
		>
			<div :id="`toolbar${editorKey}`" :slot="'toolbar'">
				<el-button
				   :disabled="disabled"
				   class="ql-custom-button"
				   size="small"
				   @click="openDialog"
				>
				   打开弹框
				</el-button>
			</div>
		</QuillEditor>
		<el-dialog
			title="提示"
			:visible.sync="dialogVisible"
			width="30%"
			:before-close="handleClose"
		>
			<span>这是一段信息</span>
			<el-button @click="insert('插入第一名称')">插入第一名称</el-button>
			<span slot="footer" class="dialog-footer">
				<el-button @click="dialogVisible = false">取 消</el-button>
				<el-button 
					type="primary" 
					@click="dialogVisible = false"
				>
					确 定
				</el-button>
			</span>
		</el-dialog>
	</div>
 </template>

maxlength 限制最大输入字数,通过compositionstart,compositionend 事件对拼音输入文字超长时特殊处理

// editor 组件
<script>
export default {
    model: {
        prop: "modelValue",
        event: "update:modelValue",
    },
    props: {
        modelValue: {
            type: String,
            required: true,
            default() {
                return "";
            },
        },
        editorKey: {
            type: String,
        },
        disabled: {
            type: Boolean,
        },
        maxlength: {
            type: Number,
            default: 0
        }
    },
    computed: {
        editor() {
            return this.$refs.myQuillEditor.quill;
        },
        editorOption() {
            return {
                placeholder: "请输入",
                modules: {
                    toolbar: `#toolbar${this.editorKey}`,
                },
            };
        },
    },
    watch: {
        modelValue(val) {
            this.content = val;
        },
    },
    data() {
        return {
            content: this.modelValue,
            // 编辑器焦点位置
            quillIndex: 0,
            // 编辑器选中的长度
            quillLength: '',
            // 编辑器选中的文本
            quillSelectionText: "",
            // 动态参数
            params: [],
            // 内容字符总长
            count: 0,
            dialogVisible: false,
            composing: false,
        };
    },
    mounted() {
		// 获取 Quill 实例
        const editor = this.editor;
        if (editor) {
            // 通过 Quill 的 root 元素来添加事件监听
            editor.root.addEventListener('compositionstart', this.onCompositionStart);
            editor.root.addEventListener('compositionend', this.onCompositionEnd);
        }
	},
    methods: {
        // 失去焦点事件
        onEditorBlur() {
            if (!this.disabled) {
                // do something 
            }
        },
        // 获得焦点事件
        onEditorFocus($event) {
            if ($event) {
                let { index, length } = $event.getSelection();
                this.quillIndex = index;
                this.quillLength = length || 0;
            }
        },
        // 内容改变事件
        onEditorChange({ quill, html, text }) {
            // 光标插入失去焦点前的位置
            if (text) {
                if (this.editor.getSelection()) {
                    this.quillIndex = this.editor.getSelection().index;
                } else {
                    // 末尾有一个\n字符
                    this.quillIndex = text && (text.length - 1);
                    this.quillLength = 0;
                }
            }
            if ((text.length > this.maxlength) && !this.composing) {
                let ExceedsLength = text.length - this.maxlength;
                this.editor.deleteText(this.maxlength, ExceedsLength);
            }
            this.$emit("onEditorChange", text);
        },
        handleModel(e) {
            this.$emit("update:modelValue", e);
        },
        openDialog(type) {
	        this.dialogVisible = true;
        },
        // 根据光标位置插入内容;有选中内容,删除后替换;
        insert(param) {
            if (this.editor.getSelection()) {
                let { index, length } = this.editor.getSelection();
                if (length) {
                    this.editor.deleteText(index, length);
                } else {
                }
                this.editor.insertText(this.quillIndex, param);
            } else {
                if (this.quillLength) {
                    let index = this.quillIndex;
                    this.editor.deleteText(this.quillIndex, this.quillLength);
                    this.editor.insertText(index, param);
                } else {
                    this.editor.insertText(this.quillIndex, param);
                }
            }
            this.$emit("onEditorChange", this.editor.getText());
        },
        handleClose(done) {
            this.$confirm("确认关闭?")
                .then((_) => {
                    done();
                })
                .catch((_) => {});
        },
        onCompositionStart(val) {
            this.composing = true;
        },
        onCompositionEnd(val) {
            this.composing = false;
            if ((this.maxlength && (this.editor.getText().length > this.maxlength))) {
                let ExceedsLength = this.editor.getText().length - this.maxlength;
                this.editor.deleteText(this.maxlength, ExceedsLength);
            }
        }
    },
};
</script>

可以结合element ui 中el-form使用,校验时用el-form-item的rules进行校验

// 父组件
<div v-for="(value, key) in editorList" :key="key">
    <editor
        :editorKey="key"
        v-model="value.html"
        @onEditorChange="
            editorChange(
                $event,
                value,
                key
            )
        "
        :maxlength="20"
    ></editor>
</div>

在父组件中循环使用

// 父组件
data() {
    return {
        editorList: {
            1: {
                html: "",
                content: "",
            },
            2: {
                html: "",
                content: "",
            }
        },
    };
},
methods: {
	// 保存纯文本内容
    editorChange(content, value, key) {
        this.$set(value, "content", content);
        // this.$refs.formDataRef.validateField([
        //     `card_content.${key}.html`,
        // ]);
    },
}

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

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

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