赞
踩
1. 需要安装的插件
npm install quill vue-quill-editor quill-image-drop-module quill-image-resize-module -s
实现的源码在下面,可直接封装成组件使用
- <template>
- <div class="ql-container">
- <quill-editor
- v-model="content"
- ref="myquillEditor"
- :options="editorOption"
- ></quill-editor>
- <input
- id="uploadImg"
- type="file"
- style="display:none"
- accept="image/png, image/jpeg, image/gif"
- @change="uploadImage"
- />
- <input
- id="uploadVideo"
- type="file"
- style="display:none"
- accept="video/*"
- @change="uploadVideo"
- />
- </div>
- </template>
- <script>
- import "quill/dist/quill.core.css";
- import "quill/dist/quill.snow.css";
- import "quill/dist/quill.bubble.css";
- import Vue from "vue";
- import * as quill from "quill"; //引入编辑器
- import VueQuillEditor from "vue-quill-editor";
- import { ImageDrop } from "quill-image-drop-module";
- import ImageResize from "quill-image-resize-module";
-
- Vue.use(VueQuillEditor /* { default global options } */);
-
- quill.register("modules/imageDrop", ImageDrop);
- quill.register("modules/imageResize", ImageResize);
-
- const BlockEmbed = quill.import("blots/block/embed");
- // 处理视频显示,video兼容小程序中显示
- class VideoBlot extends BlockEmbed {
- static create(value) {
- let node = super.create();
- node.setAttribute("src", value.url);
- node.setAttribute("controls", value.controls);
- node.setAttribute("width", value.width);
- node.setAttribute("height", value.height);
- node.setAttribute("webkit-playsinline", true);
- node.setAttribute("playsinline", true);
- node.setAttribute("x5-playsinline", true);
- return node;
- }
-
- static value(node) {
- return {
- url: node.getAttribute("src"),
- controls: node.getAttribute("controls"),
- width: node.getAttribute("width"),
- height: node.getAttribute("height")
- };
- }
- }
- VideoBlot.blotName = "simpleVideo";
- VideoBlot.tagName = "video";
- quill.register(VideoBlot);
-
- //quill编辑器的字体
- let fonts = [
- "SimSun",
- "SimHei",
- "Microsoft-YaHei",
- "KaiTi",
- "FangSong",
- "Arial",
- "sans-serif"
- ];
-
- let Font = quill.import("formats/font");
- Font.whitelist = fonts; //将字体加入到白名单
- quill.register(Font, true);
- // let fontSizeStyle = quill.import('attributors/style/size');
- // fontSizeStyle.whitelist = ['10px', '12px', '14px', '16px', '20px', '24px', '36px', false];
-
- //处理文本对齐
- let Align = quill.import("attributors/style/align");
- let aligns = [false, "right", "center", "justify"];
- Align.whitelist = aligns;
- quill.register(Align, true);
-
- export default {
- data() {
- return {
- content: "",
- editorOption: {
- modules: {
- toolbar: [
- ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
- // [{ font: [] }], // 字体种类
- [{ font: fonts }],
- [{ align: aligns }], // 对齐方式
- [{ size: ["small", false, "large", "huge"] }], // 字体大小
- // [{ 'size': fontSizeStyle.whitelist }],
- [{ header: 1 }, { header: 2 }], // 1、2 级标题
- [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
- ["blockquote", "code-block"], // 引用 代码块
- // [{ script: "sub" }, { script: "super" }], // 上标/下标
- // [{ indent: "-1" }, { indent: "+1" }], // 缩进
- // [{'direction': 'rtl'}], // 文本方向
- // [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
- [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
- // ["clean"], // 清除文本格式
- ["image", "video"]
- // ["link", "image", "video"] // 链接、图片、视频
- ],
-
- //实现拖拽,缩放的重要代码片段
- history: {
- delay: 1000,
- maxStack: 50,
- userOnly: false
- },
- imageDrop: true,
- imageResize: {
- displayStyles: {
- backgroundColor: "black",
- border: "none",
- color: "white"
- },
- modules: ["Resize", "DisplaySize", "Toolbar"]
- }
- },
- placeholder: "请填写..."
- }
- };
- },
- props: ["editorContent", "status"],
- mounted() {
- this.$refs.myquillEditor.quill.enable(this.status);
- this.$refs.myquillEditor.quill
- .getModule("toolbar")
- .addHandler("image", this.uploadImageHandler);
-
- this.$refs.myquillEditor.quill
- .getModule("toolbar")
- .addHandler("video", this.uploadVideoHandler);
- },
- methods: {
- uploadImageHandler() {
- const input = document.querySelector("#uploadImg");
- input.value = "";
- input.click();
- },
- uploadImage(event) {
- const form = new FormData();
- form.append("data", event.target.files[0]);
- this.$api.upload.uploadImg(form).then(res => {
- const addImageRange = this.$refs.myquillEditor.quill.getSelection();
- const newRange =
- 0 + (addImageRange !== null ? addImageRange.index : 0);
- this.$refs.myquillEditor.quill.insertEmbed(
- newRange,
- "image",
- res.data.data
- );
- this.$refs.myquillEditor.quill.setSelection(1 + newRange);
- });
- },
- uploadVideoHandler() {
- const input = document.querySelector("#uploadVideo");
- input.value = "";
- input.click();
- },
- uploadVideo(event) {
- const form = new FormData();
- form.append("data", event.target.files[0]);
- this.$api.upload.uploadVideo(form).then(res => {
- const addImageRange = this.$refs.myquillEditor.quill.getSelection();
- const newRange =
- 0 + (addImageRange !== null ? addImageRange.index : 0);
- this.$refs.myquillEditor.quill.insertEmbed(
- newRange,
- "simpleVideo",
- {
- url: res.data.data,
- controls: "controls",
- width: "100%",
- height: "100%"
- }
- );
- this.$refs.myquillEditor.quill.setSelection(1 + newRange);
- });
- }
- },
- watch: {
- editorContent: {
- handler: function(o, n) {
- this.content = this.editorContent;
- },
- immediate: true
- },
- // 控制编辑是否可输入
- status() {
- this.$refs.myquillEditor.quill.enable(this.status);
- }
- }
- };
- </script>
- <style lang="less" scoped>
- /deep/.ql-container {
- min-height: 200px;
- font-size: 13px;
- }
- /deep/.ql-toolbar.ql-snow .ql-picker-label {
- display: flex;
- }
- /deep/.ql-snow .ql-picker.ql-align {
- width: 80px;
- svg {
- padding: 0 5px;
- width: 28px;
- height: 18px;
- }
- }
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {
- content: "宋体";
- font-family: "SimSun";
- }
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {
- content: "黑体";
- font-family: "SimHei";
- }
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-label[data-value="Microsoft-YaHei"]::before,
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-item[data-value="Microsoft-YaHei"]::before {
- content: "微软雅黑";
- font-family: "Microsoft YaHei";
- }
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {
- content: "楷体";
- font-family: "KaiTi";
- }
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-label[data-value="FangSong"]::before,
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-item[data-value="FangSong"]::before {
- content: "仿宋";
- font-family: "FangSong";
- }
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
- /deep/.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
- content: "Arial";
- font-family: "Arial";
- }
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-label[data-value="Times-New-Roman"]::before,
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-item[data-value="Times-New-Roman"]::before {
- content: "Times New Roman";
- font-family: "Times New Roman";
- }
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-label[data-value="sans-serif"]::before,
- /deep/.ql-snow
- .ql-picker.ql-font
- .ql-picker-item[data-value="sans-serif"]::before {
- content: "sans-serif";
- font-family: "sans-serif";
- }
-
- /deep/.ql-font-SimSun {
- font-family: "SimSun";
- }
- /deep/.ql-font-SimHei {
- font-family: "SimHei";
- }
- /deep/.ql-font-Microsoft-YaHei {
- font-family: "Microsoft YaHei";
- }
- /deep/.ql-font-KaiTi {
- font-family: "KaiTi";
- }
- /deep/.ql-font-FangSong {
- font-family: "FangSong";
- }
- /deep/.ql-font-Arial {
- font-family: "Arial";
- }
- /deep/.ql-font-Times-New-Roman {
- font-family: "Times New Roman";
- }
- /deep/.ql-font-sans-serif {
- font-family: "sans-serif";
- }
-
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-label::before,
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-item::before {
- content: "14px";
- }
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
- content: "10px";
- }
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
- content: "18px";
- }
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
- /deep/.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
- content: "32px";
- }
-
- /deep/.ql-snow .ql-picker.ql-align .ql-picker-label::before,
- /deep/.ql-snow .ql-picker.ql-align .ql-picker-item::before {
- content: "left";
- text-align: left;
- }
-
- /deep/.ql-snow
- .ql-picker.ql-align
- .ql-picker-label[data-value="center"]::before,
- /deep/.ql-snow
- .ql-picker.ql-align
- .ql-picker-item[data-value="center"]::before {
- content: "center";
- text-align: center;
- }
-
- /deep/.ql-snow .ql-picker.ql-align .ql-picker-label[data-value="right"]::before,
- /deep/.ql-snow .ql-picker.ql-align .ql-picker-item[data-value="right"]::before {
- content: "right";
- text-align: right;
- }
-
- /deep/.ql-snow
- .ql-picker.ql-align
- .ql-picker-label[data-value="justify"]::before,
- /deep/.ql-snow
- .ql-picker.ql-align
- .ql-picker-item[data-value="justify"]::before {
- content: "justify";
- text-align: justify;
- }
- </style>
此段代码可直接封装成组件
父组件引用富文本组件参考代码:
<editor ref="myEditor" :editorContent="editorContent" :status="editorStatus"></editor>
父组件中获取富文本的值 参考代码: this.editorContent = this.$refs.myEditor.content;
备注: 代码中监听status 是用来控制编辑器是否可读, 监听editorContent 是用来回显文本内容
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。