摘要: 2019 年最火的前端框架当属 vue.js 了, 很多使用过 vue 的程序员这样评价它,"vue.js 兼具 angular.js 和 react.js 的优点, 并剔除了它们的缺点". 授予了这么高的评价的 vue.JS, 也是开源世界华人的骄傲, 因为它的作者是位中国人 - 尤雨溪(Evan You). Vue.JS 是一个 JavaScriptMVVM 库, 是一套构建用户界面的渐进式框架. 它是以数据驱动和组件化的思想构建的, 采用自底向上增量开发的设计. 相比于 Angular.JS,Vue.JS 提供了更加简洁, 更易于理解的 API, 使得我们能够快速地上手并使用 Vue.JS; 同时比起 React + Redux 相对复杂的架构,
调试插件
在 vue 调试方面, 可以选择安装 Chrome 插件 vue Devtools. 打开 vue 项目, 在 console 控制台选择 vue 面板. 在 Devtools 工具中, 可以选择组件, 查看对应组件内的数据信息. 也可以选择 Vuex 选项, 查看该项目内 Vuex 的状态变量信息.
UI 组件库
在 vue 组件库方面, 个人不推荐使用 UI 组件库, 毕竟自己造轮子的过程还是很有成就感的. 当然, 如果更重视开发效率, 并且选择了 vue2.0 作为前端框架, 那么饿了么推出的 Element 组件就是一个很不错的选择. 其 GitHub 项目 (https://github.com/ElemeFE/element) 更新比较频繁, 虽然项目会有些不稳定, 但是目前为止 element 就是最好的支持 vue2.0 的 UI 组件. 就像它的口号一样,"快速成型, 就为让你少加班".
vue,React,Angular1 对比
性能 对比
在 Angular1 中, 在 scope 作用域中每一次数据变化, 会触发 watcher 的重新计算, angular 对常用的 dom 事件, xhr 事件等做了封装, 在里面触发进入 angular 的 digest 流程. 在 digest 流程里面, 会从 rootscope 开始遍历, 检查所有的 watcher. 并且, 如果一些 watcher 触发另一个更新, 脏检查循环 (digest cycle) 可能要运行多次. Vue 则没有这个问题, 因为它使用基于依赖追踪的观察系统并且异步队列更新, 数据的变化都是独立处罚的, 除非数据之间有明确的依赖关系.
vue 官方宣称 vue 的渲染性能优于 react. 为了有理有据让人信服, vue 开发团队建立了一个简单的对比性能的项目(https://github.com/chrisvfritz/vue-render-performance-comparisons), 它负责渲染 10000 个列表项 100 次. Vue 官方将每一个参照项目都分别运行 20 次并取最好的结果结果如下图:
由此可见, Vue 的性能是远好于 Angular1, 并且稍微优于 React 的.
社区拓展对比
Angular1 的背后是 Google, 所以社区基础是不需要担心的, 从 Tutorial 到 Stack Overflow 的问题数量都可以反映出生态系统很完整. Angular1 之后的 2.0 版本几乎是一个推翻重做的框架, 对于使用了 1.X 版本的项目, 想要平滑的升级过渡到 2.0 版本应该是非常困难的. 现在 Angular2 的线上应用数量还不算太多, 主流编码还是以 1.X 版本居多. 这个版本化巨大的差异也间接影响到了开发者对于 angular 的信心.
Vue 和 React 都有强大的社区支持. React 有状态管理库 Flux,ReduxVue, 相应的, Vue 有 vuex.Vue 和 React 都提供了强大的路由库来应对大型应用. 然而 Vue 的路由库和状态管理库都是由官方维护支持的. React 则是选择把这些问题交给社区维护, 因此创建了一个更分散的生态系统. 但相对的, React 的生态系统相比 Vue 更加繁荣. 此外, Vue 提供了 Vue-cli 脚手架, 包括了 webpack,Browserify, 甚至路由库, 能让你非常容易地构建项目.
学习陡峭度对比
在指令与组件方面, Vue 中将指令和组件分得更清晰. 指令只封装 DOM 操作, 而组件代表一个自给自足的独立单元, 有自己的视图和数据逻辑. 在 Angular1 中两者有不少相混的地方. 在 API 与框架设计方面, angular1 都比 vue 要复杂的多. 就个人感觉而言, angular1 和 React 的学习曲线会相对陡峭一些, 而 vue 的编码方式会更趋近于前端开发者的编程习惯.
因为 vue 的作者是中国人, vue 的官方网站, 教程和 API 肯定是最完善, 最易懂的. 此外, 每次大版本的发布, 都会伴随着详尽的迁移说明文档, 包含了很多详尽的阐述以及许多迁移的例子, 甚至还有迁移工具. Angular 的开发团队你们就不觉得脸红么...
Vue 的使用非常的简单, 创建一个本地的 .html 文件, 然后通过如下方式引入 Vue:
这样就生成了 vue 的 hello world 应用.
渲染能力对比
ReactNative 能使你用相同的组件模型编写有本地渲染能力的 App(iOS 和 Android). 能同时跨多平台开发, 对开发者是非常棒的. 为了弥补这方面的不足, 在 2016 年 9 月举办的 JSConf2016 期间, vue.JS 的作者尤雨溪宣布加盟 Weex 团队担任技术顾问, 双方将进行更紧密的合作, 共建开发生态圈. Weex 是阿里的跨平台用户界面开发框架, Weex 的 JavaScript 框架运行时用的就是 Vue. 在此之后, 在 Weex 的帮助下, 使用 Vue 语法开发的组件不仅仅可以运行在浏览器端, 还能被用于开发 iOS 和 Android 上的原生应用.
Vue.JS 的作者尤雨溪表示:"Weex 选择 Vue 作为其 JavaScript 运行时框架是让我非常高兴的一件事. Vue 的组件开发模式已经被 web 开发者社区广泛 认可, 而把 Vue 的开发体验拓展到原生平台则是我一直想做但没有余力去做的事情. 一想到 Weex 将能让开发者们用 Vue 的语法去写跨 Web/Android/iOS 三端的通用组件, 就让我很兴奋."
vue 的缺点
Vue 就这么好, 难道没有缺点吗? 当然有, vue 虽然在 16 年非常火爆, 但是相比于 angular 和 react, 不论是成熟度还是社区活跃度都还不是对手. 此外, Vue 明确声明了自己放弃了对 IE8 的支持. 再看看现在的招聘网站上, 有多少写了需要有 angular 经验, 而又有多少写了需要 vue 经验, 就可见 vue 的影响力相比于 angular 和 react 还差的很远.
vue 全家桶及项目架构
Vue 有著名的全家桶系列, 包含了 vue-router(http://router.vuejs.org),vuex(http://vuex.vuejs.org), vue-resource(https://github.com/pagekit/vue-resource). 再加上构建工具 vue-cli, 就是一个完整的 vue 项目的核心构成.
vue-router 路由
推荐使用 NPM 工具来安装 vue-router
NPM install vue-router
通过 import 导入并定义 Vue 模块, vue-router 模块和需要使用的组件, 在本例中, 分别是 Goods,Ratings 和 Seller 组件. 最后, 如果在一个模块化工程中使用它, 必须要通过 Vue.use() 明确地安装路由功能.
- import Vue from'vue'
- importRouter from'vue-router'
- import Goods from '@/components/goods/goods';
- import Ratings from '@/components/ratings/ratings';
- import Seller from '@/components/seller/seller';
- Vue.use(Router); // 需要 import Vue 和 Router, 不然会报错 undefined
通过 const router= new VueRouter()来定义一个路由, 并传入对应的配置, 包括路径 path 和组件 components.
最后, 在使用 newVue 来创建和挂载 vue 根实例的时候, 记得要通过 router 配置参数注入路由, 即在 router 中 export 出来的路由对象, 从而让整个应用都有路由功能.
vuex 状态管理
Vuex 是一个专为 Vue.JS 应用程序开发的状态管理模式. 它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化. 如前面所提到的, Vuex 已经集成到 Vue 的官方调试工具 vue Devtools, 可以轻松的查看项目中的 Vuex 状态变化情况.
假设有这样一个场景: 我们的项目规模比较大, 有多个父组件, 每个父组件同时又包含多个子组件. 如何保持对所有时间的追踪将变得很困难. 到底哪个事件是哪个组件派发的, 哪个组件该监听哪个事件? 父组件将变得和子组件耦合越来越严重, 因为它需要明确的派发和监听子组件的某些事件. 项目逻辑分散在各个组件当中, 很容易导致逻辑的混乱, 不利于我们项目的维护.
这就是 Vuex 用来解决的问题. Vuex 的四个核心概念分别是:
The state tree:Vuex 使用单一状态树, 用一个对象就包含了全部的应用层级状态. 至此它便作为一个『唯一数据源(SSOT)』而存在. 这也意味着, 每个应用将仅仅包含一个 store 实例. 单状态树让我们能够直接地定位任一特定的状态片段, 在调试的过程中也能轻易地取得整个当前应用状态的快照.
Getters: 用来从 store 获取 Vue 组件数据.
Mutators: 事件处理器用来驱动状态的变化.
Actions: 可以给组件使用的函数, 以此用来驱动事件处理器 mutations
Vuex 和简单的全局对象是不同的, 当 Vuex 从 store 中读取状态值的时候, 若状态发生了变化, 那么相应的组件也会高效的更新. 并且, 改变 store 中状态的唯一途径就是提交 commit mutations. 这样便于我们跟踪每一次状态的变化. 只要发生了状态的变化, 一定伴随着 mutation 的提交.
让我们来看一个最简单的 vuex 例子:
安装 Vuex 之后, 让我们来创建一个 store. 创建过程直截了当 -- 仅需要提供一个初始 state 对象和一些 mutations:
现在, 你可以通过 store.state 来获取状态对象, 以及通过 store.commit 方法触发状态变更:
vue-resource 介绍
Vue-resource 有体积小, 支持 IE9 以上的浏览器, 支持 promise 特性的特点. 同样推荐使用 NPM 来安装 Vue-resource.
$ NPM install vue-resource
在安装并引入 vue-resource 后, 可以基于全局的 Vue 对象使用 http, 也可以基于某个 Vue 实例使用 http.
在发送请求后, 使用 then 方法来处理响应结果, then 方法有两个参数, 第一个参数是响应成功时的回调函数, 第二个参数是响应失败时的回调函数.
vue-resource 的请求 API 是按照 REST 风格设计的, 它提供了 7 种请求 API:
- . get(url,[options])
- . head(url,[options])
- . delete(url,[options])
- . JSONP(url,[options])
- . post(url,[body], [options])
- . put(url, [body],[options])
- . patch(url,[body], [options])
vue 工程目录结构
下图是一个简单的 vue 项目的大概结构, 下面简要介绍一下每个文件夹中一般都会存放哪些内容.
components / 文件夹用来存放 Vue 组件. 个人建议, 把每一个组件中使用到的 image 图片放置到对应的组件子文件目录下, 便于统一的管理
Node_modules/NPM 安装的该项目的依赖库
vuex / 文件夹存放的是和 Vuex store 相关的东西(state 对象, actions,mutations)
router / 文件夹存放的是跟 vue-router 相关的路由配置项
build / 文件是 webpack 的打包编译配置文件
static / 文件夹存放一些静态的, 较少变动的 image 或者 CSS 文件
config / 文件夹存放的是一些配置项, 比如服务器访问的端口配置等
dist / 该文件夹一开始是不存在, 在我们的项目经过 build 之后才会产出
App.vue 根组件, 所有的子组件都将在这里被引用
index.HTML 整个项目的入口文件, 将会引用我们的根组件 App.vue
main.JS 入口文件的 JS 逻辑, 在 webpack 打包之后将被注入到 index.HTML 中
vue 中 Less 的应用
在 vue 项目中一样可以使用 Less 预编译, 只是需要使用 NPM 安装 Less-loader 插件. 安装完成后, 在 vue 中的 CSS 模块进行简单的配置, 这样就可以直接使用 Less 来编写样式表了. 在打包编译的时候, 会自动生成对应的 CSS 样式.
vue 合实例讲解 Vue 核心功能
Vue 的功能有很多, 很难一一进行详细的解释. 下面根据在工作中的项目实例, 结合代码解释一下 vue 的几大核心功能.
计算属性
假设有如下的购物车结算场景, 用户选中商品的总金额是根据商品数量, 选中商品种类数
和商品单价来变化的. 然而, 数量, 选中种类数量和单价这几个对象都是根据用户选择而动态变化的, 如果在前端模版中为了计算最终商品总额, 放入这几个动态变化的变量(商品数量, 商品单价, 选中商品种类), 会让这个逻辑变得复杂难以维护. 在这种情况下, 模版便不再简洁清晰. Vue 给出了此种场景的解决方案, 在任何复杂的逻辑, vue 都推荐使用计算属性.
如上图所示, 在 HTML 中, 我们只需要使用 {{totalPrice}} 这个计算属性就可以来表示最终的商品总额. 我们不需要关注这个变量的数值变化, totalPrice 这个变量的逻辑写在对应的 computed 计算属性中.
也许会有疑问, 这个计算属性和定义一个 method 方法不是差不多么? 这两者最大的区别是计算属性是基于它的依赖进行缓存的. 计算属性只有在它的相关依赖发生变化时才会重新计算求值. 在本例中, 只有当选择商品的价格 price 和数量 count 发生变化时, 这个计算属性 totalPrice 才会重新计算新的值. 这就意味着, 只要 totalPrice 这个值没有发生变化, 多次访问该计算属性会立即返回之前的计算结果, 而不必再次执行计算.
模版语法
Vue.JS 使用了基于 HTML 的模版语法, 允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据. 所有 Vue.JS 的模板都是合法的 HTML , 所以能被遵循规范的浏览器和 HTML 解析器解析. Vue 的模版语法包括了使用双大括号插入文本, 使用 v-HTML 插入纯 HTML 内容, 使用 v-bind 插入对象, 类似 angular 的 v-if,v-show,v-for 指令, 以及过滤器等等.
组件化
组件 (Component) 是 Vue.JS 最强大的功能. 组件可以封装可重用的代码, 通过传入对象的不同, 实现组件的复用.
举一个简单的组建例子, 我们首先编写一个 star 组件, 它就是一个普通的 star.vue 文件. 它的作用就是简单实现了一个五角星.
如何在其他的 vue 文件中使用这个 star 组件呢? 如下图所示, 首先通过 import 引入 star 组件对象, 并在想使用 star 组件的 vue 文件中声明注册 star 组件. 现在就可以愉快的通过标签来在该 vue 文件中任意地方使用 star 组件了. 在你想展示一个五角星的地方, 使用一个 star 标签, 就可以轻松完成这个功能.
组件实例的作用域是孤立的. 这意味着不能在子组件的模板内直接引用父组件的数据. 要让子组件使用父组件的数据, 我们需要通过子组件的 props 选项. 如本例所示, 子组件 star 要显式的使用 props 选项声明它期待获得的数据. 在这里就是指的 "size" 和 "score" 两个变量. 我们可以通过父级给子组件 star 传入大小和数值这两个对象, 来实现对子组件的定制化.
过渡效果
Vue 在插入, 更新或者移除 DOM 时, 提供多种不同方式的应用过渡效果, 可以用简单的几行代码实现酷炫的过渡效果. Vue 提供了 transition 的封装组件, 在使用 v-if,v-show 等方法使得 transition 内部 dom 元素发生变化时, 可以给任何元素和组件添加 entering/leaving 过渡.
当 v-show 中内容发生变化时, transition 组件中的元素会发生状态的改变, 在应用了 transition 封装后, Vue 会自动识别目标元素是否应用了 CSS 过渡效果动画, 如果有, 会在合适的时机添加 entering/leaving 的 class 来实现该过渡效果.
下图所示是一个简单的过渡效果的例子, 需要将想实现过渡效果的元素放在 transition 标签中包裹, 通过 name="slide-fade" 来声明过渡效果名称, 并在对应的 vue 文件中添加过渡效果
的 CSS 样式, 这样就可以简单的完成该元素的过渡效果.
总结
根据不完全统计, 包括饿了么, 稀土掘金, 苏宁易购, 美团, 天猫, 荔枝 FM, 房多多, Laravel,htmlBurger 等国内外知名大公司都在使用 vue 进行新项目的开发和旧项目的前端重构工作.
此外, vue + vuex+ vue-resource + vue-router + webpack + es6 + Less 的项目架构成为了越来越多大公司的第一选择.
来源: http://www.jianshu.com/p/1227067e501b