当前位置: 首页 > Web前端 > vue.js

600行代码,只为让wangEditor5在vue3中更好用

时间:2023-03-31 23:05:51 vue.js

.border{border:1pxsolid#ddd;}1。前言WangEditor5公测已经有一段时间了,经常有人在公测群里问关于官方vue组件的问题,所以我开始使用,从这个角度总结一下目前@wangeditor/editor的一些缺陷-for-vue@next:editorId的设置允许我们获取编辑器的实例。虽然最终的效果是达到了,但是使用起来效率不是很高,而且还不够傻。并且需要在编辑器销毁后使用editorId手动清除缓存。如果用户忘记了这一步,就会造成内存泄漏。异步设置内容时,需要额外的变量来控制编辑器的创建,增加了使用的复杂度。这对傻瓜来说也是不够的。-model将数据的同步推送给了用户,增加了使用的复杂度。vue是一个支持双向绑定的框架,我们组件库的一些特殊配置项是没有响应式的。如果用户可以通过editable.config。readOnly=false可以禁用编辑器,使用editable.mode='simple'来切换编辑器模式,那么它会为用户省略n多行代码,处理事件也比较傻。很明显,你可以直接使用config.onChange=()=>{}但是我坚持单独提一下。特殊场景不明白:在一个页面中,文章列表在左边,编辑器在右边。点击列表中的文章,编辑器会自动显示该文章的内容,不会有历史记录(之前QQ群某用户的需求)。针对这种情况,用户只能不断控制某个变量,先给变量赋值false,再赋值true,销毁重建编辑器。如果能为用户提供一个reloadEditorAPI,使用起来会更方便。针对以上缺陷,在21/12/21这天开始尝试封装一个自认为好用的vue3组件。截至21/12/30,它将完全完成。该组件支持的功能有:支持动态配置编辑器参数(创建编辑器后修改配置项不会生效)支持v-model和v-model:html形式的双向绑定支持用于在不存在的情况下动态显示默认内容旧文档的历史记录和默认内容的配置项支持json数组、json字符串和html字符串三种格式的数据。自然支持TypeScript。由于这个原因,目前没有发布npm包。有需要的可以从GitHub上扒一扒(只有一个文件),如果觉得好用的话不妨给个star吧。2.自封组件的使用2.1.全局注册组件import{createApp}from'vue'importwangeditorfrom'xxx/wangeditor'//全局注册EditorToolbar、EditorEditable两个组件createApp(App).use(wangeditor).mount('#app')2.2.快速入门.border{border:1pxsolid#ddd;}2.3、Vuehook:useWangEditor经过useWangEditor处理后,返回的editable和toolbar对应分别到编辑器和菜单栏配置项,但是此时配置项对象具有响应式的特性,我们可以直接修改editable/toolbar更新或重新加载编辑器的相应属性如果传入的editableOption和toolbarOption是响应式数据,内部关联会自动解除关联,也就是说经过useWangEditor处理后得到的editable和toolbar配置对象即使内容发生变化也不会触发之前的依赖更新!!!/***vuehook,用于实现编辑器配置项的动态绑定*@param{Object}编辑器主体部分editableOption配置*@param{Object}toolbarOption菜单栏配置*@param{Number}reloadDelay反shakeDuration,延迟控制重载,单位:毫秒*/declarefunctionuseWangEditor(editableOption:EditorEditableOption|null=null,toolbarOption:EditorToolbarOption|null=null,reloadDelay:number=365):{editable:Requiredtoolbar:RequiredgetEditable:()=>IDomEditor|未定义的getToolbar:()=>工具栏|undefinedclearContent:()=>voidreloadEditor:()=>void}2.3.1、配置项:EditorEditableOption/***Editor配置项*/interfaceEditorEditableOption{/**editormode*/mode?:'default'|'simple'/**编辑器初始化的默认内容*/defaultContent?:Descendant[]|字符串|null/**编辑器配置,具体配置以官方为准*/config?:Partial/**v-model/v-model:html数据同步防抖时长,默认值:3650,单位:毫秒*/delay?:number/***编辑器创建时默认内容的优先排序,默认值:true*true:v-model>v-model:html>defaultContent。*false:defaultContent>v-model>v-model:html。*/extendCache?:boolean}2.3.2、配置项:EditorToolbarOption/***菜单栏配置项*/interfaceEditorToolbarOption{mode?:'default'|'simple'config?:Partial}2.4、动态修改配置const{editable,toolbar}=useWangEditor()editable.config.placeholder='newplaceholder'//切换到只读模式editable.config.readOnly=truetoolbar.mode='simple'2.4.1、数据优先:EditorEditableOption.extendCache当v-model/v-model:html和defaultContent同时使用时,我们可以使用extendCache配置项来控制默认内容重新加载后的编辑器。当extendCahce为true时,编辑器创建/重新加载时显示内容的优先级为:v-model>v-model:html>defaultContent。当extendCache为false时,编辑器创建/重新加载时显示内容的优先级为:defaultContent>v-model>v-model:html。false模式可能会导致数据丢失,所以在重新加载编辑器之前必须保存数据。我们可以配置reloadbefore事件来保存数据。2.4.2.默认值:EditorEditableOption.defaultContentdefaultContent的改变默认不会触发编辑器的重新加载。如果需要直接显示defaultContent的内容,我们需要通过reloadEditor强制让编辑器重新加载。并且需要注意extendCache对重载后编辑器默认内容的影响。const{editable,toolbar,reloadEditor}=useWangEditor()onMounted(()=>{setTimeout(()=>{//当你绑定v-model/v-model:html时,如果你想编辑后编辑器是reloaded,//新设置的默认值会显示为编辑器的默认内容,这时需要设置extendCache为false,//这样会造成编辑器内容丢失,可以配合reloadbefore事件合理处理editable.extendCache=false//然后修改配置editable.defaultContent=[{type:'header1',children:[{text:'Header1'}]}]//也支持字符串形式的JSONeditable.defaultContent='[{"type":"header1","children":[{"text":"Header1"}]}]'//兼容HTML字符串(不推荐,有缺陷)editable.defaultContent='

TitleOne

Paragraph

'//最后还需要强制重新加载编辑器reloadEditor()},5000)})2.5、编辑器/菜单栏重新加载EditorEditableOption改为.mode,EditorEditableOption.config.hoverbarKeys、EditorEditableOption.config.maxLength和EditorEditableOption.config.customPaste将触发编辑器重新加载。其他EditorEditableOption配置项只支持动态配置,不会触发Overloading,避免了不必要的资源消耗。如果需要强制重新加载编辑器,也提供了reloadEditor接口供用户手动触发。与EditorEditableOption不同的是,EditorToolbarOption的任何一个选项的变化都会触发菜单栏的重新加载。const{reloadEditor}=useWangEditor()//强制重新加载编辑器reloadEditor()2.5.1、重新加载前:reloadbefore事件编辑器重新加载前,会触发reloadbefore事件。2.6.清除内容不仅会清除编辑器内容,还会同步v-model/v-model:htmldataconst{clearContent}=useWangEditor()clearContent()2.7.获取菜单栏实例const{getToolbar}=useWangEditor()consttoolbarInstance:Toolbar|undefined=getToolbar()if(toolbarInstance){//做某事}else{//做某事}2.8。获取编辑器实例const{getEditable}=useWangEditor()consteditableInstance:IDomEditor|undefined=getEditable()if(editableInstance){console.log(editableInstance.children)}else{console.error('Editorisnotinstantiated')}2.9、支持v-modelEditorEditable同时支持v-modelData与v-model:html绑定,分别对应json数组和html字符串中的数据。两种格式可以同时绑定,也可以单独绑定v-model或v-model:html。第一,可以不进行数据绑定。不建议只绑定v-model:html,有无法避免的缺陷!!!并且需要注意extendCache可能带来的影响!!!同时,我们在绑定v-model时,推荐使用shallowReactive/shallowRef来缓存json数组数据。如果你硬要用reactive/ref做数据缓存,那么运行时出现未知错误,那你可能就找不到问题了。重要!重要!重要!!!!3.总结一下这个封装组件给我最大的感受就是:程也响应式API,bug也来自响应式API。因此,如果你也在使用第三方库,而这些库使用的是响应式数据,你必须合理地使用toRaw、markRaw、shallowReactive、shallowReadonly、unref、shallowRef这些API来释放数据的响应性。否则,运行时错误不是那么容易修复的。对于响应式特性导致的runtimebug,wangEditor官方(issues:262)的解决方案是对数据进行深度克隆。虽然算不上优雅,但效果格外好用,够简单。当然,只要按照本组件中的文档进行操作,就不必考虑相关问题。4.最后,由于这个原因,目前没有发布npm包。如有必要,您可以从GitHub上获取(只有一个文件)。如果觉得好用,不妨给个star吧。

猜你喜欢