Vue.js
数据驱动 + 组件化的前端界面开发
@尤小右
@yyx990803
vuejs.org
Vue.js 概况
Vue.js 不是一个框架
路由
视图管理
数据持久化
路由
视图管理
数据持久化
灵活的接口
简单示例
Quick Demo
核心思想:
数据驱动
Data-Driven
视图
View
用户行为
User Input
数据模型
Model
渲染
Render
视图
View
用户行为
User Input
数据模型
Model
渲染
Render
视图只是数据的映射
“真相只有一个”
DOM
DOM 在单页 Web 应用中的问题�
View
ViewModel
Model
通过 MVVM 的数据绑定实现自动同步
DOM
POJO
(原生JS对象)
Vue
View
ViewModel
Model
通过 MVVM 的数据绑定实现自动同步
var vm = new Vue({� el: '#demo',� data: {� msg: 'Hello Vue.js!'� }�})
<div id="demo">� <h1>{{msg}}</h1>�</div>
JavaScript
HTML
var vm = new Vue({� el: '#demo',� data: {� msg: 'Hello Vue.js!'� }�})
<div id="demo">� <h1>{{msg}}</h1>�</div>
JavaScript
指令 Directive
(插值其实被编译为 v-text 指令)
ViewModel
Model
View
HTML
View
Model
DOM Listeners
Directives
ViewModel
应用逻辑全部是数据操作
DOM 操作封装在指令中
组件化
Component-Oriented
每一个应用界面都可以
看作是组件构成的
Nav
Content
Item
Sidebar
Side
Item
每一个组件都可以看做是一个
ViewModel
Nav
Content
Item
Sidebar
所以可以把界面抽象为
ViewModel Tree
在 Vue.js 中注册组件
// 扩展 Vue 来自定义一个可复用的组件类
var MyComponent = Vue.extend({
template: '<p>{{msg}}</p>',
paramAttributes: ['msg']
})
// 全局注册该组件
Vue.component('my-component', MyComponent)
在 Vue.js 模板中使用组件
<my-component msg="Hello!"></my-component>
my-component 组件的模板将会被填充到该元素中,而 msg 则会被作为数据传入该组件实例。渲染结果如下。
<my-component>
<p>Hello!</p>�</my-component>
通过 paramAttributes
实现父子组件之间的数据传递
<my-component msg="{{msgFromParent}}"></my-component>
root
my-component
msgFromParent
msg
双向绑定
每一个组件都默认有自己的独立作用域。
组件之间也可以通过
事件系统进行通信
$dispatch()
组件之间也可以通过
事件系统进行通信
$broadcast()
一些实现细节
基于 ES5 Object.defineProperty
实现对 POJO (原生JS对象)的观察和依赖收集
Object
setter
getter
Property
收集依赖
触发更新
a
setter
getter
b
Watcher
a.b
收集依赖
Directive
v-text="a.b"
DOM
{{a.b}}
通知
更新
通知
依赖收集机制的实现类似 Knockout,精确到每一个属性,比脏检测效率得多,性能不受制于 watcher 的数量。
vm.msg = 'one'�vm.msg = 'two'�vm.msg = 'three'�// 只会触发一次 DOM 更新
异步批量更新
var vm = new Vue({� data: {� nested: {� a: {� b: 'hi!'� }� }� }�})
可以直接替换多层嵌套的对象
// 直接替换对象�vm.nested = {� a: {� b: 'yo!'� }�}
var data = {� msg: 'hi'�}
�var vm = new Vue({� data: data�})
可以直接修改原数据对象
// 直接修改原对象�data.msg = 'changed'�// DOM 会在下一帧更新
var items = [a, b, c]�var vm = new Vue({� data: {� items: items� }�})�// 下一帧会触发更新�items.reverse()
数组的 mutating 方法会触发更新
对于直接的数组替换,
v-repeat 会进行 Array-diffing
确保尽可能地复用 vm 和 DOM 元素
// 不会导致性能问题哟
vm.items = vm.items.filter(fn)
* 即使用含有全新数据对象的数组替换,只要对象有 uid 也可以通过比较 uid 来达成有效复用。
// 如果 data 上不存在 prop 属性,
// 则必须要用 $set 或 $add 才会触发更新
data.$set('prop', value)�data.$add('prop', value)
// 删除属性要用 $delete�data.$delete('prop')��// 数组不能用 arr[0] = value, 要用 $set�arr.$set(0, value)
ES5 的局限:
不能侦测对象属性的添加/删除
优势和使用场景
侵入性低
不对整体架构做过多约束,方便与其他库或是已有的前端技术栈整合。
数据持久层
Data Persistence
Layer
服务器端
数据库
Database
View
View
Model
Model
以 POJO 作为 Model 使得 Vue 对于
数据持久层的接口非常灵活
鼓励模块化
基于组件的开发模式有利于将界面代码
自然分割成更容易维护的模块
基于 CommonJS 的单文件组件:Vueify
通过 Browserify 或者 Webpack 这样的模块构建工具,将一个组件的模板、CSS 和 JS 都写在同一个文件里。
轻量 + 高性能
~18kb min+gzip,无外部依赖
不依赖脏检测的高效数据绑定
Thanks
@尤小右
@yyx990803
vuejs.org