核心API - Object.defineProperty
Proxy(Vue3.0 处理响应式), 兼容性不好, 且无法polyfill

Object.defineProperty基本用法

  1. let data = {}
  2. let name = 'jack'
  3. Object.defineProperty(data, 'name', {
  4. get: function () {
  5. console.log('get')
  6. return name
  7. },
  8. set: function (newName) {
  9. console.log('set', name, newName)
  10. name = newName
  11. }
  12. })
  13. console.log(data.name)
  14. data.name = 'Mary'
  15. console.log(data.name)

Object.defineProperty实现监听式

  • 监听对象, 借助 for..in 对各属性重新defineProperty并监听。
  • 深度监听, defineReactive中调用observe(val), 实现递归(监听)
  • 监听数组,拦截数组,重写原型,添加监听。借助Object.create, 重写目的在于防止全局数组方法被污染。 ``` if (Array.isArray(target)) {
    1. target.__proto__ = defineArrayProperty()
    } function defineArrayProperty () { const oldArrayProperty = Array.prototype; const arrayProto = Object.create(Array.prototype) const methods = [‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’]; methods.forEach((methodName) => {
    1. arrayProto[methodName] = function() {
    2. updateView()
    3. oldArrayProperty[methodName].call(this, ...arguments)
    4. }
    }) return arrayProto }
  1. 附录(实现):

function defineReactive(target, key, value) {// 重新定义属性,监听起来 observer(value) // 深度监听 Object.defineProperty(target, key, { // 核心 API get() { return value }, set(newValue) { if (newValue !== value) { observer(newValue) // 深度监听 value = newValue // 设置新值,注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值 updateView() } } }) }

function observer(target) { // 监听对象属性 if (typeof target !== ‘object’ || target === null) { return target // 不是对象或数组 } if (Array.isArray(target)) { // 防止污染全局的 Array 原型 target.proto = defineArrayProperty() } for (let key in target) { // 重新定义各个属性(for in 也可以遍历数组) defineReactive(target, key, target[key]) } } ``` 考点: 组件data的数据一旦变化, 立刻触发视图更新。实现数据驱动视图的第一步是什么?