如何在非Vue项目中使用vue-quill-editor实现粘贴纯文本功能?
在一个非Vue项目构建的、仅是普通的JavaScript项目里,只是简单地在页面引入了quill.js、vue-quill-editor.js、vue.js。
- 需要实现在vuequilleditor中粘贴文本时,将粘贴的富文本转换文纯文本,并插入到光标所在位置。
- 如果光标选中了部分内容,需要将选中的内容替换为粘贴文本。
- 插入文本后,需要修改光标位置到插入文本的后面
- 即使当前光标所在的位置(选中的文本)带有css样式,粘贴后的文本也不能带有样式。
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/quill@1.3.7/dist/quill.core.css">
<link rel="stylesheet" href="https://unpkg.com/quill@1.3.7/dist/quill.snow.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/quill@1.3.7/dist/quill.js"></script>
<script src="https://unpkg.com/vue-quill-editor@3.0.6/dist/vue-quill-editor.js"></script>
</head>
<body>
<div id="main">
<div style=" height: 100px;">
<quill-editor :options="editorOption" ref="myQuillEditor"></quill-editor>
</div>
</div>
<script type="application/javascript">
Vue.use(window.VueQuillEditor)
var toolbarOptions = [
['bold', 'underline'],
[{ 'color': ['blue', 'red', 'black'] }],
['link'],
['clean']
]
var main = new Vue({
el: "#main",
data: {
QuillEditors: [],
editorOption: {
scrollingContainer: null,
modules: {
toolbar: toolbarOptions
},
theme: 'snow'
},
},
methods: {
}
})
</script>
</body>
</html>
我尝过使用mounted函数,监听‘paste’事件,然后获取剪切板内容的文本格式(text/plain),再调用quill的insertText方法将文本内容插入。但是插入后,文本内容会受到 插入index所在的delta的样式的影响?
同样,删除时使用deleteText、insertText方法,结果也都不理想。
经过maxkiicc大佬的帮助,我已经解决了
- 需要实现在vuequilleditor中粘贴文本时,将粘贴的富文本转换文纯文本,并插入到光标所在位置。
- 插入文本后,需要修改光标位置到插入文本的后面
- 即使当前光标所在的位置(选中的文本)带有css样式,粘贴后的文本也不能带有样式。
尚未解决的问题为:
- 如果光标选中了部分内容,需要将选中的内容替换为粘贴文本。
问题描述:如果用光标选中一部分内容,然后再粘贴,会发现粘贴的内容被删除了光标选中文本长度的内容。比如:当前内容为:1234光标选中文本:23要粘贴的内容:index得到的结果:1dex4
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/quill@1.3.7/dist/quill.core.css">
<link rel="stylesheet" href="https://unpkg.com/quill@1.3.7/dist/quill.snow.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/quill@1.3.7/dist/quill.js"></script>
<script src="https://unpkg.com/vue-quill-editor@3.0.6/dist/vue-quill-editor.js"></script>
</head>
<body>
<div id="main">
<div style=" height: 100px;">
<quill-editor :options="editorOption" ref="myQuillEditor"></quill-editor>
</div>
</div>
<script type="application/javascript">
Vue.use(window.VueQuillEditor)
var toolbarOptions = [
['bold', 'underline'],
[{ 'color': ['blue', 'red', 'black'] }],
['link'],
['clean']
]
var main = new Vue({
el: "#main",
data: {
QuillEditors: [],
editorOption: {
scrollingContainer: null,
modules: {
toolbar: toolbarOptions
},
theme: 'snow'
},
},
mounted () {
var quill = this.$refs.myQuillEditor.quill
quill.root.addEventListener('paste', function (e) {
e.preventDefault()
const clipboardData = e.clipboardData || window.clipboardData
const pastedText = clipboardData.getData('text/plain')
requestAnimationFrame(() => {
const pasteLength = pastedText.length
const index = quill.selection.savedRange.index
const length = quill.selection.savedRange.length
// retain delete的index不能等于0
if (index === 0) {
if (length !== 0) {
quill.updateContents([
{
insert: pastedText,
},
{
delete: length
}
])
} else {
quill.updateContents([
{
insert: pastedText,
},
])
}
}
else {
if (length !== 0) {
quill.updateContents([
{
retain: index,
},
{
insert: pastedText,
},
{
delete: length
}
])
} else {
quill.updateContents([
{
retain: index,
},
{
insert: pastedText,
},
])
}
}
// 挪动光标到复制文本后
setTimeout(() => {
quill.setSelection(index + pasteLength, 0)
}, 0)
})
})
}
})
</script>
</body>
</html>

先说下解决方法吧,之前的思路太过复杂,Quill
提供了clipboard.addMatcher
方法,可以自定义粘贴的内容,通过clipboard.addMatcher
方法,我们可以将粘贴的富文本转换为纯文本。
initQuill() {
const NODE_TYPE = {
ELEMENT_NODE: 1
}
const quill = this.$refs.myQuillEditor.quill;
quill.clipboard.addMatcher(NODE_TYPE.ELEMENT_NODE, function (node, delta) {
// 获取粘贴的纯文本
var plaintext = node.innerText;
var Delta = Quill.import("delta");
return new Delta().insert(plaintext);
});
},
https://quilljs.com/docs/modules/clipboard
https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
然后你说的那个问题确实了触发了Quill的onPaste事件,它的回调函数中有一个异步事件,导致delta的更新发生了冲突。而且自定义paste事件会让它原本的一些功能失效。
----------update----------------------
不确定使用insertText会不会受到外部样式的影响,但是QuillJs提供了使用Delta
来编辑内容的api,你可以使用updateContents
来更新当前富文本编辑器的内容。Delta
本身是不包含当前操作 Index 的,所有操作都是从头开始,可以用retain
保留光标index
之前的内容。
https://quilljs.com/docs/api#updatecontents
https://quilljs.com/docs/delta#playground
但是我在测试过程中,当index === 0
的时候会报错,感觉是QuillJS的问题,你可以对delta
的细节处理一下。
pasteListenerCb(event) {
event.preventDefault();
let paste = (event.clipboardData || window.clipboardData).getData("text");
this.clipboardData = paste;
const pasteLength = paste.length;
const quill = this.$refs.myQuillEditor.quill;
const index = quill.selection.savedRange.index;
quill.updateContents([
{
retain: index,
},
{
insert: paste,
},
]);
},

- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容