当前位置:网站首页>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边栏推荐
- Day 5 script and UI System
- Sampling strategy and decoding strategy based on seq2seq text generation
- What is the file that tp6 automatically executes? What does the tp6 core class library do?
- 打新债安不安全 有风险吗
- Is it safe to open an account online? Xiaobai asks for guidance
- Is it safe to open a stock account online now?
- Summary of NLP data enhancement methods
- Stimulsoft ultimate presents reports and dashboards
- LVS-DR模式单网段案例
- How to calculate the positive and negative ideal solution and the positive and negative ideal distance in TOPSIS method?
猜你喜欢

atguigu----17-生命周期

Home server portal easy gate

微信小程序_7,项目练习,本地生活

A 35 year old Tencent employee was laid off and sighed: a suite in Beijing, with a deposit of more than 7 million, was anxious about unemployment

UEFI: repair efi/gpt bootloader

各种同步学习笔记

GPU calculation

Bluecmsv1.6- code audit

LVS-DR模式多网段案例

Scanpy (VII) spatial data analysis based on scanorama integrated scrna seq
随机推荐
leetcode. 13 --- Roman numeral to integer
【总结】1361- package.json 与 package-lock.json 的关系
Getting to know the generation confrontation network (11) -- using pytoch to build wgan to generate handwritten digits
现在网上开通股票账号安全吗?
How to calculate the information entropy and utility value of entropy method?
What is the difference between TP5 and tp6?
声纹技术(五):声纹分割聚类技术
Summary of NLP data enhancement methods
How to analyze the grey prediction model?
Incluxdb time series database
股票网上开户安全吗?小白求指导
Home server portal easy gate
To achieve good software testing results, it is a prerequisite to build a good testing environment
Measure the current temperature
What are the indicators of entropy weight TOPSIS method?
打新债真的安全吗? 风险大吗
What does openid mean? What does "token" mean?
EasyPlayer流媒体播放器播放HLS视频,起播速度慢的技术优化
声纹技术(二):音频信号处理基础
SwipeRefreshLayout+RecyclerView无法下拉问题排查