前言
最近要做个移动端富文本,但是需求比较简单,只需要能够上传图片和实现文字位置自定义
找了蛮多文章都建议使用quill。既然大伙儿都推荐它,想必它是有过人之处的。话不多说,开始代码。
先看下移动端效果图
参考链接
代码
- ImgText.vue
<template>
<div class="example">
<quill-editor
class="editor"
ref="myTextEditor"
:value="content"
:options="editorOption"
@change="onEditorChange"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@ready="onEditorReady($event)"
/>
</div>
</template>
<script>
import dedent from 'dedent' // 能保持字符串的换行位置
import debounce from 'lodash/debounce' // 防抖
import { quillEditor } from 'vue-quill-editor'
// import theme style
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
export default {
name: 'quill-example-snow',
components: {
quillEditor
},
data() {
return {
editorOption: {
modules: {
// 可以自定义配置,toolbar内的每个二级数组为一个小组模块
// 根据需求可以删除不需要的配置
toolbar: [
['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] }],
[{ 'font': [] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'align': [] }],
['clean'],
['link', 'image', 'video']
]
}
},
content: dedent`<p style="text-align: right">首次要展示的内容</p>`,
}
},
methods: {
onEditorChange: debounce(function(value) {
this.content = value.html
}, 466),
onEditorBlur(editor) {
console.log('editor blur!', editor)
},
onEditorFocus(editor) {
console.log('editor focus!', editor)
},
onEditorReady(editor) {
console.log('editor ready!', editor)
}
},
computed: {
editor() {
return this.$refs.myTextEditor.quill
}
},
mounted() {
console.log('this is Quill instance:', this.editor)
}
}
</script>
<style lang="scss" scoped>
.example {
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
.editor {
height: 80%;
overflow: hidden;
}
}
</style>
- 根据需求删减toolbar
// 上传图片要改写成自定义上传到阿里云,默认图片是按照base64的路径
import handlers from "./handlers.js";
data() {
return {
editorOption: {
theme: "snow", // 提供了2种主题:snow和bubble,bubble没有工具栏
placeholder: "请输入图文详情",
modules: {
toolbar: {
container: [["image"], [{ align: [] }]], // 工具栏选项
handlers: handlers // 事件重写
}
}
}
};
}
- 自定义配置图片上传handlers.js
import uploadImg from "@/request/upload";
// uploadImg,这里是自己封装的图片上传到阿里云,导出的一个方法。
// 思路是:返回一个Promise,把上传到阿里云成功的图片结果resolve出来。
const uploadConfig = {
name: "img", // 必填参数 文件的参数名
accept: "image/png, image/gif, image/jpeg" // 可选 可上传的图片格式
};
const handlers = {
image: function() {
let self = this;
let fileInput = this.container.querySelector("input.ql-image[type=file]");
if (fileInput === null) {
fileInput = document.createElement("input");
fileInput.setAttribute("type", "file");
// 设置图片参数名
if (uploadConfig.name) {
fileInput.setAttribute("name", uploadConfig.name);
}
// 可设置上传图片的格式
fileInput.setAttribute("accept", uploadConfig.accept);
fileInput.classList.add("ql-image");
// 监听选择文件
fileInput.addEventListener("change", function(e) {
// uploadImg是封装好的上传图片方法
uploadImg(e.target.files[0]).then(res => {
if (res.code === "000000") {
// 后端返回的图片路径
let url = res.data[0];
// 获取当前图片的index。
// 【详见文档】(https://quilljs.com/docs/api/#getselection)
let length = self.quill.getSelection(true).index;
// 图片上传成功后,img的src需要在这里添加
self.quill.insertEmbed(length, "image", url);
self.quill.setSelection(length + 1);
}
fileInput.value = "";
});
});
this.container.appendChild(fileInput);
}
fileInput.click();
}
};
export default handlers;
- 类名替换为样式
- align为什么要处理成style呢?
- 因为默认返回的是
<p class="ql-align-right">测试内容</p>
这类,但是配置之后要使用,这种类名存储到服务器,那么使用的地方也必须引入quill的核心样式。对c端来说增加了不必要的依赖。如果能改成<p style="text-align: right">测试内容</p>
就完美啦。
methods: {
onEditorChange: debounce(function(value) {
this.content = value.html;
this.onEditorBlur();
}, 466),
onEditorBlur() {
// 调试发现每次使用水平对齐,都会生成类名:ql-align-xx,这么有规律,直接用正则替换。
const myreg = /class="ql-align-(?=justify|center|right)/g;
let newStr = this.content.replace(myreg, 'style="text-align: ');
// newStr就是需求的结果啦
console.log(newStr)
}
}