![b805ba6700b3e75d7e13407724d81428.png](https://i-blog.csdnimg.cn/blog_migrate/608e83cb2d0116899abff7cf55e480b2.jpeg)
最近,自己想用vue 做一个商品详情编辑器, 选择技术方案如下:
百度编辑器ueditor.baidu.com样式与UI不符合 并且还要后端配合 加载速度比较慢
CKEditor | Smart WYSIWYG HTML editor | Collaborative rich text editorckeditor.com![d3db3c6075b93396ecdf6127c3394f16.png](https://i-blog.csdnimg.cn/blog_migrate/e6218c64cf78e348b5fb9152f23c0c7c.jpeg)
文档全英文 (CKEditor4的文档比CKEditor5的文档全面一点) 看了半天也没搞清楚怎么扩展
wangeditorwww.wangeditor.com加载速度快,文档全中文,但是功能不够全面
Quill - Your powerful rich text editorquilljs.com![43e2fb6503d5e0b5d51c7795e59019a7.png](https://i-blog.csdnimg.cn/blog_migrate/ab7ce8def4a9c770d39ff681a1a3b298.png)
全英文文档 稍微体验了一下 无法评价
The Most Advanced WYSIWYG HTML Editorwww.tinymce.com![2048ef5079a707d6744621d6b85de4ba.png](https://i-blog.csdnimg.cn/blog_migrate/01380334a88939647e8b38cf1ca5a34a.png)
这个就是我最终选中的编辑器,在此 记录下开发流程
1.引入到vue项目中
npm install @tinymce/tinymce-vue --save
2.文本编辑器本地化 (官网上面的例子都是通过 api-key 的方式去引用js 如果没有网络连接,可能会无法引用,作者使用 vue-cli3 搭建的 如果使用vue-cli2 的 )
![e1897b30b729b7ed91c2bbef9ccf9b6a.png](https://i-blog.csdnimg.cn/blog_migrate/ca1f9f42f3679c5d631e6320f7d0ae7f.png)
tinymce包 在 node_modules/tinymce 拷贝下来的 如下图
![eb71ceb93fcee3871c2c623361038a25.png](https://i-blog.csdnimg.cn/blog_migrate/b18ecf2ad18240a11ae007e60387f67c.png)
拷贝完后 还要到官网上去找语言包 最终目录如下
![2908ca7b1b84ef70d83e507a537a30b3.png](https://i-blog.csdnimg.cn/blog_migrate/6d7f3f583d761d9e4e3057be7d15d806.png)
好了,前期的准备工作完成了,接下该在页面中使用了
代码如下:
<template>
<div class="editor">
<editor :init="init" ref="editor" :tinymce-script-src="tinymceScriptSrc" @onInit="onReady"/>
<!-- <textarea id="tinymceEl" ref="tinymceRef"></textarea> -->
</div>
</template>
<script>
import Editor from '@tinymce/tinymce-vue'
export default {
components: { Editor, PhotoAlbum },
name: 'CkEditor',
props: {
baseUrl: {
type: String,
default: process.env.BASE_URL
}
},
data () {
return {
visible: false,
editor: null,
tinymceScriptSrc: '/tinymce/tinymce.min.js',//本地的tinymce文件地址
init: {
height: 500,
menubar: false,
resize: false, // 调整编辑器大小工具 true(仅允许改变高度), false(完全不让你动), 'both'(宽高都能改变,注意引号)
statusbar: true, // 显示隐藏状态栏 状态栏指的是编辑器最底下、左侧显示dom信息、右侧显示Tiny版权链接和调整大小的那一条。默认是显示的,设为false可将其隐藏。
branding: false, // 隐藏右下角技术支持
toolbar: 'code bullist numlist emoticons charmap hr insertdatetime link | help fullscreen image',
language: 'zh_CN',
language_url: '/tinymce/langs/zh_CN.js',
theme: 'silver',
theme_url: '/tinymce/themes/silver/theme.min.js',
base_url: '/tinymce',
suffix: '.min',
plugins: 'image,wordcount,charmap,code,hr,lists,advlist,emoticons,fullscreen,help,insertdatetime,link',
setup: function (editor) {
}
}
}
},
mounted () {
var that = this
this.init.clickImage = function (editor) {
that.visible = true
}
},
methods: {
onReady (e) {
this.editor = e.target
}
}
}
</script>
总算成功的引入了,接下来就要开发自己的组件了
功能:
1.导入图片, 作者不想使用自带的图片上传插件 如图:
![e82bd31bfe1aa8a819185efef2b15763.png](https://i-blog.csdnimg.cn/blog_migrate/154e6085ea958d2b86adf124ace6a67e.jpeg)
比较难用, 自己撸
先阅读一下插件的源码
![5974cbfb3d98a2dff1ef83899513706d.png](https://i-blog.csdnimg.cn/blog_migrate/739075f7edfc568875f1e58d79b1c40b.jpeg)
发现就是ui.registry.addButton 和 .ui.registry.addMenuItem 这两个方法注册插件的
onAction 就是点击事件触发器 怎么触发事件 直接打印 tinymce 全局 发现我们自定义的参数也可以在 tinymce.settings中找到 ojbk 找到解决方案了 直接在onAction中 去调用tinymce.settings中的回调函数 不就行了吗
最终实现效果
![04257082e879a595205c3e4fe2156467.png](https://i-blog.csdnimg.cn/blog_migrate/1f1aa8da74dc4ae33d8adb46ed760898.jpeg)
点击图片选择弹出自己写的弹窗组件
饶了一大圈 终于可以自由的开发 tinymce 组件, 想咋玩就咋玩呀
最终代码如下
!(function () {
'use strict'
var e = tinymce.util.Tools.resolve('tinymce.PluginManager')
var o = function (o) {
var e = o.getContent({
source_view: !0
})
o.windowManager.open({
title: 'Source Code',
size: 'large',
body: {
type: 'panel',
items: [{
type: 'textarea',
name: 'code'
}]
},
buttons: [{
type: 'cancel',
name: 'cancel',
text: 'Cancel'
},
{
type: 'submit',
name: 'save',
text: 'Save',
primary: !0
}],
initialData: {
code: e
},
onSubmit: function (e) {
var t, n
t = o,
n = e.getData().code,
t.focus(),
t.undoManager.transact(function () {
t.setContent(n)
}),
t.selection.setCursorLocation(),
t.nodeChanged(),
e.close()
}
})
}
!(function t () {
e.add('imageUpload', function (e) {
var t, n
return (t = e).addCommand('InsertImageUpload', function (e) {
if (Array.isArray(e) && e.length > 0) {
var html = ''
for (var i in e) {
var obj = e[i]
html += '<img src="' + obj + '" class="image" /><br />'
if (i < e.length - 1) {
html += '<br />'
}
}
t.execCommand('mceInsertContent', false, html)
}
}),
(n = e).ui.registry.addButton('imageUpload', {
icon: 'image',
tooltip: 'Insert/edit image',
onAction: function () {
if (typeof n.settings.clickImage === 'function') {
return n.settings.clickImage(n)
}
return null
}
}),
n.ui.registry.addMenuItem('imageUpload', {
icon: 'image',
text: 'Insert/edit image',
onAction: function () {
if (typeof n.settings.clickImage === 'function') {
return n.settings.clickImage(n)
}
return null
}
}),
{}
})
}())
}())
插件js /tinymce/plugins/imageUpload.js
<template>
<div class="editor">
<editor :init="init" ref="editor" :tinymce-script-src="tinymceScriptSrc" @onInit="onReady"/>
<!-- <textarea id="tinymceEl" ref="tinymceRef"></textarea> -->
<!-- 自定义弹窗组件 -->
<photo-album :visible.sync="visible" @confirm="confirm"></photo-album>
</div>
</template>
<script>
import Editor from '@tinymce/tinymce-vue'
import PhotoAlbum from '@/components/photoAlbum/src/album.vue'
export default {
components: { Editor, PhotoAlbum },
name: 'CkEditor',
props: {
baseUrl: {
type: String,
default: process.env.BASE_URL
}
},
data () {
return {
visible: false,
editor: null,
tinymceScriptSrc: '/tinymce/tinymce.min.js',
init: {
height: 500,
menubar: false,
resize: false, // 调整编辑器大小工具 true(仅允许改变高度), false(完全不让你动), 'both'(宽高都能改变,注意引号)
statusbar: true, // 显示隐藏状态栏 状态栏指的是编辑器最底下、左侧显示dom信息、右侧显示Tiny版权链接和调整大小的那一条。默认是显示的,设为false可将其隐藏。
branding: false, // 隐藏右下角技术支持
toolbar: 'code bullist numlist emoticons imageUpload charmap hr insertdatetime link | help fullscreen image',
language: 'zh_CN',
language_url: '/tinymce/langs/zh_CN.js',
// skin_url: '/tinymce/skins/lightgray',
// skin: 'oxide-dark',
theme: 'silver',
theme_url: '/tinymce/themes/silver/theme.min.js',
base_url: '/tinymce',
suffix: '.min',
plugins: 'image,wordcount,charmap,code,hr,lists,advlist,emoticons,fullscreen,help,insertdatetime,link,imageUpload',
setup: function (editor) {
}
}
}
},
mounted () {
var that = this
this.init.clickImage = function (editor) {
that.visible = true
}
},
methods: {
confirm (img) {
if (Array.isArray(img) && img.length > 0) {
img.forEach((item, index) => {
// 光标放最后?
this.editor.execCommand('selectAll')
this.editor.selection.getRng().collapse(false)
this.editor.focus()
var html = '<div><img src="' + item + '"/></div>'
this.editor.insertContent(html)
})
}
},
onReady (e) {
this.editor = e.target
}
}
}
</script>
弹窗组件就不贴了
我的项目是使用 antdv 开发的 是我自己没事鼓捣玩的一个项目(前后端 都是由本人开发的)
如果对源码敢兴趣的 可以在评论中 @作者一下 哟