VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
发布时间 - 2026-01-11 02:56:13 点击率:次0x00 前言

VueJS 社区里面关于富文本编辑器的集成也不少了,但是之前小调研了一下,基本上就是 quill,medium-editor,因为之前用 AngularJS 用过 medium-editor,并且需要自定义某些按钮,而且最好还是选中弹出式的,所以就决定用 medium-editor。
社区里面 star 较多的就是这个了:vue-medium-editor,但是打开它官网,看了看文档,越看越别扭,来看看它用法:
<!-- index.html --> <medium-editor :text='myText' :options='options' custom-tag='h2' v-on:edit='applyTextEdit'>
gosh,传这么多参数,我只想要一个简单的 editor 啊
打开源码一看,就 62 行,所以决定自己动手来一个简单点的
0x01 最简版
最简版,其实就在 vue 组件中实例化一下 medium-editor 就可以了
<template>
<div class="textEditor" @input="handleInput">
</div>
</template>
<script>
/* eslint-disable no-new */
import MediumEditor from 'medium-editor'
export default {
props: {
value: String,
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
editor: null // 用来存放 editor
}
},
watch: {
// refer: https://github.com/FranzSkuffka/vue-medium-editor/blob/master/index.js
value (newVal, oldVal) {
if (newVal !== this.$el.innerHTML) { // 用 $el.innerHTML 来解决 v-html 的光标跳到行首的问题
this.$el.innerHTML = newVal || ''
}
}
},
methods: {
handleInput (e) {
this.$emit('input', e.target.innerHTML)
}
},
mounted () {
// 处理初始值的情况
this.$el.innerHTML = this.value
// 这里当然可以自定义 options 啦
this.editor = new MediumEditor(this.$el, Object.assign({}, this.options))
// medium-editor 的 api,监听内容改变化
this.editor.subscribe('editableInput', this.handleInput)
},
beforeDestroy () {
this.editor.unsubscribe('editableInput', this.handleInput)
this.editor.destroy()
}
}
</script>
完成~,是不是很简单~~哈哈,最简版是一个 v-html 控制的,但是会有自动跳转到首行的问题,所以这里是最终版,细节问题看注释啦
0x02 用法
咋用呢?很简单,在其他组件中这样:
<text-editor v-model="vm.richText"></text-editor>
当然 你首先得安装 medium-editor的 js 和 css了
0x03 自定义 button
下面是我项目中用到的自定义 button 的相关代码,是一个 buttonBuilder:
import MediumEditor from 'medium-editor'
import rangy from 'rangy/lib/rangy-core.js'
import 'rangy/lib/rangy-classapplier'
import 'rangy/lib/rangy-highlighter'
import 'rangy/lib/rangy-selectionsaverestore'
import 'rangy/lib/rangy-textrange'
import 'rangy/lib/rangy-serializer'
const pHash = {
p1: { name: 'p1', class: 'fs-36' },
p2: { name: 'p2', class: 'fs-30' },
p3: { name: 'p3', class: 'fs-24' },
p4: { name: 'p4', class: 'fs-18' },
p5: { name: 'p5', class: 'fs-14' },
p6: { name: 'p6', class: 'fs-12' }
}
function pButtonCreator (p) {
return MediumEditor.Extension.extend({
name: p.name,
init: function () {
this.classApplier = rangy.createClassApplier(p.class, {
elementTagName: 'span',
normalize: false
})
this.button = this.document.createElement('button')
this.button.classList.add('medium-editor-action')
this.button.innerHTML = p.name
this.button.title = p.class
this.on(this.button, 'click', this.handleClick.bind(this))
},
getButton: function () {
return this.button
},
clearFontSize: function () {
MediumEditor.selection.getSelectedElements(this.document).forEach(function (el) {
if (el.nodeName.toLowerCase() === 'span' && el.hasAttribute('class')) {
el.removeAttribute('class')
}
})
},
handleClick: function (event) {
this.clearFontSize()
this.classApplier.toggleSelection()
// Ensure the editor knows about an html change so watchers are notified
// ie: <textarea> elements depend on the editableInput event to stay synchronized
this.base.checkContentChanged()
}
})
}
export default {
P1: pButtonCreator(pHash['p1']),
P2: pButtonCreator(pHash['p2']),
P3: pButtonCreator(pHash['p3']),
P4: pButtonCreator(pHash['p4']),
P5: pButtonCreator(pHash['p5']),
P6: pButtonCreator(pHash['p6'])
}
简单来说就是给选中的文字加一些 class (上面是 fs-xx 之类的),其中需要引一个鼠标选中的库 rangy,挺烦人的也是,然后在 text-editor 中这样用:
先实例化
import ButtonBuilder from './buttonBuilder'
var editorOptions = {
toolbar: {
buttons: ['bold', 'italic', 'underline', 'removeFormat', 'p3', 'p4', 'p5', 'p6']
},
buttonLabels: 'fontawesome', // use font-awesome icons for other buttons
extensions: {
p3: new ButtonBuilder.P3(),
p4: new ButtonBuilder.P4(),
p5: new ButtonBuilder.P5(),
p6: new ButtonBuilder.P6()
},
placeholder: false
}
再放到 editor 上
复制代码 代码如下:
this.editor = new MediumEditor(this.$el, Object.assign({}, editorOptions, this.options))
当然上面实例化的步骤不一定要写到这个组件里面,配置 options 也可以从组件外传入
0x04 细节和坑
1、这里用到了 v-model 的自定义实现,详见官方文档:v-model
简单来说呢就是 props: value ,和 this.$emit('input', model) 就可以实现在组件中模拟 v-model 啦
2、多个 editor 使用的自定义button 实例的问题。由于我自己应用的时候有两个挨着的 <text-editor>,用的上面的代码会导致两个 editor 实例用的是同一个 button 实例,这会导致一个很严重的问题:即编辑下面编辑器的内容,可能会修改的上面的编辑器!!
要解决这个也很简单,修改这一行:
复制代码 代码如下:
this.editor = new MediumEditor(this.$el, Object.assign({}, _.cloneDeep(editorOptions), this.options))
将自定义的 options 深复制一下,这里借助了 lodash 的函数。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Vue集成Medium
# Editor
# Vue
# Medium
# vue项目中应用ueditor自定义上传按钮功能
# Vue写一个简单的倒计时按钮功能
# vue实现验证码按钮倒计时功能
# vue 开发一个按钮组件的示例代码
# Vue.js 点击按钮显示/隐藏内容的实例代码
# Vue.js表单标签中的单选按钮、复选按钮和下拉列表的取值问题
# 详解vue + vuex + directives实现权限按钮的思路
# Vue.js实现按钮的动态绑定效果及实现代码
# vue组件中点击按钮后修改输入框的状态实例代码
# 使用vue实现点击按钮滑出面板的实现代码
# Vue波纹按钮组件制作
# 自定义
# 是一个
# 编辑器
# 很简单
# 就可以
# 的是
# 文档
# 也不
# 会有
# 就在
# 鼠标
# 弹出式
# 多个
# 我只
# 这么多
# 也很
# 看了看
# 少了
# 较多
# 用过
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】
Linux系统命令中tree命令详解
如何确保西部建站助手FTP传输的安全性?
在线制作视频的网站有哪些,电脑如何制作视频短片?
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
如何用已有域名快速搭建网站?
如何在局域网内绑定自建网站域名?
Laravel如何自定义错误页面(404, 500)?(代码示例)
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
Laravel如何与Inertia.js和Vue/React构建现代单页应用
iOS中将个别页面强制横屏其他页面竖屏
如何在七牛云存储上搭建网站并设置自定义域名?
深圳网站制作的公司有哪些,dido官方网站?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
微信公众帐号开发教程之图文消息全攻略
Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】
Laravel Blade模板引擎语法_Laravel Blade布局继承用法
php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】
如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)
java获取注册ip实例
如何用美橙互联一键搭建多站合一网站?
canvas 画布在主流浏览器中的尺寸限制详细介绍
如何用5美元大硬盘VPS安全高效搭建个人网站?
如何在腾讯云服务器快速搭建个人网站?
Linux系统运维自动化项目教程_Ansible批量管理实战
猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】
如何快速重置建站主机并恢复默认配置?
Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
javascript中的try catch异常捕获机制用法分析
如何在阿里云ECS服务器部署织梦CMS网站?
Laravel观察者模式如何使用_Laravel Model Observer配置
如何用JavaScript实现文本编辑器_光标和选区怎么处理
HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】
JavaScript模板引擎Template.js使用详解
html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】
深入理解Android中的xmlns:tools属性
Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
用v-html解决Vue.js渲染中html标签不被解析的问题
长沙做网站要多少钱,长沙国安网络怎么样?
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?
中山网站制作网页,中山新生登记系统登记流程?
Python制作简易注册登录系统
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
EditPlus中的正则表达式 实战(4)
Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决
济南网站建设制作公司,室内设计网站一般都有哪些功能?

