Nuxt集成CKEditor5 Balloon Block报editor-isreadonly-has-no-setter错误
Nuxt集成CKEditor5 Balloon Block模式异常问题
问题描述
- 场景:Nuxt项目中使用CKEditor5 balloon block模式,通过官方在线构建工具下载构建文件,添加到项目后引入编辑器组件使用
- 报错:页面加载时抛出错误 editor-isreadonly-has-no-setter
- 异常表现:给编辑器绑定v-model后,绑定值无法同步更新
- 对比验证:使用完全相同的方式集成CKEditor5经典模式时,未出现同类问题,暂未定位根因
- 问题组件代码如下:
<template> <ckeditor :id="id" v-bind="$attrs" :editor="BalloonBlock" :config="editorConfig" v-on="$listeners" /> </template> <script> let BalloonBlock let CKEditor if (process.client) { BalloonBlock = require('@/plugins/ckeditor/ckeditor') CKEditor = require('@ckeditor/ckeditor5-vue2') } else { CKEditor = { component: { template: '<div></div>' } } } export default { name: 'CKEditor', components: { ckeditor: CKEditor.component, }, props: { fillErr: { type: Boolean, default: false, required: false, }, minHeight: { type: String, default: '350px', required: false, }, label: { type: String, default: '', required: false, }, }, data() { return { classicEditor: BalloonBlock, editorConfig: { language: 'fa', contentsLangDirection: 'rtl', }, editorElement: null, id: null, } }, computed: { value() { return this.$attrs.value }, }, created() { this.id = this.uuidv4() }, mounted() { if (!document.getElementById('editorFaTranslate')) { const faScript = document.createElement('script') faScript.setAttribute('charset', 'utf-8') faScript.setAttribute('type', 'text/js') faScript.setAttribute('id', 'editorFaTranslate') faScript.setAttribute( 'src', require('@@/plugins/ckeditor/translations/fa.js') ) document.head.appendChild(faScript) } const intervalId = setInterval(() => { const ckEditor = document.getElementById(this.id) if (ckEditor) { clearInterval(intervalId) this.editorElement = ckEditor } }) }, methods: { uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( /[xy]/g, function (c) { const r = (Math.random() * 16) | 0 const v = c === 'x' ? r : (r & 0x3) | 0x8 return v.toString(16) } ) }, insertTextAtTheEnd(text) { function findCorrectPosition(htmlStr) { const lastIndexOfHTMLTag = htmlStr.lastIndexOf('</') const lastUlTag = htmlStr.lastIndexOf('</ul>') const lastOlTag = htmlStr.lastIndexOf('</ol>') if ( lastUlTag === lastIndexOfHTMLTag || lastOlTag === lastIndexOfHTMLTag ) { const lastLiTag = htmlStr.lastIndexOf('</li>') return lastLiTag } return lastIndexOfHTMLTag } const currentString = this.value const correctIndex = findCorrectPosition(currentString) const firstHalf = currentString.substring(0, correctIndex) const secondHalf = currentString.substring(correctIndex) const newString = `${firstHalf}${text}${secondHalf}` this.$emit('input', newString) }, }, } </script>
解决思路
- 优先对齐依赖版本:editor-isreadonly-has-no-setter报错的核心诱因通常是版本不匹配。确认在线构建下载的CKEditor5版本号,和本地安装的
@ckeditor/ckeditor5-vue2依赖兼容的CKEditor版本完全一致。高版本CKEditor5移除了isReadOnly属性的直接赋值setter,仅支持通过setReadOnly()方法修改只读状态,若Vue适配层版本过低,仍尝试直接给isReadOnly赋值就会触发该报错,初始化失败后自然无法同步v-model值。 - 修复翻译脚本加载错误:代码中动态插入的波斯语翻译脚本,
type属性被设置为无效值text/js,浏览器无法识别该MIME类型,不会执行脚本内容,会导致编辑器语言模块初始化异常,将该属性值改为text/javascript即可。 - 修复SSR阶段变量异常:模板中绑定的
:editor="BalloonBlock"引用的是顶层作用域变量,服务端渲染阶段process.client为false,BalloonBlock未赋值为undefined,会引发hydration不匹配问题。直接使用data中已经定义的classicEditor字段即可,将模板中对应绑定改为:editor="classicEditor"。 - 移除高消耗的DOM轮询逻辑:现有代码中
setInterval未设置间隔时间,会默认以0ms间隔持续轮询DOM,占用主线程资源,反而可能阻塞编辑器初始化。如果需要获取编辑器实例,直接监听ckeditor组件的ready事件,在事件回调中拿实例即可,无需轮询DOM。 - 排查透传属性:检查父组件调用该封装组件时,是否默认传入了
disabled或readonly属性,Vue适配层接收到这两个属性会尝试修改编辑器只读状态,版本不匹配时就会触发开头的报错。
内容的提问来源于stack exchange,提问作者hossein samani
相关产品推荐
相关产品推荐

