title: 窥探Vue.js2.0

date: 2016-09-27 10:22:34

tags: vue

category: 技术总结

窥探Vue.js2.0

令人兴奋的Vue.js 2.0正式版发布了。新的VUE框架有重大的改进,添加了一些新的特性,比如 Virtual-DOM,Server Side Rendering(服务端渲染),支持 JSX/Hyperscript 语法等,并去掉了一些已有的方法。

新的特性

Virtual DOM

虚拟DOM 是一个真正DOM的抽象、轻量级版本。

它主要作用是让你操控虚拟DOM,来代替直接操控真是DOM。之后虚拟DOM和真是DOM比较,把两者差异的部分再渲染到页面上。

这比直接操作DOM的速度要快的多,因为DOM操作是非常耗时的,加入虚拟DOM对比之后减少不必要DOM操作花的时间比进行DOM和虚拟DOM对比的时间要多,所以采用虚拟DOM是更有优势的。更多关于 什么是Virtual Dom?什么是DOM ?

Server Side Rendering

我们知道 JavaScript 除了可以在浏览器上运行,也可以在服务器端运行,比如 Node.js 平台。JavaScript在服务端生成HypetText或者HTML文件发送给客户端的浏览器。

服务器端渲染(SSR)有几个特点:

  1. 服务器端渲染可以让搜索引擎更容易读取页面的meta信息以及其他SEO相关信息,大大增加网站在搜索引擎中的可见度。
  2. 更快的来生成内容和相对比较慢的来进行数据交互。
  3. 首次加载页面的速度加快。客户端渲染的一个缺点是,当用户第一次进入站点,此时浏览器中没有缓存,需要下载代码后在本地渲染,时间较长。而服务器渲染则是,用户在下载的已经是渲染好的页面了,打开速度比本地渲染快。
  4. 服务器端多更多的事情,让客户端做尽量少的事,从而可以照顾(不抛弃)那些手机或电脑性能比较特别差又想上网的用户。

现在已有的后台服务端框架都可以实现如 MeteorExpressSails

JSX (Javascript XML syntax transform)

JSX是使用XML语法编写Javascript的一套解析工具,X代表XML。这不是要由引擎或浏览器中实现,它的目的是通过各种预处理程序(transpilers),将这些标记转换成标准的ECMAScript。实质上也就是说JSX是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码。如:

// Using JSX to express UI components.
let dropdown =
<Dropdown>
A dropdown list
<Menu>
<MenuItem>Do Something</MenuItem>
<MenuItem>Do Something Fun!</MenuItem>
<MenuItem>Do Something Else</MenuItem>
</Menu>
</Dropdown>;
render(dropdown);

Hyperscript

Hyperscript是JavaScript创建超文本(HTML)的语法。客户端、服务器端都支持。

如下代码及其输入

var h = require('hyperscript')
h('h1.fun', {style: {'font-family': 'Comic Sans MS'}}, 'Is Guybrush a French name?')

舍弃和修改的部分

接下来我将用一个实例演示vue这两个版本间的一些不同的地方。主要包括:

  • events
  • .sync 依赖的弃用
  • vm.$set() 方法的弃用
  • component 组件的模板
  • 一些其他的变化

.sync 修饰符

当父子组件传参的时候我们肯能会想到把.sync修饰符用于子组件的prop上,以实现数据的双向绑定。从现在起,props 就只有单项绑定了。如果当一个组件需要修改他作用域外的数据的时候,它只能emit一个事件(vm.$emit(event,[..args])事件)让监听器回调,而不是再依赖于之前的隐士绑定了。

去掉这个修饰符的目的是为了防止子组件在父组件的范围内所引发的副作用。这样,当你阅读一个组件的代码的时候,就更加容易理解它做了什么以及是如何影响其他部分的。

vue 版本的比较

为了尽可能阐述清楚这两版本的差异,我用一个实例来解释吧。比如

这有个用户可以购买宝石的页面,其中有个Vue实例和一个购物车组件。在购物车组件里,用户选择了要购买多少个然后这个购物车组件把这个变化反映给它的父组件。

用vue 1.0.*

用vue1.0.* 的话,要实现这个功能是显而易见的。我们创建一个变量,来存储所选择的数量,我们把它传递给购物车组件,等待选择数量来更改它的值,在父组件上在写一个computed属性来计算总价格。

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.23/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<meta charset="utf-8">
<title>Gem Market</title>
</head>
<body>
<div class="container">
<h1>Gem Market</h1>
<cart :quantity.sync="quantity"></cart>
<hr>
<div>
<h3>You have to pay <strong>{{ gold }}</strong> pieces of gold.</h3>
</div>
</div>
<template id="cart-template">
<h2>How many gems would you like to buy?</h2>
<p>1 emerald costs 100 pieces of gold.</p>
<input v-model="quantity" class="form-control" number>
</template>
</body>
<script type="text/javascript">
Vue.component('cart', {
template: "#cart-template",
props: { quantity : 0 }
});
new Vue({
el: '.container',
data : function () {
return {
quantity: 0
};
},
computed:{
gold: function(){
return this.quantity * 100
}
}
})
</script>
</html>

用vue 2.0

如果切换到vue 2.0,运行上面的代码,我们会得到以下警告。

[Vue warn]: Component template should contain exactly one root element.

为了去掉这个警告我们在 template内部加上一个Div元素。

