在我写这篇文章的时候,我们刚刚从我们的应用程序代码库中删除了最后一行AngularJS代码,结束了一个为期4个月的非侵入性工作,将我们的应用程序从AngularJS迁移到VueJS。在这篇文章中,我将分享我们在整个过程中的经验。

一些背景介绍

我们的应用程序(Holistics.io)是一个基于SQL的商业智能(BI)平台,使用Rails、Sidekiq、PostgreSQL和AngularJS编写。我们的Rails应用程序始于2013年底,作为一个简单的应用程序其中使用了jQuery和AngularJS。我们使用AngularJS主要特性/功能如下:

  • 查看模型绑定(控制器,视图+模板引擎)

  • 依赖注入(服务,工厂,指令)

  • Angular第三方组件(uib-modal,ui-select,...)

其余的都是内部的自定义JavaScript。

Tocy

翻译于 2017/10/19 22:13
 顶

0

 

我们在 Angular 中遇到的问题

随着我们应用的升级,我们在使用 AngularJS 的时候遇到了这样一些问题:

  • 渲染性能:作为数据工具,由于AngularJs的特性,我们不得不花大量的时间来呈现一张巨大的数据表。

  • Angular 的文档不太好:在这成为问题之前,其他都不算什么问题。我们越深入地使用 AngularJS,就越觉得它的文档实在难以理解。

  • 双向数据流使得逻辑处理起来相当困难,不管是写组件还是写视图控制器都是如此。这可能是AngularJS不好使用最重要的一个原因。

考虑不同的框架

在决定之前,我们仔细看看各个选项:

Angular 2

我们确实花了些时间来研究 Angular 2。对于我们来说,Angular 2 甚至比 Angular 1 还让人难以理解。它带来了太多新的变化(TypeScript),新的模板语法等,但我们觉得这并没有真正解决我们的核心问题。除此之外,从 V1 到 V2 的迁移之路在那时就一直让我们觉得困惑。

边城

翻译于 2017/10/19 23:25
 顶

0

 
 

ReactJS

我们仔细审视了 ReactJS。尽管我们非常喜欢它的哲学和生态原理系统,但有一件事情让我们吃惊:我们找不到一条清晰、干净、渐进的迁移路径,来阻止我们在3-4个月内支持新功能。

AngularJS 的使用基于 HTML 的模板系统,而 ReactJS 是用的 JSX。我们不能找到办法在迁移的过程中让两种技术很好的并存。

还有一个次要的主观原因,我发现 JSX 比基于 HTML 的模板更加冗长。

EmberJS

EmberJS 不是一个 JS 库,而是一个 Web 应用框架,我们必须用基于 EmberJS 重写所有东西。

边城

翻译于 2017/10/20 00:06
 顶

0

 
 

我们为什么选择了 VueJS:逐步迁移

综合考虑各方面因素,我们最终选择了 VueJS,但对于我们来说,最重要的决定性因素是:我们看到了一个清晰、可逐步迁移到 VueJS,而又不会破坏发展路径的迁移路径。实际上,我敢打赌,在整个迁移期间,我们的客户都没有注意到什么明显的变化,他们不会知道自己访问的页面中,哪些是 Angular 实现的,哪些是 VueJS 实现的。

Vue 采用了与 ReactJS 相似的技术,基于组件,属性下行事件上行等。它与 AngularJS 在模板引擎方面有着惊人的相似。它就像 AngularJS 和 ReactJS 的优美结合。这让我们觉得完美,因为我们有大量的 AngularJS 模板,而我们的主要问题是 Angular 组件带来的复杂逻辑。

边城

翻译于 2017/10/20 00:16
 顶

2

 
 

实际上多数时候我们需要做的只是将代码中的 ng- 改为 v-,简直太美妙了!

随着深入,我们越发觉得作出了正确的选择,它解决了我们早期遇到的问题:很好的性能,单文件组件,清晰的代码结构,槽,等等。

而且,在迁移的过程中,由于 Vue 结构的方式(单向数据流,基于组件),它迫使我们反思和重构代码,而不是继续写烂代码,这简化了我们的代码逻辑。

我还想说的最后一点,我发现 VueJS 的文档写得非常好,结构也非常清晰。这也是我们选择 VueJS 的另一个主要原因。我第一次使用 Vue 的时候,花了 30 分钟来阅读它的文档,立即觉得必须要试试这个东西。

边城

翻译于 2017/10/20 00:25
 顶

0

 
 

我们是怎么进行逐步迁移的:

下面是我们迁移的简单步骤(注意有些内容与我们运行的 Rails 应用环境有关,如果你没有使用 Rails,可能会有些不同):

1. 把 AngularJS 控制器逻辑转换到 VueJS

