vue 富文本编辑器

npm install -s vue-quill-editor

image.png

main.js

//引用富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
//引入富文本css
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//富文本编辑器添加实例
Vue.use(VueQuillEditor)

.vue 文件

<template>
  <el-form ref="formData" :model="formData" > 
       <el-form-item label="内容" prop="content"
          :rules="[
            { required: true, message: '请输入内容', trigger: 'change',}
          ]"
       >
          <quill-editor ref="quillEditor" :options="contOption"              
                  @change="contEditorChange($event)">
          </quill-editor>
       </el-form-item>
  </el-form>
</template>

<script>
import VueQuillEditor from 'vue-quill-editor';
var fonts = ['SimSun', 'SimHei','Microsoft-YaHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif'];
VueQuillEditor.Quill.imports['formats/font'].whitelist = fonts;
VueQuillEditor.Quill.register(VueQuillEditor.Quill.imports['formats/font']);
// 自定义字号的大小
var sizes = ['10px', '12px', '14px', '16px' ,'18px', '20px', '22px', '24px', '26px', '32px', '48px'];
VueQuillEditor.Quill.import("formats/size").whitelist = sizes;
VueQuillEditor.Quill.register(VueQuillEditor.Quill.imports['formats/size']);
const richTextModules = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线 -----['bold', 'italic', 'underline', 'strike']
  ['blockquote', 'code-block'], // 引用  代码块-----['blockquote', 'code-block']
  [{ header: 1 }, { header: 2 }], // 1、2 级标题-----[{ header: 1 }, { header: 2 }]
  [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表-----[{ list: 'ordered' }, { list: 'bullet' }]
  [{ script: 'sub' }, { script: 'super' }], // 上标/下标-----[{ script: 'sub' }, { script: 'super' }]
  [{ indent: '-1' }, { indent: '+1' }], // 缩进-----[{ indent: '-1' }, { indent: '+1' }]
  [{'direction': 'rtl'}], // 文本方向-----[{'direction': 'rtl'}]
  [{ size: sizes }], // 字体大小-----[{ size: ['small', false, 'large', 'huge'] }]
  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题-----[{ header: [1, 2, 3, 4, 5, 6, false] }]
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色-----[{ color: [] }, { background: [] }]
  [{ font: fonts }], // 字体种类-----[{ font: [] }]
  [{ align: [] }], // 对齐方式-----[{ align: [] }]
  ['link','image', 'video'] // 链接、图片、视频-----['link', 'image', 'video']
]

