提交者
Gitee
!180 富文本编辑组件支持只读
Merge pull request !180 from JOSWAY/master
正在显示
1 个修改的文件
包含
200 行增加
和
195 行删除
| 1 | -<template> | ||
| 2 | - <div class="editor" ref="editor" :style="styles"></div> | ||
| 3 | -</template> | ||
| 4 | - | ||
| 5 | -<script> | ||
| 6 | -import Quill from "quill"; | ||
| 7 | -import "quill/dist/quill.core.css"; | ||
| 8 | -import "quill/dist/quill.snow.css"; | ||
| 9 | -import "quill/dist/quill.bubble.css"; | ||
| 10 | - | ||
| 11 | -export default { | ||
| 12 | - name: "Editor", | ||
| 13 | - props: { | ||
| 14 | - /* 编辑器的内容 */ | ||
| 15 | - value: { | ||
| 16 | - type: String, | ||
| 17 | - default: "", | ||
| 18 | - }, | ||
| 19 | - /* 高度 */ | ||
| 20 | - height: { | ||
| 21 | - type: Number, | ||
| 22 | - default: null, | ||
| 23 | - }, | ||
| 24 | - /* 最小高度 */ | ||
| 25 | - minHeight: { | ||
| 26 | - type: Number, | ||
| 27 | - default: null, | ||
| 28 | - }, | ||
| 29 | - }, | ||
| 30 | - data() { | ||
| 31 | - return { | ||
| 32 | - Quill: null, | ||
| 33 | - currentValue: "", | ||
| 34 | - options: { | ||
| 35 | - theme: "snow", | ||
| 36 | - bounds: document.body, | ||
| 37 | - debug: "warn", | ||
| 38 | - modules: { | ||
| 39 | - // 工具栏配置 | ||
| 40 | - toolbar: [ | ||
| 41 | - ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线 | ||
| 42 | - ["blockquote", "code-block"], // 引用 代码块 | ||
| 43 | - [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表 | ||
| 44 | - [{ indent: "-1" }, { indent: "+1" }], // 缩进 | ||
| 45 | - [{ size: ["small", false, "large", "huge"] }], // 字体大小 | ||
| 46 | - [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题 | ||
| 47 | - [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色 | ||
| 48 | - [{ align: [] }], // 对齐方式 | ||
| 49 | - ["clean"], // 清除文本格式 | ||
| 50 | - ["link", "image", "video"] // 链接、图片、视频 | ||
| 51 | - ], | ||
| 52 | - }, | ||
| 53 | - placeholder: "请输入内容", | ||
| 54 | - readOnly: false, | ||
| 55 | - }, | ||
| 56 | - }; | ||
| 57 | - }, | ||
| 58 | - computed: { | ||
| 59 | - styles() { | ||
| 60 | - let style = {}; | ||
| 61 | - if (this.minHeight) { | ||
| 62 | - style.minHeight = `${this.minHeight}px`; | ||
| 63 | - } | ||
| 64 | - if (this.height) { | ||
| 65 | - style.height = `${this.height}px`; | ||
| 66 | - } | ||
| 67 | - return style; | ||
| 68 | - }, | ||
| 69 | - }, | ||
| 70 | - watch: { | ||
| 71 | - value: { | ||
| 72 | - handler(val) { | ||
| 73 | - if (val !== this.currentValue) { | ||
| 74 | - this.currentValue = val === null ? "" : val; | ||
| 75 | - if (this.Quill) { | ||
| 76 | - this.Quill.pasteHTML(this.currentValue); | ||
| 77 | - } | ||
| 78 | - } | ||
| 79 | - }, | ||
| 80 | - immediate: true, | ||
| 81 | - }, | ||
| 82 | - }, | ||
| 83 | - mounted() { | ||
| 84 | - this.init(); | ||
| 85 | - }, | ||
| 86 | - beforeDestroy() { | ||
| 87 | - this.Quill = null; | ||
| 88 | - }, | ||
| 89 | - methods: { | ||
| 90 | - init() { | ||
| 91 | - const editor = this.$refs.editor; | ||
| 92 | - this.Quill = new Quill(editor, this.options); | ||
| 93 | - this.Quill.pasteHTML(this.currentValue); | ||
| 94 | - this.Quill.on("text-change", (delta, oldDelta, source) => { | ||
| 95 | - const html = this.$refs.editor.children[0].innerHTML; | ||
| 96 | - const text = this.Quill.getText(); | ||
| 97 | - const quill = this.Quill; | ||
| 98 | - this.currentValue = html; | ||
| 99 | - this.$emit("input", html); | ||
| 100 | - this.$emit("on-change", { html, text, quill }); | ||
| 101 | - }); | ||
| 102 | - this.Quill.on("text-change", (delta, oldDelta, source) => { | ||
| 103 | - this.$emit("on-text-change", delta, oldDelta, source); | ||
| 104 | - }); | ||
| 105 | - this.Quill.on("selection-change", (range, oldRange, source) => { | ||
| 106 | - this.$emit("on-selection-change", range, oldRange, source); | ||
| 107 | - }); | ||
| 108 | - this.Quill.on("editor-change", (eventName, ...args) => { | ||
| 109 | - this.$emit("on-editor-change", eventName, ...args); | ||
| 110 | - }); | ||
| 111 | - }, | ||
| 112 | - }, | ||
| 113 | -}; | ||
| 114 | -</script> | ||
| 115 | - | ||
| 116 | -<style> | ||
| 117 | -.editor, .ql-toolbar { | ||
| 118 | - white-space: pre-wrap!important; | ||
| 119 | - line-height: normal !important; | ||
| 120 | -} | ||
| 121 | -.quill-img { | ||
| 122 | - display: none; | ||
| 123 | -} | ||
| 124 | -.ql-snow .ql-tooltip[data-mode="link"]::before { | ||
| 125 | - content: "请输入链接地址:"; | ||
| 126 | -} | ||
| 127 | -.ql-snow .ql-tooltip.ql-editing a.ql-action::after { | ||
| 128 | - border-right: 0px; | ||
| 129 | - content: "保存"; | ||
| 130 | - padding-right: 0px; | ||
| 131 | -} | ||
| 132 | - | ||
| 133 | -.ql-snow .ql-tooltip[data-mode="video"]::before { | ||
| 134 | - content: "请输入视频地址:"; | ||
| 135 | -} | ||
| 136 | - | ||
| 137 | -.ql-snow .ql-picker.ql-size .ql-picker-label::before, | ||
| 138 | -.ql-snow .ql-picker.ql-size .ql-picker-item::before { | ||
| 139 | - content: "14px"; | ||
| 140 | -} | ||
| 141 | -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, | ||
| 142 | -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { | ||
| 143 | - content: "10px"; | ||
| 144 | -} | ||
| 145 | -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, | ||
| 146 | -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { | ||
| 147 | - content: "18px"; | ||
| 148 | -} | ||
| 149 | -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, | ||
| 150 | -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { | ||
| 151 | - content: "32px"; | ||
| 152 | -} | ||
| 153 | - | ||
| 154 | -.ql-snow .ql-picker.ql-header .ql-picker-label::before, | ||
| 155 | -.ql-snow .ql-picker.ql-header .ql-picker-item::before { | ||
| 156 | - content: "文本"; | ||
| 157 | -} | ||
| 158 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, | ||
| 159 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { | ||
| 160 | - content: "标题1"; | ||
| 161 | -} | ||
| 162 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, | ||
| 163 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { | ||
| 164 | - content: "标题2"; | ||
| 165 | -} | ||
| 166 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, | ||
| 167 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { | ||
| 168 | - content: "标题3"; | ||
| 169 | -} | ||
| 170 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, | ||
| 171 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { | ||
| 172 | - content: "标题4"; | ||
| 173 | -} | ||
| 174 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, | ||
| 175 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { | ||
| 176 | - content: "标题5"; | ||
| 177 | -} | ||
| 178 | -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, | ||
| 179 | -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { | ||
| 180 | - content: "标题6"; | ||
| 181 | -} | ||
| 182 | - | ||
| 183 | -.ql-snow .ql-picker.ql-font .ql-picker-label::before, | ||
| 184 | -.ql-snow .ql-picker.ql-font .ql-picker-item::before { | ||
| 185 | - content: "标准字体"; | ||
| 186 | -} | ||
| 187 | -.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, | ||
| 188 | -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { | ||
| 189 | - content: "衬线字体"; | ||
| 190 | -} | ||
| 191 | -.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, | ||
| 192 | -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { | ||
| 193 | - content: "等宽字体"; | ||
| 194 | -} | ||
| 195 | -</style> | ||
| 1 | +<template> | ||
| 2 | + <div class="editor" ref="editor" :style="styles"></div> | ||
| 3 | +</template> | ||
| 4 | + | ||
| 5 | +<script> | ||
| 6 | +import Quill from "quill"; | ||
| 7 | +import "quill/dist/quill.core.css"; | ||
| 8 | +import "quill/dist/quill.snow.css"; | ||
| 9 | +import "quill/dist/quill.bubble.css"; | ||
| 10 | + | ||
| 11 | +export default { | ||
| 12 | + name: "Editor", | ||
| 13 | + props: { | ||
| 14 | + /* 编辑器的内容 */ | ||
| 15 | + value: { | ||
| 16 | + type: String, | ||
| 17 | + default: "", | ||
| 18 | + }, | ||
| 19 | + /* 高度 */ | ||
| 20 | + height: { | ||
| 21 | + type: Number, | ||
| 22 | + default: null, | ||
| 23 | + }, | ||
| 24 | + /* 最小高度 */ | ||
| 25 | + minHeight: { | ||
| 26 | + type: Number, | ||
| 27 | + default: null, | ||
| 28 | + }, | ||
| 29 | + /* 只读 */ | ||
| 30 | + readOnly: { | ||
| 31 | + type: Boolean, | ||
| 32 | + default: false, | ||
| 33 | + } | ||
| 34 | + }, | ||
| 35 | + data() { | ||
| 36 | + return { | ||
| 37 | + Quill: null, | ||
| 38 | + currentValue: "", | ||
| 39 | + options: { | ||
| 40 | + theme: "snow", | ||
| 41 | + bounds: document.body, | ||
| 42 | + debug: "warn", | ||
| 43 | + modules: { | ||
| 44 | + // 工具栏配置 | ||
| 45 | + toolbar: [ | ||
| 46 | + ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线 | ||
| 47 | + ["blockquote", "code-block"], // 引用 代码块 | ||
| 48 | + [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表 | ||
| 49 | + [{ indent: "-1" }, { indent: "+1" }], // 缩进 | ||
| 50 | + [{ size: ["small", false, "large", "huge"] }], // 字体大小 | ||
| 51 | + [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题 | ||
| 52 | + [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色 | ||
| 53 | + [{ align: [] }], // 对齐方式 | ||
| 54 | + ["clean"], // 清除文本格式 | ||
| 55 | + ["link", "image", "video"] // 链接、图片、视频 | ||
| 56 | + ], | ||
| 57 | + }, | ||
| 58 | + placeholder: "请输入内容", | ||
| 59 | + readOnly: this.readOnly, | ||
| 60 | + }, | ||
| 61 | + }; | ||
| 62 | + }, | ||
| 63 | + computed: { | ||
| 64 | + styles() { | ||
| 65 | + let style = {}; | ||
| 66 | + if (this.minHeight) { | ||
| 67 | + style.minHeight = `${this.minHeight}px`; | ||
| 68 | + } | ||
| 69 | + if (this.height) { | ||
| 70 | + style.height = `${this.height}px`; | ||
| 71 | + } | ||
| 72 | + return style; | ||
| 73 | + }, | ||
| 74 | + }, | ||
| 75 | + watch: { | ||
| 76 | + value: { | ||
| 77 | + handler(val) { | ||
| 78 | + if (val !== this.currentValue) { | ||
| 79 | + this.currentValue = val === null ? "" : val; | ||
| 80 | + if (this.Quill) { | ||
| 81 | + this.Quill.pasteHTML(this.currentValue); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + }, | ||
| 85 | + immediate: true, | ||
| 86 | + }, | ||
| 87 | + }, | ||
| 88 | + mounted() { | ||
| 89 | + this.init(); | ||
| 90 | + }, | ||
| 91 | + beforeDestroy() { | ||
| 92 | + this.Quill = null; | ||
| 93 | + }, | ||
| 94 | + methods: { | ||
| 95 | + init() { | ||
| 96 | + const editor = this.$refs.editor; | ||
| 97 | + this.Quill = new Quill(editor, this.options); | ||
| 98 | + this.Quill.pasteHTML(this.currentValue); | ||
| 99 | + this.Quill.on("text-change", (delta, oldDelta, source) => { | ||
| 100 | + const html = this.$refs.editor.children[0].innerHTML; | ||
| 101 | + const text = this.Quill.getText(); | ||
| 102 | + const quill = this.Quill; | ||
| 103 | + this.currentValue = html; | ||
| 104 | + this.$emit("input", html); | ||
| 105 | + this.$emit("on-change", { html, text, quill }); | ||
| 106 | + }); | ||
| 107 | + this.Quill.on("text-change", (delta, oldDelta, source) => { | ||
| 108 | + this.$emit("on-text-change", delta, oldDelta, source); | ||
| 109 | + }); | ||
| 110 | + this.Quill.on("selection-change", (range, oldRange, source) => { | ||
| 111 | + this.$emit("on-selection-change", range, oldRange, source); | ||
| 112 | + }); | ||
| 113 | + this.Quill.on("editor-change", (eventName, ...args) => { | ||
| 114 | + this.$emit("on-editor-change", eventName, ...args); | ||
| 115 | + }); | ||
| 116 | + }, | ||
| 117 | + }, | ||
| 118 | +}; | ||
| 119 | +</script> | ||
| 120 | + | ||
| 121 | +<style> | ||
| 122 | +.editor, .ql-toolbar { | ||
| 123 | + white-space: pre-wrap!important; | ||
| 124 | + line-height: normal !important; | ||
| 125 | +} | ||
| 126 | +.quill-img { | ||
| 127 | + display: none; | ||
| 128 | +} | ||
| 129 | +.ql-snow .ql-tooltip[data-mode="link"]::before { | ||
| 130 | + content: "请输入链接地址:"; | ||
| 131 | +} | ||
| 132 | +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { | ||
| 133 | + border-right: 0px; | ||
| 134 | + content: "保存"; | ||
| 135 | + padding-right: 0px; | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +.ql-snow .ql-tooltip[data-mode="video"]::before { | ||
| 139 | + content: "请输入视频地址:"; | ||
| 140 | +} | ||
| 141 | + | ||
| 142 | +.ql-snow .ql-picker.ql-size .ql-picker-label::before, | ||
| 143 | +.ql-snow .ql-picker.ql-size .ql-picker-item::before { | ||
| 144 | + content: "14px"; | ||
| 145 | +} | ||
| 146 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, | ||
| 147 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { | ||
| 148 | + content: "10px"; | ||
| 149 | +} | ||
| 150 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, | ||
| 151 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { | ||
| 152 | + content: "18px"; | ||
| 153 | +} | ||
| 154 | +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, | ||
| 155 | +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { | ||
| 156 | + content: "32px"; | ||
| 157 | +} | ||
| 158 | + | ||
| 159 | +.ql-snow .ql-picker.ql-header .ql-picker-label::before, | ||
| 160 | +.ql-snow .ql-picker.ql-header .ql-picker-item::before { | ||
| 161 | + content: "文本"; | ||
| 162 | +} | ||
| 163 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, | ||
| 164 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { | ||
| 165 | + content: "标题1"; | ||
| 166 | +} | ||
| 167 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, | ||
| 168 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { | ||
| 169 | + content: "标题2"; | ||
| 170 | +} | ||
| 171 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, | ||
| 172 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { | ||
| 173 | + content: "标题3"; | ||
| 174 | +} | ||
| 175 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, | ||
| 176 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { | ||
| 177 | + content: "标题4"; | ||
| 178 | +} | ||
| 179 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, | ||
| 180 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { | ||
| 181 | + content: "标题5"; | ||
| 182 | +} | ||
| 183 | +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, | ||
| 184 | +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { | ||
| 185 | + content: "标题6"; | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +.ql-snow .ql-picker.ql-font .ql-picker-label::before, | ||
| 189 | +.ql-snow .ql-picker.ql-font .ql-picker-item::before { | ||
| 190 | + content: "标准字体"; | ||
| 191 | +} | ||
| 192 | +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, | ||
| 193 | +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { | ||
| 194 | + content: "衬线字体"; | ||
| 195 | +} | ||
| 196 | +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, | ||
| 197 | +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { | ||
| 198 | + content: "等宽字体"; | ||
| 199 | +} | ||
| 200 | +</style> |
-
请 注册 或 登录 后发表评论