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)