export default  {
  data() {
      var than_ = this;
      // 富文本编译器-自定义方法
        var customFun = {
            image: function image() { 
                // 上传图片
                let self = this;
                let fileInput = this.container.querySelector('input.ql-image[type=file]');
                let accept = 'image/png, image/jpg, image/gif, image/jpeg';
                if (fileInput === null) {
                    fileInput = document.createElement('input');
                    fileInput.setAttribute('type', 'file');
                    fileInput.setAttribute('accept', accept); // 文件格式
                    fileInput.classList.add('ql-image');
                    // 监听选择文件
                    fileInput.addEventListener('change', function () {
                        let file = fileInput.files[0];
                        fileInput.value = '';
                        let name = (file.name).substring((file.name).lastIndexOf(".")+1,(file.name).length);
                        if (name!='png' && name!='jpg' && name!='gif' && name!='jpeg') {
                            than_.$message.closeAll();
                            than_.$message.warning('文件格式错误,请重新上传');
                        } else {
                            let par = new FormData();
                            par.append("file", file);
                            // 调用接口
                            than_.$getInterfaceData(than_.$api.index.upload,'POST',par,'','',true).then(res=>{
                                // console.log('上传成功', res.data);
                                if(res.data.url){
                                     // 接口返回地址-添加到富文本中
                                    let length = self.quill.getSelection(true).index;
                                    self.quill.insertEmbed(length, 'image', res.data.url);
                                    self.quill.setSelection(length + 1);
                                }else{
                                    console.log('上传文件失败', res);
                                    than_.$message.closeAll();
                                    than_.$message.error(res.data.message);
                                }
                            });
                        }
                    });
                    this.container.appendChild(fileInput);
                }
                fileInput.click();
            },
            video: function video() { 
                // 上传视频
                let self = this;
                let fileInput = this.container.querySelector('input.ql-video[type=file]');
                let accept = '.mp4';
                if (fileInput === null) {
                    fileInput = document.createElement('input');
                    fileInput.setAttribute('type', 'file');
                    fileInput.setAttribute('accept', accept); // 文件格式
                    fileInput.classList.add('ql-video');
                    // 监听选择文件
                    fileInput.addEventListener('change', function () {
                        let file = fileInput.files[0];
                        fileInput.value = '';
                        let name = (file.name).substring((file.name).lastIndexOf(".")+1,(file.name).length);
                        if (name!='mp4') {
                            than_.$message.closeAll();
                            than_.$message.warning('文件格式错误,请重新上传');
                        } else {
                            let par = new FormData();
                            par.append("file", file);
                            // 调用接口
                            than_.$getInterfaceData(than_.$api.index.upload,'POST',par,'','',true).then(res=>{
                                // console.log('上传成功', res.data);
                                if(res.data.url){
                                    // 接口返回地址-添加到富文本中
                                    let length = self.quill.getSelection(true).index;
                                    self.quill.insertEmbed(length, 'video', res.data.url);
                                    self.quill.setSelection(length + 1);
                                }else{
                                    console.log('上传文件失败', res);
                                    than_.$message.closeAll();
                                    than_.$message.error(res.data.message);
                                }
                            });
                        }
                    });
                    this.container.appendChild(fileInput);
                }
                fileInput.click();
            }
        };
        return { 
            formData: {
              content: '',
            },
            // 富文本编译器
            contOption: {
                placeholder: "",
                theme: 'snow',
                modules: {
                    clipboard: {
                        // 粘贴版,处理粘贴时候的自带样式
                        matchers: [[Node.ELEMENT_NODE, this.HandleCustomMatcher]],
                    },
                    toolbar: {
                        container: richTextModules,  // 工具栏
                        handlers: customFun
                    }
                },
            },
        }
    },
  methods: {
        // 清除复制
        HandleCustomMatcher(node, Delta) {
            let ops = []
            Delta.ops.forEach(op => {
                if (op.insert && typeof op.insert === 'string') {
                    ops.push({
                        insert: op.insert,
                    })
                }
            })
            Delta.ops = ops
            return Delta
        },
        // 富文本-改变时-关闭校验
        contEditorChange(val) {
            if(val.html) {
                val.html = val.html.replace(/<p class="ql-align-center"><br><\/p>/g,'');
            }
            this.formData.content = val.html;
            if(this.formData.content) {
                this.$refs['formData'].clearValidate('content');
            }
        },
  }
</script>
<style scoped lang="less">
// 富文本编辑器-中文
/deep/ .quill_editor_box {
    line-height: normal !important;
    .ql-container {
        height: 150px;
    }
    .ql-snow.ql-toolbar input.ql-video[type=file],
    .ql-snow .ql-toolbar input.ql-video[type=file] {
        display: none;
    }
    .ql-snow .ql-tooltip {
        left: -90px !important;
        &::before {
            content: "请输入链接地址:";
        }
        a.ql-action::after {
            content: '修改';
        }
        a.ql-remove::before {
            content: '删除';
        }
    }
    .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
        content: '保存';
    }

    .ql-snow .ql-tooltip[data-mode=video]::before {
        content: "请输入视频地址:";
    }

    .ql-snow .ql-picker.ql-header {
        width: 65px;
        .ql-picker-label::before, .ql-picker-item::before {
            content: '文本';
        }
        .ql-picker-label[data-value="1"]::before, .ql-picker-item[data-value="1"]::before {
            content: '标题1';
        }
        .ql-picker-label[data-value="2"]::before, .ql-picker-item[data-value="2"]::before {
            content: '标题2';
        }
        .ql-picker-label[data-value="3"]::before, .ql-picker-item[data-value="3"]::before {
            content: '标题3';
        }
        .ql-picker-label[data-value="4"]::before, .ql-picker-item[data-value="4"]::before {
            content: '标题4';
        }
        .ql-picker-label[data-value="5"]::before, .ql-picker-item[data-value="5"]::before {
            content: '标题5';
        }
        .ql-picker-label[data-value="6"]::before, .ql-picker-item[data-value="6"]::before {
            content: '标题6';
        }
    }


    .ql-snow .ql-picker.ql-size {
        width: 60px;
        .ql-picker-label::before, .ql-picker-item::before {
            content: '16px';
        }
        .ql-picker-label[data-value="10px"]::before, .ql-picker-item[data-value="10px"]::before {
            content: '10px';
        }
        .ql-picker-label[data-value="12px"]::before, .ql-picker-item[data-value="12px"]::before {
            content: '12px';
        }
        .ql-picker-label[data-value="14px"]::before, .ql-picker-item[data-value="14px"]::before {
            content: '14px';
        }
        .ql-picker-label[data-value="16px"]::before, .ql-picker-item[data-value="16px"]::before {
            content: '16px';
        }
        .ql-picker-label[data-value="18px"]::before, .ql-picker-item[data-value="18px"]::before {
            content: '18px';
        }
        .ql-picker-label[data-value="20px"]::before, .ql-picker-item[data-value="20px"]::before {
            content: '20px';
        }
        .ql-picker-label[data-value="22px"]::before, .ql-picker-item[data-value="22px"]::before {
            content: '22px';
        }
        .ql-picker-label[data-value="24px"]::before, .ql-picker-item[data-value="24px"]::before {
            content: '24px';
        }
        .ql-picker-label[data-value="26px"]::before, .ql-picker-item[data-value="26px"]::before {
            content: '26px';
        }
        .ql-picker-label[data-value="32px"]::before, .ql-picker-item[data-value="32px"]::before {
            content: '32px';
        }
        .ql-picker-label[data-value="48px"]::before, .ql-picker-item[data-value="48px"]::before {
            content: '48px';
        }
    }
    .ql-editor {
        .ql-size-10px {
            font-size: 10px;
        }
        .ql-size-12px {
            font-size: 12px;
        }
        .ql-size-14px {
            font-size: 14px;
        }
        .ql-size-16px {
            font-size: 16px;
        }
        .ql-size-18px {
            font-size: 18px;
        }
        .ql-size-20px {
            font-size: 20px;
        }
        .ql-size-22px {
            font-size: 22px;
        }
        .ql-size-24px {
            font-size: 24px;
        }
        .ql-size-26px {
            font-size: 26px;
        }
        .ql-size-32px {
            font-size: 32px;
        }
        .ql-size-48px {
            font-size: 48px;
        }
    }
    
    
    .ql-snow .ql-picker.ql-font {
        width: auto;
        .ql-picker-label {
            box-sizing: border-box;
            padding-right: 20px;
        }
        .ql-picker-label[data-value=SimSun]::before, .ql-picker-item[data-value=SimSun]::before {
            content: "宋体";
            font-family: "SimSun" !important;
        }
        .ql-picker-label[data-value=SimHei]::before, .ql-picker-item[data-value=SimHei]::before {
            content: "黑体";
            font-family: "SimHei" !important;
        }
        .ql-picker-label[data-value=Microsoft-YaHei]::before, .ql-picker-item[data-value=Microsoft-YaHei]::before {
            content: "微软雅黑" !important;
            font-family: "Microsoft YaHei";
        }
        .ql-picker-label[data-value=KaiTi]::before, .ql-picker-item[data-value=KaiTi]::before {
            content: "楷体";
            font-family: "KaiTi"!important;
        }
        .ql-picker-label[data-value=FangSong]::before, .ql-picker-item[data-value=FangSong]::before {
            content: "仿宋";
            font-family: "FangSong" !important;
        }
        .ql-picker-label[data-value=Arial]::before, .ql-picker-item[data-value=Arial]::before {
            content: "Arial";
            font-family: "Arial" !important;
        }
        .ql-picker-label[data-value=Times-New-Roman]::before, .ql-picker-item[data-value=Times-New-Roman]::before {
            content: "Times New Roman";
            font-family: "Times New Roman" !important;
        }
        .ql-picker-label[data-value=sans-serif]::before, .ql-picker-item[data-value=sans-serif]::before {
            content: "sans-serif";
            font-family: "sans-serif" !important;
        }
    }
    .ql-editor {
        font-family: "SimSun" !important;
        .ql-font-SimSun {
            font-family: "SimSun" !important;
        }
        .ql-font-SimHei {
            font-family: "SimHei" !important;
        }
        .ql-font-Microsoft-YaHei {
            font-family: "Microsoft YaHei" !important;
        }
        .ql-font-KaiTi {
            font-family: "KaiTi" !important;
        }
        .ql-font-FangSong {
            font-family: "FangSong" !important;
        }
        .ql-font-Arial {
            font-family: "Arial" !important;
        }
        .ql-font-Times-New-Roman {
            font-family: "Times New Roman" !important;
        }
        .ql-font-sans-serif {
            font-family: "sans-serif" !important;
        }
    }
}

