escapar CodingDaydreaming
寒假开发计划:前端的总结
Vue.js, AnguarJS, 前端
## 停不下来的前端 开学后,为了调整心态,长期没有接触作业以外的代码。于是准备在假期进行若干项目的开发,保证习惯不生疏、工具不落后于市场需求。 在为课题图表工具选型的时候看到了[“蚂蚁数据可视化”](https://antv.alipay.com/zh-cn/index.html)需要前端御三家的最新版本,感觉有必要跟进学习一下。(顺带一提,这个工具没有区域选择功能,图表联动手动实现,这些都是BI工具必备的功能。阿里即使有必要再造一个 chart.js ,这点上也有失水准了。) ## Vue.js的亮点 以下内容主观,来自于一个习惯用 AngularJS 开发前端的后端程序员,必然有不严谨的地方。 ### 从 AngularJS 无缝迁移的开发习惯 网上 AngularJS 和 Vue.js 的程序员好像势不两立,但实在的开发人员才是合格的开发人员。 从使用习惯上来说,**Vue.js 的第二版本才更像 Angular2 应有的样子**,这点对不乐意在前端上花费太多学习成本的人来说尤其重要。 ### 清晰的数据流 组件之间的通信一般两个流派,**发布订阅**和**全局状态管理**,还有一个邪道,就是**组件共享作用域**。 新人喜欢共享作用域,感觉这样方便。事实上,程序都是会变大的,组件解耦地不明显会造成麻烦。当有四五个程序维护同一个作用域的时候,完全**搞不清 bug 是哪里产生的**。 所以这个清晰,体现在它**强行规定了组件间的数据流向**,而且冒着失去灵活性风险采用了最佳实践。 父=>子,必须父级在 dom 里用 v-bind 绑定 props ,子组件在 JS 声明接受的 props , props 是 final 的(但需要注意传引用的情况)。 子=>父,必须父级在 dom 里绑定事件,子组件 emit 事件。 子=>子,必须由父级作跳板,如果这种情况很多,或者出现跨路由的通信,就最好用上 Vuex。 ### 简明易懂的生命周期 你可以马上就花两小时搞懂 link、compile 等组件的生命周期,但**一个月后你还能记起来么**?反正我不行。 看看 Vue 的设计,对于复杂的 SPA 还是很有帮助的。 最打动我的是 `mounted + nextTick`组合,它可以保证 **DOM 完全渲染完** 。 ### 其它 **Scoped CSS**:对我来说这个吸引力不够大,但对于一些喜欢组件化的前端开发人员来说,CSS 有作用域是一件方便的事情。 **方法和组件本地数据的清晰声明**:正是[ John Papa 的 AngularJS Style Guide ](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md)试图做到的。 ## Nuxt.js 以前用 Prerender.io 做过服务端渲染的服务,体验不错。不过在线服务不知哪天就会挂,作为 Vue.js 官方的服务端渲染推荐方案之一,这次尝试了一下 Nuxt.js。 没有用 SSR ,因为太麻烦了,对我来说不如用 vaadin 开发顺手。似乎 VueJS 最近也有发布更底层渲染工具的计划,希望有一天可以看到[基于 Nashorn 的 SSR](https://github.com/vuejs/vue/issues/5415)。 因为 Nuxt.js 本质上是一个服务端解决方案,需要另外运行一个服务来处理请求和渲染前端页面,所以我没去仔细看实现原理,八成也是类似的。 ### 限制 Nuxt.js 将 Vue 实例分为了 **Page** 和 Component。 - 异步的请求**只能**在 Page 中指定的 asyncData 中发出,否则**不会在服务端被渲染**。 - 异步请求获取的数据可以自上而下地传到组件中,但组件若创建一个副本且使用副本作为 ViewModel 的数据,它**不会在服务端被渲染**。 - 发请求的库最好是 **axios** ,用 vue-resource 不奏效。 - **vue-auth 的 jwt 方案目前仍然不被支持,据说今后有计划**。 - 这个库的**文档不怎么详细**。 关于文档的问题举个例子,例如 Transition 的 Mode 被默认设置成了 In-out,和官方组件的行为不一致。要取消这个 Mode ,不能在 Option 对象中将它设置为 `null`,而是要写成 `''`。文档里没有对这种反直觉的内容进行说明,这些坑不深入查一下是难以解决的。 ## 遇到的一些小坑 ### 在 Vue.js 中使用 Livere 评论,但有时加载不正常 #### 问题阐述 LiveRe 是目前墙内能用的、体验最好的评论解决方案。但在 Vue.js 的 App 里可能会有重复加载、加载不出的情况。 异步加载的 `iframe` 真是有原罪。 ~~开销大、代码也烂,要不是懒,而且也没什么人来看,我才不会用这种方案。~~ github 上有专门为 Vue.js 优化的 LiveRe 库,指定了一下 `window.refer`、给加载用了个`setTimeout`的 Trick(好像回到了 AngularJS 的各种 jQuery 插件 Wrapper 时代)。 **但那个 vue-livere 库做得还不够**。 #### 解决思路 首先采用 github 的 vue-livere 库。 如果依然遇到问题,请查看**是否使用了 In-Out 或类似模式的 Transition**。在动画进行的几秒间,两个 Route 的 `div` 会同时存在于页面上,这时后一个 `div` 已经开始了异步加载,Livere 的脚本会寻找 `document` 中**第一顺位的 `#lv-container` 元素**,很可惜,它**往往存在于即将退出的那个 div**。 就结果而言,我们看到了请求发出,却发现新页面的 `#lv-container`里空空如也。解决方案就是,**在页面切换的时候,只留下正确的`#lv-container`**。 实现的思路有很多种,哪个都不尽优雅。请注意,动画进行的过程中,**正在退出的组件处在`beforeDestroy` 生命周期之前**,在这里执行移除 div 的逻辑往往已经太晚了。 ### AngularJS:使用组件库的 Dialog 编辑数据表格 List 中的某一项,编辑完后发现顺序错乱 #### 解决思路 不论您是否使用了独立作用域,请查看您是否使用了 `angular.copy` 传递数据。 `ng-repeat` 所维护的列表对象中,每个元素的顺序由 `$index` 决定,**`angular.copy` 会忽略对象中带 `$` 的一切属性**,所以发生了错乱。 ## 结论 **AngularJS 的使用者可以考虑定一个长期过渡到 Vue.js 的计划。** 本人准备适时学习 Vuex 和 Vue.js 常用 Admin Panel 的用法,学习优秀项目的代码风格。 在此之前,如果遇到重要的项目,还是会暂时采用 AngularJS + Angular Material。