前言
继上一章,我们实现了富文本框字数限制,到上一章呢,基本上得功能已经可以实现了。接下来就是扩展章节了,我会继续去探索更多得自定义菜单,今天先开一个简单得——“首行缩进”,感兴趣就继续往下看看吧~
一、首行缩进
富文本编辑器本身提供了一种缩进,可以实现整体得缩进,效果如下:
上图可以看到,如果点击了缩进,这个段落都会缩进。但我不需要一段都缩进,我只希望他首行缩进,所以今天我们就要实现下图得功能:
二、自定义菜单
具体位置如下图:
1.引入wangEditor
因为新建了一个文件,所以要重新引入。
引入BtnMenu是因为我们要自定义一个BtnMenu菜单
import E from "wangeditor";
const { $ } = E;
const { BtnMenu, DropListMenu, PanelMenu, DropList, Panel, Tooltip } = E;
2.通过class 来扩展
根据官方写法,这里就用class的方式来新建一个菜单吧~
class AlertMenu extends BtnMenu {}
注意啦!!接下来的内容都写在class里面
- 首先我们要创建一个菜单,指定一个图标,让他显示在菜单栏上
通过constuctor创建一个菜单,并加上hover文字
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="首行缩进" style="z-index:auto;">
<i class="el-icon-s-fold"></i>
</div>`
);
super($elem, editor);
}
菜单有啦,我们点击这个菜单的时候会发生什么事情呢~
- 接下来我们就写点击菜单后要做什么事情
首先,我来描述一下大概思路,以便代码更好理解:
我们要定义一个方法,该方法我们需要 去获取选中的dom,判断当前是否添加了首行缩进样式,有就取消,没有就加上。最后我们恢复选取
// 菜单点击事件
clickHandler(value) {
const editor = this.editor;
const $elems = editor.selection.getSelectionRangeTopNodes(); //$elems——选中完整段落或多个段落——上级节点
if ($elems.length > 0) {
$elems.forEach(item => {
// operateElement($(item), value, editor)
const $elem = $(item).getNodeTop(editor); //获取选中的上一级节点
const reg = /^(P|H[0-9]*)$/; //判断是不是p\h标签
//getNodeName获取标签名
if (reg.test($elem.getNodeName())) {
const $elem1 = $elem.elems[0]; //获取每一行的带标签内容
if ($elem1.style["textIndent"] === "") {
//如果此时的样式没有缩进,就添加缩进样式
$elem.css("text-indent", "2em");
} else {
//如果此时的样式有缩进,就取消缩进样式
$elem.css("text-indent", "");
}
}
});
}
// 恢复选区
editor.selection.restoreSelection();
this.tryChangeActive(); //菜单高亮
}
首行缩进的样式已经实现了,但是这个菜单点击后的激活效果没有实现也,
- 所以接下来我就来实现,首行缩进的菜单激活效果。
还是说一下思路:
获取选中的文本的dom信息,如果不存在节点信息,就可以止步于此。如果存在上级节点信息,代表这选中的是这一行,可以首行缩进,再判断当前dom是否有样式,有就调用active(),没有就调用unActive()
tryChangeActive() {
// 激活菜单
// 1. 菜单 DOM 节点会增加一个 .w-e-active 的 css class
// 2. this.this.isActive === true
// this.active()
const editor = this.editor;
const $selectionElem = editor.selection.getSelectionStartElem(); //获取选中的dom信息
const $selectionStartElem = $($selectionElem).getNodeTop(editor); //获取选中的上级节点信息
console.log($selectionElem, $selectionStartElem.length <= 0, "这是啥");
if ($selectionStartElem.length <= 0) return; //如果没有上级节点就止步于此
if ($selectionStartElem.elems[0].style["textIndent"] != "") {
//如果有样式,就激活菜单
// active 、unActive方法是官方提供的菜单激活方法
this.active();
} else {
this.unActive();
}
3.导出自定义菜单
最后我们export这个菜单:
export default AlertMenu;
4.页面使用
到第三步这个菜单功能和效果已经实现啦,那么我们就只需要再页面中注册这个菜单啦,切换到editor.vue页面
- 引入刚才自定义的菜单
import AlertMenu from "./components/textIndent";
然后再_initEditor()方法第一行注册菜单名,将这个菜单加到原本菜单中去
const menuKey = "textIndent"; // 给定菜单名
var editor = new E(this.$refs.editor);
// 注册菜单
editor.menus.extend(menuKey, AlertMenu);
editor.config.menus = editor.config.menus.concat(menuKey);
看一下结构图,别写错位置啦哟~
好啦,到这里这个首行缩进菜单功能就实现啦,这个算是不难的功能啦吧,不过我第一次接触富文本编辑器还是思考了很久~~
总结
以上就是今天要讲的内容,本文仅仅简单自定义首行缩进菜单的思路和实现,好啦好啦,希望能够帮助到你啦,或者开阔一下思维也可以滴~。如果有什么想法也可以评论区留言给我哟~白白啦