富文本编辑器:ckeditor(使用官网下载包)
之前,直接使用的ckeditor-vue实现的富文本编辑器,问题主要是使用add-ons里面的plugin比较麻烦,需要自己包装,然后如果想要更改固有的plugin,比如table、tableselection比较麻烦。于是,为了更方便使用修改plugin,我们采用了第二中方式,从官网下载解压package,直接放到项目里面。下载官网地址:https://ckeditor.com/ckeditor
之前,直接使用的ckeditor-vue实现的富文本编辑器,问题主要是使用add-ons里面的plugin比较麻烦,需要自己包装,然后如果想要更改固有的plugin,比如table、tableselection比较麻烦。
于是,为了更方便使用修改plugin,我们采用了第二中方式,从官网下载解压package,直接放到项目里面。
下载
官网地址:https://ckeditor.com/ckeditor-4/download/
可以根据需要直接选择前三个下载,也可以定制自定义的,如果你想要使用额外的add-ons里面的plugin、或者想要未优化的源码方便修改的话,建议使用ONline Builder自定义下载包。而且,自定义的构建器还可以选择语言、皮肤什么的。
最后,同意协议,可以选择优化后的或者源码(如果你想要修改ckeditor的源码的话,选择源码,否则,选择optimized比较快),download即可。
使用
将下载包解压,放到vue的项目下的public目录下(该目录下的文件不打包,直接复制到结果里面),项目目录样式如下:
然后,在index.html文件里面引入ckeditor.js文件
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<script src="<%= BASE_URL %>ckeditor/ckeditor.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
创建CkEditor.vue文件,然后在App.vue里面引用即可使用。
<template>
<div>
<textarea :id='id'></textarea>
</div>
</template>
<script>
import MyDialog from './MyDialog'
export default {
name: 'CkEditor',
mounted: function () {
const self = this
let CKEDITOR = window.CKEDITOR
console.log(CKEDITOR)
// 渲染编辑器
let ckeditor = window.CKEDITOR.replace(self.id, {
height: 500,
language: 'en',
allowedContent: true,
pasteFilter: null,
toolbar: [
{
name: 'code',
items: ['Source']
},
{
name: 'basicstyles',
items: ['Styles', '-', 'Bold', 'Italic', 'Strike', 'Underline', 'TextColor', 'BGColor', 'Font', 'FontSize']
},
{
name: 'styles',
items: ['RemoveFormat']
},
{
name: 'insert',
items: ['Table', 'SpecialChar', 'HorizontalRule']
},
'/',
{
name: 'paragraph',
items: ['Format', 'NumberedList', 'BulletedList', '-', 'Indent', 'Outdent', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'lineheight']
},
{
name: 'links',
items: ['Link', 'Unlink', '-', 'Subscribe', 'Unsubscribe', 'HtmlTemplate']
},
{
name: 'document',
items: ['Undo', 'Redo']
}
]
})
//处理图片copy、paste
ckeditor.on('paste', async evt => {
if (evt.data.dataTransfer.getFilesCount() > 0) {
evt.data.dataValue = ''
if (evt.data.dataTransfer.getFilesCount()) {
let file = evt.data.dataTransfer.getFile(0)
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
self.ckeditor.insertHtml(`<img src="${reader.result}"/>`)
};
reader.onerror = error => {
console.error(error)
}
}
}
})
//处理tab
ckeditor.on('key', function (event) {
let keycode = event.data.keyCode
if (keycode === 9) {
event.cancel()
ckeditor.execCommand('indent')
}
})
ckeditor.on('instanceReady', () => {
self.ckeditor = ckeditor
console.log(ckeditor)
})
// 监听内容变更事件
ckeditor.on('change', function () {
self.$emit('contentChanged', self.ckeditor.getData())
})
},
data: function () {
return {
id: parseInt(Math.random() * 10000).toString(),
textarea: '',
ckeditor: null
}
},
methods: {
insertDiv (data) {
this.ckeditor.insertHtml(data)
}
}
}
</script>
<style scoped>
</style>
注意上面的配置文件里面的height、allowedContent、toolbar都可以不配置,这里是为了获得自己想要的效果,自定义的配置。
自定义插件
下面,我们要定义一个插件mydialog,具体步骤如下。
首先,在public/ckeditor/plugins下面添加文件夹mydialog,该文件夹里面包含icons目录和plugin.js文件,如图所示:
icons里面是图标mydialog.png,plugin.js是插件定义,代码如下:
CKEDITOR.plugins.add('mydialog', {
icons: 'mydialog',
init: function (editor) {
editor.addCommand('mydialog', {
exec: function (editor) {
editor.dialog.show()
}
})
editor.ui.addButton('MyDialog', {
label: 'Open My Dialog',
command: 'mydialog'
})
}
})
其中,icons是图标,名字和icons下面的图片一致,然后,定义一个button和一个点击button时候执行的命令即可。
插件定义好了,那么要怎么使用它呢?
我们修改CkEditor.vue文件,使自定义插件生效:
<template>
<div>
<textarea :id='id'></textarea>
<my-dialog ref="dialog" @content-changed="insertDiv"></my-dialog>
</div>
</template>
<script>
import MyDialog from './MyDialog'
export default {
name: 'CkEditor',
mounted: function () {
const self = this
let CKEDITOR = window.CKEDITOR
console.log(CKEDITOR)
// 渲染编辑器
let ckeditor = window.CKEDITOR.replace(self.id, {
height: 500,
language: 'en',
//自定义插件(位于public下的ckeditor/plugins/mydialog)
extraPlugins: 'mydialog',
removePlugins: 'resize',
allowedContent: true,
pasteFilter: null,
toolbar: [
{
name: 'code',
items: ['Source']
},
{
name: 'basicstyles',
items: ['Styles', '-', 'Bold', 'Italic', 'Strike', 'Underline', 'TextColor', 'BGColor', 'Font', 'FontSize']
},
{
name: 'styles',
items: ['RemoveFormat']
},
{
name: 'insert',
items: ['MyDialog', 'Table', 'SpecialChar', 'HorizontalRule']
},
'/',
{
name: 'paragraph',
items: ['Format', 'NumberedList', 'BulletedList', '-', 'Indent', 'Outdent', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight']
},
{
name: 'links',
items: ['Link', 'Unlink', '-', 'Subscribe', 'Unsubscribe', 'HtmlTemplate']
},
{
name: 'document',
items: ['Undo', 'Redo']
}
]
})
ckeditor.on('paste', async evt => {
if (evt.data.dataTransfer.getFilesCount() > 0) {
evt.data.dataValue = ''
if (evt.data.dataTransfer.getFilesCount()) {
let file = evt.data.dataTransfer.getFile(0)
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
self.ckeditor.insertHtml(`<img src="${reader.result}"/>`)
};
reader.onerror = error => {
console.error(error)
}
}
}
})
ckeditor.on('key', function (event) {
let keycode = event.data.keyCode
if (keycode === 9) {
event.cancel()
ckeditor.execCommand('indent')
}
})
ckeditor.on('instanceReady', () => {
self.ckeditor = ckeditor
ckeditor.dialog = self.$refs.dialog
console.log(ckeditor)
})
// 监听内容变更事件
ckeditor.on('change', function () {
self.$emit('contentChanged', self.ckeditor.getData())
})
},
data: function () {
return {
id: parseInt(Math.random() * 10000).toString(),
textarea: '',
ckeditor: null
}
},
methods: {
insertDiv (data) {
this.ckeditor.insertHtml(data)
}
},
components: {
MyDialog
}
}
</script>
<style scoped>
</style>
主要修改内容:
- 配置文件里面加
extraPlugins: 'mydialog',
,引入插件; - import插件界面文件MyDialog,把dialog界面引入;
- toolbar配置里面加入
'MyDialog'
按钮 - instanceReady里面加入
ckeditor.dialog = self.$refs.dialog
,把界面对象赋值给editor - 添加
<my-dialog ref="dialog" @content-changed="insertDiv"></my-dialog>
dialog界面 - 添加insertDiv方法(插入div)
MyDialog文件内容如下:
<template>
<el-dialog title="Insert A Div" :visible.sync="showDialog" width="50%">
<el-form label-width="120px" label-position="left">
<el-form-item label="color:" >
<el-color-picker v-model="color"></el-color-picker>
</el-form-item>
<el-form-item label="background:">
<el-color-picker v-model="background"></el-color-picker>
</el-form-item>
<el-form-item label="border">
<el-input v-model="border" style="width: 300px"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="showDialog = false">Cancel</el-button>
<el-button type="primary" @click="save">OK</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'MyDialog',
data () {
return {
showDialog: false,
color: '#000',
background: '#fff',
border: '1px solid #ccc'
}
},
methods: {
show () {
this.showDialog = true
},
save () {
let div = `<div style="color: ${this.color}; background: ${this.background}; border: ${this.border}; padding:5px 10px;"> </div>`
this.$emit('content-changed', div)
this.showDialog = false
}
}
}
</script>
<style scoped>
</style>
最后的实现效果:
点击自定义button,弹出如下对话框,点击ok,插入div。
插入的div如下所示:
这里我们的自定义插件的界面使用的是自己的界面,ckeditor提供了自己的dialog,如果要使用ckeditor的dialog,就不需要定义MyDialog文件了,可以直接在plugin.js里面定义界面,具体怎么做可以去官网查。
代码仓库:
https://github.com/gaograce/ckeditor-vue-example2.git
更多推荐
所有评论(0)