Object.defineProperty
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
参数
obj
要定义属性的对象。
prop
要定义或修改的属性的名称 。
descriptor
要定义或修改的属性描述符
-
configurable
当且仅当该属性的 configurable
键值为 true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false
-
enumerable
当且仅当该属性的 enumerable
键值为 true
时,该属性才会出现在对象的枚举属性中。 默认为 false
-
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined
。
-
writable
当且仅当该属性的 writable
键值为 true
时,属性的值,也就是上面的 value
,才能被赋值运算符
(en-US)改变。 默认为 false
。
-
get
当访问该值时会调用此方法,方法需要 return
一个值,默认为 undefined
-
set
当值修改时会调用此方法,方法会传入一个新值。
let value = ''
Object.defineProperty(obj, key, {
configurable: false,
enumerable: true,
writable: true,
value: '1',
get: function () {
console.log(`key: ${key}, value: ${value}`)
return value
},
set: function (val) {
value = val
}
})
发布订阅
let dep = {
clientList: {},
on: (key, fn) => {
if (this.clientList[key]) {
this.clientList[key].push(fn)
} else {
this.clientList[key] = []
this.clientList[key].push(fn)
}
},
emit: () => {
const key = Array.prototype.shift.call(arguments)
const fns = this.clientList[key]
if (!fns || fns.length === 0) {
return false
}
for (let i = 0; i < fns.length; i++) {
const fn = fns[i]
fn.apply(this, arguments)
}
}
}
vm 数据劫持
data
数据对象
tag
发布订阅名称
dataKey
对象属性
selector
元素选择器
valueChange
对象属性变化时触发的函数
on
元素事件
let mv = function ({ data, tag, dataKey, selector, valueChange, on }) {
let value = data[dataKey] || ''
const el = document.querySelector(selector)
Object.defineProperty(data, dataKey, {
get: function () {
console.log(`key: ${dataKey}, value: ${value}`)
return value
},
set: function (val) {
value = val
dep.emit(tag, el, value, data)
}
})
if (on && typeof on === 'object') {
for (const key in on) {
if (on.hasOwnProperty(key) && typeof on[key] === 'function') {
el.addEventListener(key, on[key])
}
}
}
dep.on(tag, function (ele, value, data) {
console.log('触发订阅')
if (valueChange && typeof valueChange === 'function') {
valueChange(ele, value, data)
}
})
}
测试
<div id="box1">box1</div>
const obj = {}
mv({
data: obj,
tag: 'onBox1',
dataKey: 'name',
selector: '#box1',
valueChange: function (el, value, data) {
console.log('name变化了')
console.log(el, value, data)
},
on: {
click: function () {
console.log('box点击事件')
}
}
})
obj.name = '小明'
console.log(obj.name)