quill-editor是一款非常强大的富文本组件,在最近的项目里也是使用到了,附上:插件源码
使用也是非常简单:
一.下载Vue-Quill-Editor
npm install vue-quill-editor --save
二.在vue里的组件中使用
<template>
<div class="edit_container">
<quill-editor
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
@change="onEditorChange($event)">
</quill-editor>
</div>
</template>
<script>
import { quillEditor } from "vue-quill-editor"; //调用编辑器
export default {
components: {
quillEditor
},
data() {
return {
content: `<p></p><p><br></p><ol><li><strong><em>Or drag/paste an image here.</em></strong></li><li><strong><em>rerew</em></strong></li><li><strong><em>rtrete</em></strong></li><li><strong><em>tytrytr</em></strong></li><li><strong><em>uytu</em></strong></li></ol>`,
editorOption: {}
}
},
methods: {
onEditorReady(editor) {} // 准备编辑器,
onEditorBlur(){}, // 失去焦点事件
onEditorFocus(){}, // 获得焦点事件
onEditorChange(){}, // 内容改变事件
},
computed: {
editor() {
return this.$refs.myQuillEditor.quill;
},
}
}
</script>
<style lang="scss">
.edit_container {
width: 800px;
}
//输入框
.ql-container {
height: 400px;
}
</style>
三.获取富文本里的内容
我们发现富文本里数据是双向数据绑定到content这个变量上面的,那我们可以在methods里面写一个方法,在页面上添加一个按钮,当点击按钮时我们输出内容
//html
<button @click="getQuillEditorContent">点击输出内容</button>
//methods里面的方法
getQuillEditorContent() {
console.log(this.content) //输出的是一段html
// console.log(this.$refs.myQuillEditor.quill.getText())
// console.log(this.$refs.myQuillEditor) //获取到富文本对象
//这里一定要注意写法,这里获取的是一个Delta对象
console.log(this.$refs.myQuillEditor.quill.getContents())
// console.log(this.$refs.myQuillEditor.quill.getText())
// console.log(this.$refs.myQuillEditor.quill.root.innerHTML)
}
一定要注意第二个console.log里面的写法:
1.this.$refs.myQuillEditor是获取到富文本对象 console.log(this.$refs.myQuillEditor)
2.一定要点quill否则拿不到quill的api(各种方法)
由此可见,获取富文本内容的三种方式:
- content双向数据绑定的方式
- getContents() —— 返回的是Delta对象,一种JSON数组
- getText() —— 返回文本域里对应字符串
四 展示富文本数据
我们获取到的富文本是一段纯标签的数据,里面没有带上行内样式,为了原样展示出富文本的数据,专门写了一个展示的组件
//展示子组件
<template>
<div>
<div style='height:500px;width:700px;'>
<div class='quill-editor'>
<div class="ql-container">
<!-- 利用v-html标签做到原样展示 -->
<div class='ql-editor' v-html="quillHtml">
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
export default {
name: "quillShow",
data(){
return {
quillHtml: ""
}
},
created(){
//这里的created钩子只会执行一次,所以做不到传递异步数据的效果
// this.quillHtml = this.quillHtmlStr
console.log(this.quillHtml,this.quillHtmlStr)
},
watch: {
//利用watch来实现传递异步数据
"quillHtmlStr": function(newVal,oldVal){
this.quillHtml = newVal
}
},
props: {
quillHtmlStr: {
type: String
}
}
}
</script>
在需要展示的父组件里引入这个组件并传值就可以了
//使用
<quill-show :quillHtmlStr.sync="quillHtmlStr"></quill-show>
//然后在方法里调用就可以了
getQuillEditorContent() {
// console.log(this.content)
// console.log(this.$refs.myQuillEditor)
// console.log(this.$refs.myQuillEditor.quill.getContents())
// console.log(this.$refs.myQuillEditor.quill.getText())
// console.log(this.$refs.myQuillEditor.quill.root.innerHTML)
this.quillHtmlStr = this.content
},
五.自定义一个图标
自定义一个图标的方式有两种方式:官方文档
1.利用options来配置:
//这里是全部的图标,你想要选择什么就留下什么就可以了
var toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['clean'] // remove formatting button
];
具体含义:
背景颜色 - background
加粗- bold
颜色 - color
字体 - font
内联代码 - code
斜体 - italic
链接 - link
大小 - size
删除线 - strike
上标/下标 - script
下划线 - underline
引用- blockquote
标题 - header
缩进 - indent
列表 - list
文本对齐 - align
文本方向 - direction
代码块 - code-block
公式 - formula
图片 - image
视频 - video
清除字体样式- clean
现在我们在vue的组件里配置:
//这里配置的是部分图标
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
['clean'] // remove formatting button
];
export default {
components: {
quillEditor
},
data() {
return {
content: ``,
editorOption: {
modules:{
toolbar: toolbarOptions
}
}
}
},
}
配置出来的效果:
2.利用solt的形式
solt形式就是利用button来实现和这个效果
3.增加一个图标
3.1 新建一个quill-config.js
在这个js里面重写配置一个操作按钮的数组,其中的[‘sourceEditor’]就是新的操作按钮的名字,而handlers 就是点击这个按钮应该做的事情,initButton是初始化这个按钮的样式函数,必须在mounted钩子去初始化这个按钮.
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
['clean'] // remove formatting button
['sourceEditor'] //新添加的工具
];
//重写事件方法
const handlers = {
shadeBox:null,
sourceEditor: function(){ //添加工具方法
alert('我新添加的工具方法');
}
};
//默认导出一个对象
export default {
placeholder: '',
theme: 'snow', // 主题
modules: {
toolbar: {
container: toolOptions, // 工具栏选项
handlers: handlers // 事件重写
}
},
initButton:function(){ //在使用的页面中初始化按钮样式
const sourceEditorButton = document.querySelector('.ql-sourceEditor');
sourceEditorButton.style.cssText = "width:80px; border:1px solid #ccc; border-radius:5px;";
sourceEditorButton.innerText="源码编辑";
}
}
3.2 在页面上使用
在页面上使用的时候,注意的是要在mounted钩子里面初始化这个按钮,不然页面上的按钮将没有样式.
<template>
<quill-editor ref="myTextEditor"
v-model="content" :options="quillOption">
</quill-editor>
</template>
<script>
import { quillEditor } from 'vue-quill-editor'
import quillConfig from './quill-config.js'
export default {
components: {
quillEditor
},
mounted(){
//在mounted钩子里面初始化富文本的样式
quillConfig.initButton();
},
data() {
return {
content: '',
quillOption: quillConfig,
}
}
}
</script>
五 上传图片到服务器
这里的方法最主要是借鉴了quill-editor-vue组件在github里issue的实现方法,地址
<template>
<div>
<!-- 图片上传组件辅助-->
<el-upload
class="avatar-uploader"
:action="serverUrl"
name="img"
:headers="header"
:show-file-list="false"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload">
</el-upload>
<!--富文本编辑器组件-->
<el-row v-loading="uillUpdateImg">
<quill-editor
v-model="detailContent"
ref="myQuillEditor"
:options="editorOption"
@change="onEditorChange($event)"
@ready="onEditorReady($event)"
>
</quill-editor>
</el-row>
</div>
</template>
<script>
export default {
// 工具栏配置
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['link', 'image', 'video'],
['clean'] // remove formatting button
]
data() {
return {
serverUrl: '', // 这里写你要上传的图片服务器地址
header: {token: sessionStorage.token}, // 有的图片服务器要求请求头需要有token之类的参数,写在这里
detailContent: '', // 富文本内容
editorOption: {
placeholder: '',
theme: 'snow', // or 'bubble'
modules: {
toolbar: {
container: toolbarOptions, // 工具栏
handlers: {
'image': function (value) {
if (value) {
document.querySelector('#quill-upload input').click()
} else {
this.quill.format('image', false);
}
}
}
}
}
}
}
},
methods: {
// 富文本图片上传前
beforeUpload() {
// 显示loading动画
this.quillUpdateImg = true
},
uploadSuccess(res, file) {
// res为图片服务器返回的数据
// 获取富文本组件实例
let quill = this.$refs.myQuillEditor.quill
// 如果上传成功
if (res.code === '200' && res.info !== null) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.info为服务器返回的图片地址
quill.insertEmbed(length, 'image', res.info)
// 调整光标到最后
quill.setSelection(length + 1)
} else {
this.$message.error('图片插入失败')
}
// loading动画消失
this.quillUpdateImg = false
},
// 富文本图片上传失败
uploadError() {
// loading动画消失
this.quillUpdateImg = false
this.$message.error('图片插入失败')
}
}
}
</script>
上面的代码是与element-ui结合实现的,其实与可以自己实现一个图片上传框,比如:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box {
width: 500px;
height: 550px;
margin: 150px auto;
}
input {
height: 20px;
margin-bottom: 10px;
border: 1px solid #000;
}
.imgShow {
width: 500px;
height: 400px;
border: 5px solid #000;
}
</style>
</head>
<body>
<div class="box">
<!-- 利用label标签可以美化上传按钮 -->
<label for="fileBtn" class="uploadFile">上传文件</label>
<input type="file" id="fileBtn" style="display: none">
<div class="imgShow"></div>
<img src="" alt="">
</div>
</body>
</html>
<script>
document.getElementById('fileBtn').onchange = function(){
//获取到文件
console.log(this.files[0]);
// console.dir(this);
//限制上传的代码格式与大小
var fileSize = this.files[0].size
var size = fileSize / 1024
if(size>2000){
alert("附件不能大于2M");
return
}
//限制上传的文件格式
var name = this.files[0].name;
var fileName = name.substring(name.lastIndexOf(".")+1).toLowerCase();
if( fileName !="jpg"
&& fileName !="jpeg"
&& fileName !="pdf"
&& fileName !="png"
&& fileName !="dwg"
&& fileName !="gif" ){
alert("请选择图片格式文件上传(jpg,png,gif,dwg,pdf,gif等)!");
this.files[0].name = "";
return
}
// 将文件生成一个url路径字符串
var url = URL.createObjectURL(this.files[0]);
// 将图片展示在div的盒子里面
document.querySelector('.imgShow').style.background = "url("+ url + ") no-repeat center/cover";
//也可以将图片显示在img单标签里面
document.querySelector('img').src = url;
}
</script>