首先需要绑定两个事件compositionstart、compositionend两个事件分别是输入法唤起输入法关闭
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所以要兼容下输入跳过问题
//字数限制 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字符长度弹框只弹一次,有这个需求自行添加
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)); }); },
本人前端小白一昧,有更好的方案希望大佬指点。