# 一览 Vue.js 2 – dotdev > 本文转载自:[众成翻译](http://www.zcfy.cc) > 译者:[少年阿布DX](http://www.zcfy.cc/@shawndai06) > 链接:[http://www.zcfy.cc/article/2531](http://www.zcfy.cc/article/2531) > 原文:[https://dotdev.co/peeking-into-vue-js-2-part-1-b457e60c88c6#.l282x8har](https://dotdev.co/peeking-into-vue-js-2-part-1-b457e60c88c6#.l282x8har) Vue.js 2 就要来了,我们都对此感到非常激动。Vue 的新版本除了带来了巨大的提升与许多新特性(虚拟 DOM、服务端渲染、JSX / Hyperscript 支持等),也做了一些舍弃与改变。 ## 新特性 所有 Vue 2 带来的这些新特性听起来都很棒。但在实践它们之前,你应该熟悉这些特性到底是什么。 ### 虚拟 DOM 虚拟 DOM 是真实 DOM 的抽象 / 轻量级版本。 它最主要的理念就是不直接操作 DOM,而是操作虚拟 DOM。在与真实 DOM 比较之后,真实 DOM 中需要被改变的部分会被重新渲染。 相对于直接与真实 DOM 打交道来说,这快多了。因为它避免了许多重量级的操作直接发生在真实 DOM 上。 如果你想了解更多关于虚拟 DOM 的内容,我认为你真的需要读下面这篇 [Tony Freed](https://medium.com/@tony_freed) 写的文章。 [什么是虚拟 DOM?](https://medium.com/tony-freed-consulting/what-is-virtual-dom-c0ec6d6a925c) ### 服务端渲染 JavaScript 不仅能在浏览器运行,也能通过使用像 [Node.js](http://nodejs.org/) 的平台跑在服务器上。 通过在服务端运行 JavaScript,你能生成 HyperText 或 HTML 然后直接发送到客户端浏览器。浏览器在渲染模版时会导致短暂的空模版闪现(在看到真实的内容前,你可能先看到一对空的 ’*{{}}*’),服务端渲染通常用来避免这个问题。 服务端渲染通常会造成内容会很快出现,而到可以交互的时间会轻微增长。 SSR(服务端渲染)对 SEO、Facebook 的 meta tag 等也很有用。 此外,人们通常借助 JavaScript 框架如 [Meteor](https://www.meteor.com/)、[Express](http://expressjs.com/)、[Sails](http://sailsjs.org/) 等来使用 SSR 构建 API。 我最喜欢 SSR 的一点就是**服务端做更多的工作,客户端做更少的工作**。对那些使用老旧电脑或不那么强力的手机访问网页的用户来说,这无疑救他们于水火。 ### JSX(类 XML 的语法扩展) JSX 是对 ECMAScript 的类 XML 语法扩展,没有任何新定义的语义。它并不打算被引擎或浏览器实现,它期望被各式预处理器(转译器)用来将这些词元转译成标准的 ECMAScript。 例如: ```jsx // 用 JSX 表示一个组件 let dropdown = A dropdown list(一个下拉列表) Do Something Do Something Fun! Do Something Else ; render(dropdown); ``` JSX 的官网是 [http://facebook.github.io/jsx/](http://facebook.github.io/jsx/)。 ### Hyperscript Hyperscript 被用来在客户端或服务器用 JavaScript 创建 HyperText(译者注:超文本。HTML 全程就是超文本标记语言)。 看下面的例子和它的输出: ```javascript var h = require('hyperscript'); h('h1.fun', {style: {'font-family': 'Comic Sans MS'}}, 'Is Guybrush a French name?'); ``` ![](http://p0.qhimg.com/t017383f8ed228db1d5.png)

带有 “fun” 类的标题

你能在它们的[可交互 Demo 页]()游玩一番。 ## 舍弃与改变 我将搭建一个简单的基于 Vue 2 的 app,并借此来指出两个版本之间的不同(译者注:1.x 和 2)。 我会设计的主要一些点有: * **事件** * 舍弃 **_.sync_** 修饰符 * 舍弃 **_vm.$set()_** 修饰符 * 组建模版包装 ### 再见 .sync 有一个我们我都将会怀念的东西,那就是使用 “**_.sync_**" 实现的在父子组件之间同步数据的能力。从现在开始,props 只会**单向向下传播**。如果一个组件需要修改不在其作用域的数据,它必须触发一个事件,而不是依赖于隐式结合(implicit binding)。 舍弃 **_.sync_** 的目的是为了阻止子组件在父组件作用域中产生副作用。按这种新方式,当你在阅读组件代码时,你会更容易理解它在干什么,会如何影响你的应用的其他部分。 ## Vue 版本对比 ### 使用 Vue 1.0.* 我将实现的场景是关注。有一个用户可以购买宝石的网页,我们有一个 Vue 实例与一个 _Cart_ (译者注:购物车)组件。在 _Cart_ 组件中,用户会选择他想购买的宝石数量,然后这个组件会向其父组件反映这个改变。 使用 Vue.js 1.0.*,实现会很简单。我们会创建一个变量来存储被选择的数量,然后将它传递至会更新它的值的组件,最后返回到父组件。在 Vue 中,我们可能需要可计算属性来计算总价。 ```html ` Gem Market

