紧接上文,接下来我们要处理布局问题,利用成熟工具最容易实现的布局是 grid 布局,我们将采用此种方式,配合 vue-grid-layout 来完成,首先我们来看看效果:
基本功能实现的差不多了,我们需要改变思维方式,即:
之前是自底向上,从功能角度解决一些复杂的点,现在需要自顶向下解决问题
首先我们需要一个 EJSHandler 组件 和一个 EJSHandlerService 类,这个类我们将依赖注入,其下的所有组件都将可以访问到他们的数据:
加入了一些测试数据
然后,我们创建一个 Layout 组件和相关服务,使用 vue-grid-layout:
相关服务为:
用一个新的 WidgetService, 继承自 Template service (只有一层,不用太过担心):
界面很美好,功能基本都完成
但是有个很恐怖的一点,响应式保持失败了,为什么呢?
一旦点击按钮更新 ejs 的组件,会发现报错,拿不到value
记住这个错误:
Uncaught (in promise) TypeError: Cannot create property 'value' on string/number/data
是的,这就是Vue新版本的重难点 ——
响应式保持
模板中一旦写入了 ref,自然会被 Vue 拆包,一般情况下这个不会影响太大,但是若是第三方库在子组件中进行了模板映射,出现了拆包动作,问题就很难解决了:
我们将一个包含ref的复杂结构传入给了 vue-grid-layout,并不知道他会不会改我们的值,Vue3 目前正式版都还没有发售,第三方库肯定没有响应式保持的意识,因此,将 WidgetService 伙同 layout 数据一股脑传进去是绝对会失败的,即便我这么处理也没有用:
这里我并没有强制更新所有子项,然而还是失败了
html 还是字符串,不是 ref
响应式保持的 bug,修改起来会非常消耗时间,我在优化的同时,也总结了一套解决响应时保持问题的规则,可以与大家共享
将在下一章开个特别篇讨论~