<template id="cart-template">
<div>
<h2>How many gems would you like to buy?</h2>
<p>1 emerald costs 100 pieces of gold.</p>
<input v-model="gems" class="form-control" number>
</div>
</template>

刷新浏览器,发现这个警告消失。

当我们改变这个变量的时候,我们得到这个警告。

[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: )

这是因为在vue2中,直接修改prop是被视作反模式的。由于在新的渲染机制中,每当父组件重新渲染时,子组件都会被覆盖,所以应该把props看做是不可变对象 [1]

不能更改 quantity prop使其和父组件同步 , 而是让应该这个组件提交个事件给父组件,可以 watch quantity 变量,如果变量发生改变就emit事件,所以这里压根不需要 prop。

由于 vm.$dispatch 和 vm.$broadcast 被弃用了,我们用一个集中式事件集线器触发事件 来实现组件间的通讯。建议阅读 升级提示

因为在Vue实例中已经实现了事件发射器接口emit,实际开发中可以用空的Vue实例作为事件发射器。

让我们看回这个例子,创建一个emitter,重构一下Cart组件。

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的值,都会在控制台上打印出变化前后的值。



然后,就是要更新父Vue的实例来监听,并更新相应的数据。

new Vue({
el: '.container',
data : function () {
return {
quantity: 0
};
},
created: function () {
// store this to use with Vue.set
var temp = this;
bus.$on('quantity-changed', function (quantity) {
// vm.$set deprecated
Vue.set(temp, 'quantity', quantity)
})
},
computed:{
gold: function(){
return this.quantity * 100
}
}
})

注意

  • vm.$set() 被弃用了,所以我们用全局方法 Vm.set()。

    因为不能使用prop去同步,所以我们这样引用购物车组件:

    <cart></cart>

  • ’lazy’ 和 ’number’ 修饰符更改了,所以我们这样修改下 购物车组件里的Input

    // Vue 1

    <input v-model=”quantity” class=”form-control” number>

    // Vue 2

    <input v-model.number=”quantity” class=”form-control”>

好了,这就是所有的了,你可以查看最终代码,然后自己把玩一番吧 JSFiddle

其他资源

下面列出的资源清单强烈建议你去看下:

本文参考


  1. 在面向对象和函数式编程,不可变对象的状态在创建后不能修改 ↩︎

窥探Vue.js 2.0的更多相关文章

  1. 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?

    引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...

  2. Vue.js 2.0 参考手册.CHM下载

    下载地址 Vue.js 2.0 参考手册.CHM下载链接: http://pan.baidu.com/s/1kVbhd4b 密码: wxfh

  3. Vue.js 2.0版

    Vue.js 2.0版升级,更改了好多方法或指令 new Vue({ el:'#demo', data:{ msg:"vue2.0" } }) v-model lazy numbe ...

  4. Vue.js 2.0 和 React、Augular

    Vue.js 2.0 和 React.Augular 引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那 ...

  5. 基于Vue.js 2.0 + Vuex打造微信项目

    一.项目简介 基于Vue + Vuex + Vue-router + Webpack 2.0打造微信界面,实现了微信聊天.搜索.点赞.通讯录(快速导航).个人中心.模拟对话.朋友圈.设置等功能. 二. ...

  6. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  7. flask 与 vue.js 2.0 实现 todo list

    实现了后端与前端分离,后端提供 RESTful api. 后端 flask 与前端 vue 的数据传输都是 json. 本文使用 vue.js 2.0 对前一个例子:flask, SQLAlchemy ...

  8. vue.js 2.0实现的简单分页

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...

  9. 使用 Vue.js 2.0+ Vue-resource 模仿百度搜索框

    使用 Vue.js 2.0 模仿百度搜索框 <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...

随机推荐

  1. TypeScript: Angular 2 的秘密武器(译)

    本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...

  2. Hibernatel框架关联映射

    Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...

  3. [C#] 软硬结合第二篇——酷我音乐盒的逆天玩法

    1.灵感来源: LZ是纯宅男,一天从早上8:00起一直要呆在电脑旁到晚上12:00左右吧~平时也没人来闲聊几句,刷空间暑假也没啥动态,听音乐吧...~有些确实不好听,于是就不得不打断手头的工作去点击下 ...

  4. C# 利用性能计数器监控网络状态

    本例是利用C#中的性能计数器(PerformanceCounter)监控网络的状态.并能够直观的展现出来 涉及到的知识点: PerformanceCounter,表示 Windows NT 性能计数器 ...

  5. node中的cmd规范

    你应该熟悉nodejs模块中的exports对象,你可以用它创建你的模块.例如:(假设这是rocker.js文件) exports.name = function() { console.log('M ...

  6. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  7. RabbitMq应用一的补充(RabbitMQ的应用场景)

    直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...

  8. CSS 3学习——transition 过渡

    以下内容根据官方规范翻译以及自己的理解整理. 1.介绍 这篇文档介绍能够实现隐式过渡的CSS新特性.文档中介绍的CSS新特性描述了CSS属性的值如何在给定的时间内平滑地从一个值变为另一个值. 2.过渡 ...

  9. JAVA 分页工具类及其使用

    Pager.java package pers.kangxu.datautils.common; import java.io.Serializable; import java.util.List; ...

  10. SAP CRM 性能小技巧

    导言 本页面打算收集SAP CRM实施中可以用于避免性能问题的注意事项,重要的事项会由图标标识. 如果你有其他的技巧想要说出来,别犹豫! 性能注意事项 通用 缓存读取类访问,特别是在性能关键的地方,比 ...