问题描述
Tinymce 富文本编辑器作为子组件引入时,如果富文本编辑器已经绑定过值,再通过 v-model 双向绑定去更新值时,值不会发生变化
这是我第三次单击编辑,此时由于富文本中已经有值,再次回写不生效,因此预览正确应该为 a,但是富文本中不正确。
问题分析
代码位置:/src/components/Tinymce/index.vue
该文件是 Tinymce
富文本子组件,其中监听器中 value
就是用来更新富文本中的值的
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || ''))
}
},
},
你会发现这个判断,含义是值不变化时才走下面的赋值,由于没研究过富文本,因此我通过简单粗暴的 console.log 对值进行分析,然后去找了这个值变动的地方,得出以下结论
!this.hasChange
- 第一次编辑: 由于富文本组件未初始化,直接通过 v-model 回写是成功的,此时没有触发这个监听器,但是会通过初始化函数 init_instance_callback 进行回写。
- 第二次编辑: 富文本组件已初始化,此次编辑
value 监听器
成功触发回写,所以第二次也是成功的。但也会触发 init_instance_callback 中的 editor.on 函数,此时this.hasChange
会被变成true
,目的是让你在编辑时候不会触发value 监听器
,因此 editor.on 这个函数应该是进入编辑状态的意思 - 第三次编辑: 由于第二次中
this.hasChange
变成true
,因此!this.hasChange
为false
,value 监听器
就不再起作用了,这也是为什么,第三次开始回写就不成功。
init_instance_callback
init_instance_callback: editor => {
if (_this.value) {
editor.setContent(_this.value)
}
_this.hasInit = true
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true
this.$emit('input', editor.getContent())
})
},
解决方案
首先一点,我们不能去除 !this.hasChange
的判断,因为这个是为了防止你在编辑时候,触发回写导致卡顿与失去焦点,可以自己试下。
因此我的方案就是父组件去调用子组件中的赋值函数从而实现回写。
子组件函数:
搜下就有了,通过这个函数能实现回写
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value)
},
父组件调用:
Tinymce 增加 ref 引用来获取子组件信息
<tinymce ref="tinymce" v-model="form.text" :height="300" />
然后在编辑时候直接调用子组件的 setContent(value) 函数进行赋值
if (this.$refs['tinymce'] !== undefined) {
this.$refs['tinymce'].setContent(this.form.text)
}