当前位置:网站首页>Object.defineProperty也能监听数组变化?
Object.defineProperty也能监听数组变化?
2022-06-25 07:44:00 【InfoQ】
本文简介
Object.definePropertyVue2Object.definePropertyObject.definePropertyVue2基础用法
Object.defineProperty()语法
Object.defineProperty(obj, prop, descriptor)
obj要定义属性的对象。
prop要定义或修改的属性的名称或Symbol。
descriptor要定义或修改的属性描述符。
const data = {}
let name = '雷猴'
Object.defineProperty(data, 'name', {
get() {
console.log('get')
return name
},
set(newVal) {
console.log('set')
name = newVal
}
})
console.log(data.name)
data.name = '鲨鱼辣椒'
console.log(data.name)
console.log(name)
get
雷猴
set
鲨鱼辣椒
鲨鱼辣椒
data.namenamenamedata.namenameconst data = {}
Object.defineProperty(data, 'name', {
value: '雷猴',
writable: false
})
data.name = '鲨鱼辣椒'
delete data.name
console.log(data.name)
data.namedata.name雷猴Object.defineProperty深度监听
// 触发更新视图
function updateView() {
console.log('视图更新')
}
// 重新定义属性,监听起来(核心)
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue != value) {
// 深度监听
observer(newValue)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发视图更新
updateView()
}
}
})
}
// 深度监听
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 准备数据
const data = {
name: '雷猴'
}
// 开始监听
observer(data)
// 测试1
data.name = {
lastName: '鲨鱼辣椒'
}
// 测试2
data.name.lastName = '蟑螂恶霸'
updateViewDOMVueObject.definePropertysetobserver(newValue)observerdefineReactive监听数组
key下标- 判断要监听的数据是否为数组
- 是数组的情况,就将数组模拟成一个对象
- 将数组的方法名绑定到新创建的对象中
- 将对应数组原型的方法赋给自定义方法
// 触发更新视图
function updateView() {
console.log('视图更新')
}
// 重新定义数组原型
const oldArrayProperty = Array.prototype
// 创建新对象,原形指向 oldArrayProperty,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function() {
updateView() // 触发视图更新
oldArrayProperty[methodName].call(this, ...arguments)
}
})
// 重新定义属性,监听起来(核心)
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue != value) {
// 深度监听
observer(newValue)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发视图更新
updateView()
}
}
})
}
// 监听对象属性(入口)
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
// 数组的情况
if (Array.isArray(target)) {
target.__proto__ = arrProto
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 准备数据
const data = {
nums: [10, 20, 30]
}
// 监听数据
observer(data)
data.nums.push(4) // 监听数组
Array.prototype.push = function() {
updateView()
...
}
ArrayObject.defineProperty['push', 'pop', 'shift', 'unshift', 'splice']综合代码
// 深度监听
function updateView() {
console.log('视图更新')
}
// 重新定义数组原型
const oldArrayProperty = Array.prototype
// 创建新对象,原形指向 oldArrayProperty,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
// arrProto.push = function () {}
// arrProto.pop = function() {}
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function() {
updateView() // 触发视图更新
oldArrayProperty[methodName].call(this, ...arguments)
}
})
// 重新定义属性,监听起来(核心)
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
// Object.defineProperty 不具备监听数组的能力
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue != value) {
// 深度监听
observer(newValue)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发视图更新
updateView()
}
}
})
}
// 监听对象属性(入口)
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
if (Array.isArray(target)) {
target.__proto__ = arrProto
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
总结
Vue 2缺点
- 深度监听,需要递归到底,一次计算量大
- 无法监听新增属性/删除属性(所以需要使用 Vue.set 和 Vue.delete)
- 无法原生监听数组,需要特殊处理
Vue 3Object.definePropertyProxyProxyVue 2Vue 3边栏推荐
- With the beauty of technology enabled design, vivo cooperates with well-known art institutes to create the "industry university research" plan
- Paper:Generating Hierarchical Explanations on Text Classification via Feature Interaction Detection
- Problems caused by Gil problems and Solutions
- 打新债安不安全 有风险吗
- 浏览器查看当前页面所有的监听事件
- 城鏈科技平臺,正在實現真正意義上的價值互聯網重構!
- 【强化学习笔记】强化学习中的常见符号
- Hyper-v:Hyper-v 第 1 代或第 2 代虚拟机
- Sharepoint:sharepoint server 2013 and adrms Integration Guide
- 对常用I/O模型进行比较说明
猜你喜欢

软件测试月薪10K如何涨到30K,只有自动化测试能做到

Unity addressable batch management

Internet of things (intelligent irrigation system - Android end)

City Chain technology platform, really Realizing value Internet reconstruction!

C language: count the number of characters, numbers and spaces

各种同步学习笔记

Incluxdb time series database

leetcode.13 --- 罗马数字转整数

Various synchronous learning notes

What about the exponential smoothing index?
随机推荐
《树莓派项目实战》第五节 使用Nokia 5110液晶屏显示Hello World
What is the difference between TP5 and tp6?
Is there any risk in the security of new bonds
Is it safe to open a stock account online now?
SwipeRefreshLayout+RecyclerView无法下拉问题排查
How to calculate the fuzzy comprehensive evaluation index? How to calculate the four fuzzy operators?
Exchange:管理日历权限
C language "Recursion Series": recursively realizing the n-th power of X
在二叉树(搜索树)中找到两个节点的最近公共祖先(剑指offer)
Can I grant database tables permission to delete column objects? Why?
leetcode. 13 --- Roman numeral to integer
SharePoint:SharePoint Server 2013 与 ADRMS 集成指南
linux中的mysql有10061错误怎么解决
打新债的安全性 有风险吗
堆栈认知——栈溢出实例(ret2libc)
微信小程序_7,项目练习,本地生活
How to calculate the characteristic vector, weight value, CI value and other indicators in AHP?
声纹技术(二):音频信号处理基础
在哪个平台买股票开户安全?求分享
With the beauty of technology enabled design, vivo cooperates with well-known art institutes to create the "industry university research" plan