在逐步迁移策略中,我们要在引入 VueJS 时尽可能少做改动。因此,我们从标准的 AngularJS 和模板文件开始修改,将 VueJS 引入其中:

  1. // user_edit_controller.js.es6`
  2. import Vue from 'vue'
  3.  
  4. app.controller('UserEditCtrl', ['$scope', '$http', 'Ajax', 'Util', 'Modals',  
  5.   function ($scope, $http, Ajax, Util, Modals) {
  6.     let vapp = new Vue({
  7.       el: '#v-wrapper',
  8.       components: {
  9.           ...
  10.       },
  11.       data: {
  12.       }
  13.     });
  14.   }
  15. ]);
  1. <!-- `users/edit.html.erb` -->
  2.  
  3. <div ng-controller="UserEditCtrl">  
  4.   <div id="v-wrapper">
  5.     <!-- vuejs logic goes here... -->
  6.     <input v-model="username" placeholder="Username" />
  7.     ...
  8.   </div>
  9. </div>

我们在应用中引入了 Vue 的逻辑,却不需要改变任何相关应用的前端结构。这极大程度的帮助我们降低在迁移过程中发生错误的风险,我们可以花 1-2 个小时迅速地将一小部分 AngularJS 实现的东西转换为 VueJS 实现,然后测试并部署,不用担心它会导致回归缺陷

边城

翻译于 2017/10/20 00:34
 顶

1

 
 

2. 把 AngularJS 服务转换为 ES6 模块

我们首先需要找到一个 AngularJS 中大量使用的 $http 服务的替代品。我们直接使用了 axios。我们不再直接使用 $http,但我们围绕它进行了抽象封装,以使修改变得非常简单。

然后,我们像这样定义了大量的 AngularJS:

  1. // users.js
  2. app.service('Users', ['$http', 'Ajax',  
  3.   function ($http, Ajax) {
  4.     this.create = function(user) {
  5.       // ...
  6.     }
  7.   }
  8. ]);

使用 ES6 类语法代替就好:

  1. // users.js.es6
  2. export default class Users {  
  3.   static create(user) {
  4.     // ...
  5.   }
  6. }

如果其它控制器中使用有 Angular 代码在使用这些服务,我们会复制这些服务并使用 ES6 类语法来实现,同时保持原有的 Angular 版本,直到不再有 Angular 代码使用它们为止。这会在短时间内让代码出现重复,但我们只需要小心一点,在代码中多写些注释来关联两个版本。

边城

翻译于 2017/10/20 00:43
 顶

0

 
 

3. 使用 VueJS 组件代替 AngularJS 控制器

完成上述两点之后,一些 AngularJS 控制器可以完全迁移到 VueJS,这和上面的第 2 步相似,我们使用 ES6 语法来代替 app.controller() 定义。不过这次,我们使用 Vue 的单文件组件:

文件:user_edit.vue

  1. <template>  
  2.   <div>
  3.     <!-- vuejs logic goes here... -->
  4.     <input v-model="username" placeholder="Username" />
  5.     ...
  6.   </div>
  7. </template>
  8.  
  9. <script>  
  10. import Users from 'users.js.es6'  
  11. export default {  
  12.   data: {    
  13.   },
  14.   methods: {   
  15.   },
  16.   mounted() {
  17.     // initializing
  18.   }
  19.  
  20. };
  21. </script>

4. 为 Rails 控制器/视图添加安装入口

默认情况下,每个 Rails 页面加载的时候会渲染视图。在上面的 Vue 单文件组件中,我们将 Raisl 视图,users/edit.html.erb 文件,改为:

  1. <div class="v-user-edit">  
  2.   <user-edit></user-edit>
  3. </div>

然后加些代码在页面加载的时候将其安装为正确的 Vue 组件:

  1. import UserEdit from 'user_edit.vue'  
  2. let vueConfig = {  
  3.   el: '.v-user-edit',
  4.   components: {
  5.     UserEdit
  6.   }
  7. };
  8. new Vue(vueConfig);

实际上,上面的代码被抽象成了可复用的函数,在不同的页面中调用。

边城

翻译于 2017/10/20 00:49
 顶

1

 
 

总结

我们在 2017 年九月末完成了框架的迁移,经历了大约 4 个月时间的非侵入性(我们在迁移过程中会继续添加其它新特性)工作。实际上我们并没有把迁移作为最紧急的任务,不管什么时候,只要我们的改动涉及到旧的 Angular 代码,我们会先把它转换成 Vue 实现,然后再进行变更。

迁移完成后,我们收获了:

  • 非常整洁的代码和模块(基于组件的),以及 VueX 和 Vue Store;它们大大提高了编程效率

  • 再没有复杂的逻辑

  • 改善了 UI 性能

这并不是说 Vue 就是最好的,它只是在我们特定的情况下工作良好:Angular 固有的设计本质导致使用 Angular 实现应用很重,而 Vue 为我们很好地填补了这一空白,这一切都是自然而然地逐步迁移实现的。

你怎么想?请在下面的评论中与我们分享。希望了解更多你们遇到的情况!

