首先需要绑定两个事件 compositionstart、compositionend 两个事件分别是输入法唤起输入法关闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setup: (ed) => {
const vm = this;
ed.on("keyup", function (e) {
vm.wordLimit(e);
});
ed.on("input", function (e) {
vm.wordLimit(e);
});
ed.on("compositionstart", function (e) {
vm.isChinese = false;
});
ed.on("compositionend", function (e) {
vm.isChinese = true;
});
};

在 keyup 和 keyinput 事件里调用核心字数控制函数并且代入 event,输入法输入时 innerText 有可能跳过 1000 所以要兼容下输入跳过问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//字数限制
wordLimit (e) {
const vm = this
let last = ''
let lastIndex = ''
let startVal = ''
let endVal = ''
if (e.target.innerText.length === 1000) {
vm.htmlText = e.target.innerHTML
//兼容输入法有可能会跳过1000
} else if ((!vm.isChinese && e.target.innerText.length === 1001)) {
last = e.target.innerText.substr(e.target.innerText.length - 1, 1)
lastIndex = e.target.innerHTML.lastIndexOf(last)
startVal = e.target.innerHTML.substring(0, lastIndex)
endVal = e.target.innerHTML.substring(lastIndex + 1, e.target.innerHTML.length)
vm.htmlText = startVal + endVal
}
if (e.target.innerText.length > 1000) {
e.target.innerHTML = vm.htmlText
var ifra = document.getElementById("tinymces_ifr");
this.keepLastIndex(ifra.contentWindow.document.getElementById('tinymce'), ifra.contentWindow)
if (!this.limitNum) {
this.$message.error('长度限制为1000个字符')
this.limitNum++
}
}
},

整体的核心思路判断富文本编辑器的 innerText 的字符数量,如果到达了指定文字那么我们就记录下当前的 innerHTML,当超过了指定数量我们就把之前记录的 innerHTML 赋值给 e.target.innerHTML,防止用户继续输入,要注意的是发往后端的是 innerHTML 是带有 HTML 标签的所以后端不要进行字符拦截,纯前端拦截。
只做了这些可以解决正常输入限制字数,这里还有一个问题是粘贴的时候这部分的思路是粘贴时候过滤掉所有的标签然后用限制字数减去输入框现有字数可以知道距离输入框限制字数还有多数个字符,然后在插入的时候用限制字数减去输入框内容字数就可以啦,这里有个 this.limitNum 参数,这个是我项目的需求,主要作用是超过 1000 字符长度弹框只弹一次,有这个需求自行添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
init_instance_callback: (editor) => {
// 注册事件
editor.on('paste', (e) => {
var ifra = document.getElementById("tinymces_ifr");
e.preventDefault();
var contentOnBlur = (e.originalEvent || e).clipboardData.getData('text/plain');
contentOnBlur = contentOnBlur.replace(/(<([^>]+)>)/ig, '');
if (!(1000 - e.target.innerText.length) && !this.limitNum) {
this.$message.error('长度限制为1000个字符')
this.limitNum++
}
ifra.contentWindow.document.execCommand('insertText', true, contentOnBlur.slice(0, 1000 - e.target.innerText.length));
});
},