相关概念
- 数据驱动
- 数据响应式
数据模型仅仅是普通js
对象,当我们修改数据时,更图会自动更新,避免了繁琐的DOM
操作,提高开发效率。 - 双向绑定
数据改变,视图随之发生改变;视图改变,数据也会发生改变。使用v-model在表单上创建双向绑定。 - 数据驱动
是Vue
最独特的特性之一,开发过程中只需要关注数据,不需要关心数据时如何渲染到视图。
- 数据响应式
- 响应式核心原理
-
Vue2.x
响应式核心原理
当把一个普通的JavaScript
对象传入Vue
实例作为data
选项,Vue
将遍历此对象所有的property
,并使用Object.defineProperty
把这些property
全部转为getter/setter
。Object.defineProperty
是ES5
中一个无法shim
的特性,这也就是Vue
不支持IE8
以及更低版本浏览器的原因。
Object.defineProperty(obj, prop, descriptor)
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。obj
:要定义属性的对象prop
:要定义或修改的属性的名称或Symbol
descriptor
:要定义或修改的属性描述符。- 属性描述符有两种主要形式:数据描述符和存取描述符。一个描述符只能是这两者其中之一;不能同时是两者。
- 两种描述符都是对象。它们共享以下可选键值:
configurable
:键值为true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false
。enumerable
:键值为true
时,该属性才会出现在对象的枚举属性中。默认为false
。
- 数据描述符还具有以下可选键值:
value
:该属性对应的值。可以是任何有效的JavaScript
值(数值,对象,函数等)。默认为undefined
。writable
:键值为true
时,属性的值,也就是上面的value
,才能被赋值运算符改变。默认为false
。
- 存取描述符还具有以下可选键值:
get
:属性的getter
函数,如果没有getter
,则为undefined
。当访问该属性时,会调用此函数。该函数的返回值会被用作属性的值。默认为undefined
。set
:属性的setter
函数,如果没有setter
,则为undefined
。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值)。默认为undefined
。
var data = { msg: 'Hello World' }; var vm = { } Object.defineProperty(vm, 'msg', { configurable: true, // 是否可配置 enumerable: true, // 是否可枚举 set(val) { console.log('set', val); if (val === data.msg) return; data.msg = val; document.querySelector('#app').textContent = data.msg; }, get() { console.log('get', data.msg); return data.msg; } })
-
Vue3.x
响应式核心原理
使用ES6
中新增的Proxy
,能直接监听对象,而不是属性,性能由浏览器优化,比Object.defineProperty
更好,IE
不支持。
Proxy
对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。const p = new Proxy(target, handler)
target
要使用Proxy
包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理p
的行为。是一个容纳一批特定属性的占位符对象。它包含有Proxy
的各个捕获器(trap)
。所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。handler.defineProperty()
:Object.defineProperty
方法的捕捉器。handler.has()
:in
操作符的捕捉器。handler.get()
:属性读取操作的捕捉器。handler.set()
:属性设置操作的捕捉器。handler.deleteProperty()
:delete
操作符的捕捉器。handler.ownKeys()
:Object.getOwnPropertyNames
方法和Object.getOwnPropertySymbols
方法的捕捉器。handler.apply()
:函数调用操作的捕捉器。handler.construct()
:new
操作符的捕捉器。
var data = { msg: 'Hello World' }; const p = new Proxy(data, { get(target, key) { console.log('set', target, key); return target[key] }, set(target, key, val) { console.log('set', target, key, val); if (target[key] === val) reutrn; target[key] = val; document.querySelector('#app').textContent = val } })
-
- 发布订阅模式和观察者模式
-
发布订阅模式
假定存在一个信号中心
,某个任务执行完成时,就像信号中心发布
一个信号,其他任务可以向信号中心订阅
这个信号,从而知道自己什么时候开始执行。
在Vue
中可以简单的认为$.on
注册的事件是订阅者
,而$emit
注册的事件是发布者
。
模拟实现发布订阅模式:- 定义一个类,类中包含一个
$on
和$emit
函数,一个存储$on
定义的事件和回调函数的映射对象subs
,一个事件可能存在多个回调函数。 $on
订阅事件,接收事件名以及一个事件处理函数,然后将事件名和函数存储到subs
中。// 订阅 $on(eventType, handler) { // 将注册的事件和回调函数放到subs对象中 this.subs[eventType] = this.subs[eventType] || []; // 确保事件对应的值是一个数组。 this.subs[eventType
- 定义一个类,类中包含一个
-