第一传送门:https://ssshooter.com/2021-03...拆分组件我也以为拆分子组件是为了抽象,但是实践告诉我拆分子组件是提高性能的一种方式(具体情况)。我在实际工作中遇到过这样的问题。有一个带有用于多个新条目的对话框的大表单。当数据较多时,填写新的数据会换卡。原因是,在一个组件中,修改一个值会引起整个组件的数据校验和diff。但是明知道大表上什么都没有改变,我又何必浪费时间去检查呢?为了解决这个问题,单独提取对话框是一种非常有效的优化方法。子组件更新时,默认不会触发父组件的更新,除非子组件改变了父组件的数据。我以elementUI的dialog为例:打开这个链接直接打开runnableexample写一个页面,里面包含两个dialog,一个直接写到页面,一个抽象成组件。点击打开对话框点击打开Dialog2{{renderAfter()}}
取消确定 下面是对话框组件的内容:取消确定从实践中可以看出,当对话框打开和关闭,输入框修改数据时,整个组件的渲染函数都会被触发,而无论dialog2是打开关闭还是进入,都不会触发父组件的更新。如果dialog所在组件的数据量小,差别不大,但当数据量大时,进入dialog时会有明显的滞后感。(一句话:对话框本身就是一个组件,内部更新不影响父组件)不仅如此,另一方面,父组件更新时,会渲染dialog1,不会渲染dialog2,这真是一箭双雕。(一句话:父组件更新时,没有数据变化的子组件没有变化。)即使不重用这个组件,也可以将对话框中使用的方法分离到一个单独的文件中,而不用将它们与方法混在一起的主页。如果一个对话框有很多逻辑,那么将它分离到一个单独的文件中绝对是一个好方法。但是当然也有缺点:一是数据交互有点不方便,不过总能用$parent和Vuex解决。第二个问题是“dialogData”道具的意外突变。(vue/no-mutating-props)修改dialogData.visible时会报错。作为Vue的最佳实践,父母给孩子的道具一定不能被孩子直接修改。我的观点是,如果您知道自己在做什么并且副作用不是太强……可能不会造成伤害,你们怎么看?如果你坚持最佳实践,有两个选项:emit、useon和emithonestly,还有几行代码:所以写等于:然后传递这个子组件中的.$emit('update:title',newTitle)更新父组件。$refs的可见性由dialog本身控制,而dialog的可见性是通过父组件中的refs设置的:this.$refs.child.visible=true反之亦然?也可以修改child中的parent(这不算修改prop,小技巧)this.$parent.visible=true关于更新粒度更详细的解释可以看这里:VueandReacthavedifferentupdategranularity对于组件有什么区别?PS:还有一个隐藏的结论。如果一个组件使用了一个插槽,子组件将与父组件一起重新渲染。Computed是官方文档强调的。可以说众所周知,computed可以缓存计算结果,依赖值不变的情况下减少计算时间。同样众所周知的是KeepAlive组件。减少重组件和插件的使用很多UI框架是完美的,但是因为太完美了,各种功能的交互可能会让你运行太慢或者调试不好。直接修改原来的框架当然是可以的,但是理解成本不低,而且修改之后,更新后合并代码就更难受了,所以还是宁愿自己做一个。我不想成为一个适用于全世界的轮子。因为每个人的需求不一样,如果想要做一个满足每个人要求的轮子,轮子会变得很重,我个人也不愿意看到……所以希望做一个“轮子轻”framework”,满足最低功能需求,让大家轻松修改,同时也不用担心持续更新越来越重。例如v-vld和[tbl]。(https://github.com/v-cpn/cpn-tbl)单向绑定甚至完全不绑定MDNObject.defineProperty()单向绑定是指数据使用defineProperty设置configurable为false,所以即data对应的defineReactive会跳过响应式设置:Object.defineProperty(data,key,{configurable:false,})但是仍然可以通过v-model给绑定目标赋值,只是界面不会任务完成后更新。这种方式适用于数据嵌套较深的情况,阻塞defineReactive后不会对数据中的子对象进行递归处理。(数据扁平化也可以避免递归。)完全不绑定就是官网写了Object.freeze一个对象,然后赋值。这样就不能直接改变对象的内部值(第一层),可以应用于纯显示的数据。缓存的ajax数据可以像普通的axiosget一样进行封装,直接替换原来的axios对象:env.VUE_APP_BASEURLletajax=axios.create({baseURL,withCredentials:true,})letajaxCache={}ajaxCache.get=(...params)=>{leturl=params[0]letoption=params[1]让id=baseURL+url+(option?JSON.stringify(option.params):'')if(sessionStorage[id]){returnPromise.resolve(JSON.parse(sessionStorage[id]))}returnajax.get(...params)}ajax.interceptors.response.use(function(response){//其他处理//...if(response.data.code==='20000'){letparams=response.config.paramsletid=response.config.url+(params?JSON.stringify(params):'')sessionStorage[id]=JSON.stringify(response.data.data)returnresponse.data.data}},function(错误){Message.error('Connectiontimeout')returnPromise.reject(error)})exportdefaultajaxCache功能组件