// 富文本编辑器-回显
/deep/ .rich_text_show_page {
    .ql-align-center {
        text-align: center;
    }
    .ql-align-right {
        text-align: right;
    }
    .ql-size-10px {
        font-size: 10px;
    }
    .ql-size-12px {
        font-size: 12px;
    }
    .ql-size-14px {
        font-size: 14px;
    }
    .ql-size-16px {
        font-size: 16px;
    }
    .ql-size-18px {
        font-size: 18px;
    }
    .ql-size-20px {
        font-size: 20px;
    }
    .ql-size-22px {
        font-size: 22px;
    }
    .ql-size-24px {
        font-size: 24px;
    }
    .ql-size-26px {
        font-size: 26px;
    }
    .ql-size-32px {
        font-size: 32px;
    }
    .ql-size-48px {
        font-size: 48px;
    }
    font-family: "SimSun" !important;
    .ql-font-SimSun {
        font-family: "SimSun" !important;
    }
    .ql-font-SimHei {
        font-family: "SimHei" !important;
    }
    .ql-font-Microsoft-YaHei {
        font-family: "Microsoft YaHei" !important;
    }
    .ql-font-KaiTi {
        font-family: "KaiTi" !important;
    }
    .ql-font-FangSong {
        font-family: "FangSong" !important;
    }
    .ql-font-Arial {
        font-family: "Arial" !important;
    }
    .ql-font-Times-New-Roman {
        font-family: "Times New Roman" !important;
    }
    .ql-font-sans-serif {
        font-family: "sans-serif" !important;
    }
}
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容