Vue + UEditor + v-model 双向绑定。之所以有这个
repo
的原因是:
1、UEditor 依然是国内使用频率极高的所见即所得编辑器而 Vue 又有着广泛的使用,所以将两者结合使用,是很多 Vue 项目开发者的切实需求。
2、目前没有发现满足这种需求,而使用又很方便的repo
、有的可能也只是简单的暴露一个UEditor
的实例,仍然需要开发者手动去调用getContent
,setContent
,而通过v-model
绑定数据也是很多人期待的方式。于是自己在写公司项目时就手动撸了一个,周末整理一下分享出来,希望能帮助到有同样需求的小伙伴。
npm i vue-ueditor-wrap
# 或者
yarn add vue-ueditor-wrap
Quick Start(基于 vue-cli 2.x 的完整DEMO)
-
下载 UEditor下载最新编译的 UEditor。官网目前最新的版本是
1.4.3.3
,存在诸多 BUG,例如 Issue1 和 Issue8,且官方不再积极维护。为了世界的和平,针对一些常见 BUG,我进行了修复,并把编译好的文件放在了本仓库的assets/downloads
目录下,你可以放心下载,当然你也可以自己clone
官方源码并编译。将下载的压缩包解压并重命名为
UEditor
(只需要选择一个你需要的版本,比如utf8-php
),放入你项目的static
目录下如果你使用的是 vue-cli 3.x,可以把
UEditor
文件夹放入你项目的public
目录下。 -
引入
VueUeditorWrap
组件import VueUeditorWrap from 'vue-ueditor-wrap' // ES6 Module // 或者 const VueUeditorWrap = require('vue-ueditor-wrap') // CommonJS
你也可以通过直接引入
CDN
链接的方式来使用,它会暴露一个全局的VueUeditorWrap
变量(具体如何使用你可以阅读我的这篇博客或参考这个仓库)。<script src="https://cdn.jsdelivr.net/npm/vue-ueditor-wrap/lib/vue-ueditor-wrap.min.js"></script>
-
注册组件
components: { VueUeditorWrap }, // 或者在 main.js 里将它注册为全局组件 Vue.component('vue-ueditor-wrap', VueUeditorWrap)
-
v-model
绑定数据<vue-ueditor-wrap v-model="msg"></vue-ueditor-wrap>
data () { return { msg: '<h2><img src="http://img.baidu.com/hi/jx2/j_0003.gif"/>Vue + UEditor + v-model双向绑定</h2>' } },
-
根据项目需求修改配置,完整配置选项查看 ueditor.config.js 源码或 官方文档
<vue-ueditor-wrap v-model="msg" :config="myConfig"></vue-ueditor-wrap>
data () { return { msg: '<h2><img src="http://img.baidu.com/hi/jx2/j_0003.gif"/>Vue + UEditor + v-model双向绑定</h2>', myConfig: { // 编辑器不自动被内容撑高 autoHeightEnabled: false, // 初始容器高度 initialFrameHeight: 240, // 初始容器宽度 initialFrameWidth: '100%', // 上传文件接口(这个地址是我为了方便各位体验文件上传功能搭建的临时接口,请勿在生产环境使用!!!) serverUrl: 'http://35.201.165.105:8000/controller.php', // UEditor 资源文件存放的根目录,如果你使用的是 vue-cli 3.x,设置为'/UEditor/'(参考下方的常见问题2) UEDITOR_HOME_URL: '/static/UEditor/' } } },
至此你已经可以在页面中看到一个初始化之后的
UEditor
了,并且它已经成功和数据绑定了!👏👏👏
-
如何获取
UEditor
实例?<vue-ueditor-wrap @ready="ready"></vue-ueditor-wrap>
methods: { ready (editorInstance) { console.log(`编辑器实例${editorInstance.key}: `, editorInstance) } }
-
设置是否在组件的
beforeDestroy
钩子里销毁UEditor
实例<vue-ueditor-wrap :destroy="true"></vue-ueditor-wrap>
-
如何自定义按钮?
结合组件的
init
属性和registerButton
方法,可以方便地添加自定义按钮,来对 window.UE 进行二次开发。init 函数将在 scripts 加载完毕、UEditor 初始化之前运行。DEMO 仓库中提供了自定义“表格居中”按钮的示例。<template> <vue-ueditor-wrap ref="editor" v-model="msg" :init="myInit"></vue-ueditor-wrap> </template> <script> export default { methods: { myInit () { this.$refs.editor.registerButton({ name: 'test', icon: '/static/test-button.png', tip: 'this is a test tip', index: 0, handler: (editor, name) => { editor.execCommand('inserthtml', `<span>text inserted by test button</span>`) } }) } } } </script>
参数:
name
按钮名称、icon
按钮图标、tip
按钮 hover 时显示的提示文、index
自定义按钮在工具栏的位置索引、handler
以 editor 和 name 为入参的按钮动作函数。
-
v-model
双向数据绑定!你不需要考虑实例化,也不需要考虑何时getContent
,何时setContent
,简单到像使用input
框一样! -
完全遵从官方
API
,所有的配置参数和实例方法与官方完全一致。通过给vue-ueditor-wrap
组件的config
属性传递一个对象,你就可以得到一个完全独立配置的UEditor
编辑器。通过监听ready
事件你就可以得到初始化后的UEditor
实例并执行实例上的各种方法。 -
自动添加依赖文件。你不需要自己在
index.html
或main.js
里引入UEditor
的 JS 文件。更重要的是即使你在一个页面里同时使用多个vue-ueditor-wrap
组件,它所依赖的 JS 文件也只会加载一次。这么做的原因在于你不需要当用户一打开项目就先加载大量UEditor
相关的资源,所有的资源文件只会在vue-ueditor-wrap
组件第一次被激活时才加载。当然,如果你在index.html
或main.js
里引入了相关资源,vue-ueditor-wrap
也会准确判断,你不用担心它会重复加载。 -
每个
vue-ueditor-wrap
组件是完全独立的。你甚至可以在上面使用v-for
指令一次渲染 99个 兔斯基(不要忘记添加key
值)。
-
是否支持
IE
等低版本浏览器?与
Vue
相同,支持到IE9。
👏👏👏 -
为什么我会看到这个报错?
这是
UEDITOR_HOME_URL
参数配置错误导致的。建议使用绝对路径。如果你的项目不是部署在网站根目录下,比如"http://www.example.com/my-app/"
,你可能需要设置为"/my-app/static/UEditor/"
。路由是否使用history
模式、是否设置base
、服务器配置是否正确等等都有可能会产生影响。总而言之:无论本地开发和部署到服务器,你所指定的UEditor
资源文件是需要真实存在的,vue-ueditor-wrap
也会在 JS 加载失败时在控制台输出它试图去加载的资源文件的完整路径,你可以借此分析如何填写。当需要区分环境时,你可以判断process.env.NODE_ENV
来分别设置。 -
我该如何上传图片和文件?为什么我会看到
后台配置项返回格式出错
?上传图片、文件等功能是需要与后台配合的,而你没有给
config
属性传递正确的serverUrl
,我提供了http://35.201.165.105:8000/controller.php
的临时接口,你可以用于测试,但切忌在生产环境使用!!! 关于如何搭建上传接口,可以参考官方文档。 -
单图片跨域上传失败!
这是
UEditor
的BUG
,你可以通过配置toolbars
参数来隐藏单图片上传按钮,并结合上面介绍的“自定义按钮”,曲线救国,以下代码仅供参考。var input = document.createElement('input') input.type = "file" input.style.display = 'none' document.body.appendChild(input) input.click() input.addEventListener('change',(e)=>{ // 利用 AJAX 上传,上传成功之后销毁 DOM console.log(e.target.files) })
-
为什么我输入的
"? ! $ #"
这些特殊字符,没有成功绑定?那时因为
v-model
的实现基于对UEditor
实例上contentChange
事件的监听,由于你输入这些特殊字符时通常是按住shift
键的,UEditor
本身的contentChange
在shift
键按住时不会触发,你也可以尝试同时按下多个键,你会发现contentChange
只触发一次。所有我也很无奈呀!请移步 UEditor。 -
单图片上传后
v-model
绑定的是loading
小图标。这个也是
UEditor
的BUG
。我最新编辑的版本,修复了官方的这个BUG
,如果你使用的是官网下载的资源文件,请替换资源文件或参考 Issue1。
更多问题,欢迎提交 ISSUE 或者去 聊天室 提问。但由于这是一个个人维护的项目,我平时也有自己的工作,所以并不能保证及时解决你们的所有问题,如果小伙伴们有好的建议或更炫酷的操作,也欢迎
PR
,如果你觉得这个组件给你的开发带来了实实在在的方便,也非常感谢你的Star
,当然还有咖啡:
代码修改请遵循指定的
ESLint
规则,PR
之前请先执行npm run lint
进行代码风格检测,大部分语法细节可以通过npm run fix
修正,构建之后,记得修改package.json
里的版本号,方便我Review
通过后麻溜溜的发布到npm
。