Gem Market


You have to pay {{ gold }} pieces of gold.

` ```

Vue.js 1.0.*

![](http://p0.qhimg.com/t01de47c4ed6ce1b41e.png) ### 使用 Vue 2 如果我们到 Vue 2,运行上面的代码时,我们会得到下面的警告。 *[Vue warn]: Component template should contain exactly one root element.* (译者注:[Vue 警告]: 组件模板会要包含至少一个根元素) 为了消除这个警告,我们会把组件的模板封装到一个 _'div'_ 元素中。 ```html ```

根元素

再刷新浏览器时,我们会看到警告会消失。 当我们试图改变 quantity 时会得到警告是: *[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “gems” (found in component: < cart>)* (译者注:[Vue 警告]:避免直接改变一个 prop,因为它的值会在父组件重新渲染时被重写。然而,使用基于 prop 值的 data 或可计算属性时。Prop 被改变了:“gems”(组件:< cart>) 这是因为 Vue 2 中局部改变一个 prop 会被当成是 **反模式**。因为新的渲染机制,无论何时父组件重新渲染,自组件的本地改变都会被重写。现在你应该**把 props 当成不可变(immutable)的**。 > 在面向对象与函数式编程中,不可变对象是指在创建后它的状态不能被改变的对象。 所以不要直接更新 quantity prop 而是与它的父组件同步,我们会让我们的组件提交一个事件到父组件。当然,它也需要监听 quantity 的改变,然后在它发生时用新的值触发事件。我们甚至不需要 prop。 由于 '**_vm.$dispatch_**' 和 `**_vm.$broadcast_**' 已经被舍弃,为了触发一个事件,我们将使用一个集中式事件中心让组件之间可以通讯,正如[升级贴士](https://github.com/vuejs/vue/issues/2873#upgrade-tips)中建议的那样。 由于 Vue 实例实现了 event emitter 接口,实际上我们可以使用一个空的 Vue 实例来作为我们的事件触发器。 回到例子,创建事件触发器并重构 _Cart_ 组件。 ```javascript let bus = new Vue() Vue.component('cart', { template: "#cart-template", data () { return {quantity : 0 } }, watch: { 'quantity': function (quantity, oldQuantity) { console.log('quantity changed from %s to %s', oldQuantity, quantity) bus.$emit('quantity-changed', quantity) } } }); ``` 如果你看控制台,你会注意到每次你改变 quantity 的值时,你都能看到它当前与之前的值。 ![](http://p0.qhimg.com/t010af8673a023d2534.png)

浏览器控制台输出

还剩最后一件事,修改父组件 Vue 实例,监听并更新 quantity 数据。为此我们可以在 _created hook_(译者注:钩子)里建立事件监听器。 ```javascript new Vue({ el: '.container', data : function () { return { quantity: 0 }; }, created: function () { // 使用 Vue.set 存储 var temp = this; bus.$on('quantity-changed', function (quantity) { // vm.$set 已舍弃 Vue.set(temp, 'quantity', quantity) }) }, computed:{ gold: function(){ return this.quantity * 100 } } }) ``` **注意 1:'vm.$set()'** 已经被舍弃,所以我们得使用全局的 '**Vue.set()**' 方法。 由于我们不再需要一个属性来同步两个 quantities,所以我们可以像这样引用 Cart 组件: ```html ``` **注意 2:** '**_lazy_**' 与 '**_number_**' 参数现在是装饰器了,所以我们不得不更新 Cart 的 input 标签: ```html // Vue 1 // Vue 2 ``` **这就行了!**你可以在 [JSFiddle](https://jsfiddle.net/hootlex/hvv2r8ae/) 看到最终的代码并畅玩一番。 ## 有用的资源 下面是我建议你看看的资源列表。 * [Vue 2 官方声明](https://vuejs.org/2016/04/27/announcing-2.0/) * [Vue 2 直播](https://www.youtube.com/watch?v=c9esL3I4IGM) 来自于 [Evan You](https://twitter.com/youyuxi),介绍了一些新特性与舍弃。 * [Vue 2 特性](https://github.com/vuejs/vue/issues/2873) 文档展示了所有的新特性、舍弃和其他的改变。它会由 Vue 团队**持续更新**。 ## 书的更新 因为每个人都在问我的书是否会更新,跟上 Vue 2 的改变,答案是**是!**一旦 Vue 2 稳定了,我们计划更新大部分书中的实例,展示如何使用 **Vue 两个版本** 来构建它们!。
![](http://p0.qhimg.com/t01a43a63183ca8b131.png)

如果你还没读过,快到 LeanPub 看一看!

## 发信给我 欢迎对本篇教程的反馈和问题或任何其他的东西。你也能在[推特上关注我](https://twitter.com/hootlex),来获悉更多关于 Vue.js 与 Laravel 的更新。