我们为什么以及是如何从 Angular.js 迁移到 Vue.js?的更多相关文章

  1. 为什么我们从Angular 2迁移到Vue.js(为什么我们没有选择React)

    在Rever(www.reverscore.com),我们刚刚使用Vue.js发布了我们的Web客户端的新版本.经过641次提交和16周的紧张开发,我们非常自豪之前做出的决定.8个月前,我们的前端在使 ...

  2. Vue.js 2 vs Vue.js 3的实现 – 云栖社区

    Vue.js 2 vs Vue.js 3的实现 – 云栖社区 vue.js核心团队已经讨论过将在Vue3实现的变化.虽然API不会改变,但是数据响应机制(译者注:对数据改变的监听和通知)发生了变化.这 ...

  3. 分享Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站

    这是个什么的项目? 使用 Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站. 博客线上地址:www.boblog.com Github地址:https: ...

  4. 浅析angular,react,vue.js jQuery-1

    作者:尚春链接:https://www.zhihu.com/question/38989845/answer/79201080来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...

  5. 浅析angular,react,vue.js jQuery使用区别

    前端越来越混乱了,当然也可以美其名曰:繁荣.当新启动一个前端项目,第一件事就是纠结:使用什么框架,重造什么轮子? PS:大牛留言讨论那么,希望看完此篇,能够给你一个清晰的认识,或者让你更加地纠结和无所 ...

  6. oc 与 js交互之vue.js

    - .vue.js 调用oc的方法并传值 vue.js 组件中调用方法: methods: {     gotoDetail(item){         //此方法需要在移动端实现,这里可以加入判断 ...

  7. Js 框架之Vue .JS学习记录 ① 与Vue 初识

    目录 与 Vue.js 认识 VUE.JS是个啥?有啥好处? Vue 的目标 战前准备  VUE.JS环境 VUE.JS 尝试一下,你就明白 第一步 实例化VUE 对象 第二步VueAPP 调用数据 ...

  8. vue.js devtools-------调试vue.js的开发者插件

    vue.js devtools插件: 作用: 以往我们在进行测试代码的时候,直接在console进行查看,其实这个插件雷同于控制台,只不过在vue里面,将需要查看的数据存放在一个变量里面了~ 效果图: ...

  9. JS框架_(Vue.js)带有星期日期的数字时钟

    百度云盘 传送门 密码:tv1v 数字时钟效果: <!doctype html> <html> <head> <meta charset="utf- ...

随机推荐

  1. win7下docker环境搭建nginx+php-fpm+easyswoole+lavarel+mysql开发环境

    win7环境基础在上一篇win7下docker环境搭建nginx+php-fpm+easyswoole开发环境中已经详细叙述搭建完成 本篇文章将叙述如何在上述基础上搭建laravel开发环境,这个其实 ...

  2. Ionic Js十四:浮动框

    $ionicPopover $ionicPopover 是一个可以浮在app内容上的一个视图框. 实例 HTML 代码 <p> <button ng-click="open ...

  3. eclipse 设置文本模板中 insert variable... 函数 详解

    设置文本模板简要图: 设置文本模板详细过程:http://www.cnblogs.com/lsy131479/p/8478711.html 此处引出设置文本模板中 insert variable... ...

  4. 【Naive Splay Template】

    写小作业的时候重新复习了一下splay 只支持插入,删除,查k大,查节点数.没有迭代器. T类型需要重载==和<,要调用拷贝构造函数. template<class T> class ...

  5. BZOJ 2750 HAOI 2012 Road 高速公路 最短路

    题意: 给出一个有向图,求每条边有多少次作为最短路上的边(任意的起始点). 范围:n <= 1500, m <= 5005 分析: 一个比较容易想到的思路:以每个点作为起点,做一次SPFA ...

  6. PyQt QString 与 Python str&unicode

    昨日,将许久以前做的模拟网页登录脚本用PyQt封装了一下,结果出大问题了, 登录无数次都提示登录失败!!而不用PyQt实现的GUI登录直接脚本登录无数次都提示登录成功!!心中甚是伤痛,于是探究起来,解 ...

  7. Codeforces Round #361 (Div. 2) B. Mike and Shortcuts bfs

    B. Mike and Shortcuts 题目连接: http://www.codeforces.com/contest/689/problem/B Description Recently, Mi ...

  8. Codeforces Beta Round #97 (Div. 1) B. Rectangle and Square 暴力

    B. Rectangle and Square 题目连接: http://codeforces.com/contest/135/problem/B Description Little Petya v ...

  9. ROS知识(13)----基于catkin的包安装

    ROS软件包开发完成后,需要安装包,如果你用的是catkin创建的工作空间,那么即可使用命令"catkin_make install"完成此项任务.下面介绍其安装的过程: 1.源码 ...

  10. 编写简单登陆和注册功能的demo时遇到的问题

    一.注册功能中添加数据不成功 给数据库添加EditText中的内容后,数据库中找不到添加后的数据,并且存在字符串为空的数据 解决方法:EditText registerAccount = (EditT ...