Vue 2.x 响应式原理(一)

发布时间:2022-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Vue 2.x 响应式原理(一)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

前期准备工作

  1. 数据驱动
  2. 响应式的核心原理
  3. 发布订阅者模式和观察者模式

数据驱动

  • 数据响应式
    • 数据模型仅仅是普通的 JavaScript 对象,而当我们修改数据时,视图会进行更新,避免了繁琐的 DOM 操作,提高开发效率
  • 双向绑定
    • 数据改变,视图改变;视图改变,数据也随之改变
    • 我们可以使用 v-model 在表单元素上创建双向数据绑定
  • 数据驱动是 Vue 最独特的特性之一
    • 开发过程仅需要关注数据本身,不需要关心数据是如何渲染到视图

Vue 2.x 简单响应式例子

主要是利用 ES5 Object.definePRoPErty,看代码

// 模拟 Vue 中的 data 选项
let data = { msg: 'hello' }

// 模拟 Vue 的实例
let vm = {}

// 数据劫持:当访问或者设置 vm 中的成员的时候,做一些干预操作

Object.defineProperty(vm, 'msg', {
	// 可枚举(可遍历)
	enumerable: true,
	// 可配置(可以使用 delete 删除,可以通过 defineProperty 重新定义)
	configurable: true,
	// 当获取值的时候执行
	get() {
		console.LOG('get: ', data.msg)
		return data.msg
	},
	// 当设置值的时候执行
	set(newValue) {
		console.log('set: ', newValue)
		if (newValue === data.msg) {
			return
		}
		data.msg = newValue
		// 数据更改,更新 DOM 的值
		document.querySelector('#app').textContent = data.msg
	}
})

肯定会有多个属性,所以只需要循环遍历一下 key

// 模拟 Vue 中的 data 选项
let data = { msg: 'hello', name: 'zhang' }

// 模拟 Vue 的实例
let vm = {}

ProxyData(data)

function proxyData(data) {
	// 遍历 data 对象中的所有属性
	Object.keys(data).foreach((key) => {
		// 把 data 中的属性,转换成 vm 的 setter/setter
		Object.defineProperty(vm, key, {
			enumerable: true,
			configurable: true,
			get() {
				console.log('get: ', key, data[key])
				return data[key]
			},
			set(newValue) {
				console.log('set: ', newValue)
				if (newValue === data[key]) {
					return
				}
				data[key] = newValue
				// 数据更改,更新 DOM 的值
				document.querySelector('#app').textContent = data[key]
			}
		})
	})
}

Vue 3.x 简单响应式例子

主要是 ES6 Proxy,直接监听对象,而非属性

// 模拟 Vue 中的 data 选项
let data = { msg: 'hello', count: 0 }
// 模拟 Vue 实例
let vm = new Proxy(data, {
	// 当访问 vm 的成员会执行
	get(target, key) {
		console.log('get, key: ', key, target[key])
		return target[key]
	},
	// 当设置 vm 的成员会执行
	set(target, key, newValue) {
		console.log('set, key: ', key, newValue)
		if (target[key] === newValue) return
		target[key] = newValue
		document.querySelector('#app').textContent = target[key]
	}
})

发布/订阅模式

主要是发布者、订阅者、消息中心

class EventEmITter {
	constructor() {
		// { eventType: [ handler1, handler2 ] }
		this.subs = {}
	}
	// 订阅通知
	$on(eventType, handler) {
		this.subs[eventType] = this.subs[eventType] || []
		this.subs[eventType].push(handler)
	}
	// 发布通知
	$emit(eventType) {
		if (this.subs[eventType]) {
			this.subs[eventType].forEach((handler) => {
				handler()
			})
		}
	}
}
// 测试
VAR bus = new EventEmitter()

// 注册事件
bus.$on('click', function () {
	console.log('click')
})
bus.$on('click', function () {
	console.log('click1')
})

// 触发事件
bus.$emit('click')

观察者

  • 观察者(订阅者) -- watcher
    • update(): 当事件发生时,具体要做的事
  • 目标(发布者) -- Dep
    • subs 数组:存储所有的观察者
    • addSub():添加观察者
    • notify():当事件发生,调用所有观察者的 update() 方法
// 发布者-目标
class Dep {
    constructor () {
        // 记录所有的订阅者
        this.subs = []
    }
    // 添加订阅者
    addSub (sub) {
        if(sub && sub.update) {
            this.subs.push(sub)
        }
    }
    // 发布通知
    notify () {
        this.subs.forEach(sub => {
            sub.update()
        })
    }
}
// 订阅者-观察者
class Watcher {
    update () {
        console.log('update')
    }
}

// 测试
let dep = new Dep()
let watcher = new Watcher()

dep.addSub(watcher)
dep.notify()

脚本宝典总结

以上是脚本宝典为你收集整理的Vue 2.x 响应式原理(一)全部内容,希望文章能够帮你解决Vue 2.x 响应式原理(一)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。