JavaScript 数据与DOM双向绑定
reactive.js
export default { reactive }
export function reactive(target, prism = new Map()) {
if (Array.isArray(target)) {
const items = target.map(item => {
if (item instanceof HTMLElement) {
return item
}
return reactive(item, prism)
})
return new Proxy(items, {
get(target, prop) {
if (prop === "map") {
return function (...args) {
return reactive(target[prop](...args).map((item, index) => {
if (item === target[index]) {
return item
}
if (item instanceof HTMLElement) {
const arr = prism.get(target[index]) ?? []
arr.push(item)
prism.set(target[index], arr)
return item
}
return reactive(item, prism)
}))
}
}
if (prop === "pop") {
console.log("调用了 pop 方法", target)
return function (...args) {
const item = target[prop](...args)
const arr = prism.get(item) ?? []
arr.forEach(element => element.remove()) // 移除映射的DOM
return item
}
}
if (prop === "splice") {
console.log("调用了 splice 方法", target)
return function (...args) {
const items = target[prop](...args)
items.map(item => {
const arr = prism.get(item) ?? []
arr.forEach(element => element.remove()) // 移除映射的DOM
})
return items
}
}
return target[prop]
},
set(target, prop, value) {
target[prop] = reactive(value, prism)
return true
}
})
}
if (typeof target === "object" && target !== null) {
const proxiedObject = {}
for (const key in target) {
proxiedObject[key] = reactive(target[key], prism)
}
return new Proxy(proxiedObject, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
target[prop] = value
return true
}
})
}
return target
}
index.html
<!DOCTYPE html>
<script type="module">
// 创建响应式数据
const data = reactive([
{ id: 1, name: 'aa' },
{ id: 2, name: 'bb' },
{ id: 3, name: 'cc' },
])
document.body.append(data.map(item => {
const element = document.createElement('div')
element.textContent = item.name
element.onclick = (event) => {
console.log('删除数据会自动移除DOM元素')
data.splice(data.indexOf(item), 1)
}
return element
}))
</script>
--- satori ---
Last