案例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.cover {
display: flex;
}
.box {
height: 100px;
width: 100px;
border: 1px solid #333;
margin-right: 30px;
line-height: 100px;
text-align: center;
color: #fff;
}
.box1 {
background-color: aqua;
}
.box2 {
background-color: #789;
}
.box3 {
background-color: rgb(53, 26, 102);
}
.box4 {
background-color: rgb(139, 37, 59);
}
.btn_cover {
margin-top: 30px;
display: flex;
}
button {
margin-right: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="cover">
<div class="box box1" v-if="isshow1">
box1
</div>
<div class="box box2" v-if="isshow2">
box2
</div>
<div class="box box3" v-show="isshow3">
box3
</div>
<div class="box box4" v-show="isshow4">
box4
</div>
</div>
<div class="btn_cover">
<button @click="changeShow1">btn1</button>
<button @click="changeShow2">btn2</button>
<button @click="changeShow3">btn3</button>
<button @click="changeShow4">btn4</button>
</div>
</div>
</body>
<script src="./index.js"></script>
<script>
new myProxy({
el: "#app",
data: {
isshow1: false,
isshow2: false,
isshow3: false,
isshow4: false
},
methods: {
changeShow1() {
this.data.isshow1 = !this.data.isshow1
},
changeShow2() {
this.data.isshow2 = !this.data.isshow2
},
changeShow3() {
this.data.isshow3 = !this.data.isshow3
},
changeShow4() {
this.data.isshow4 = !this.data.isshow4
},
}
})
</script>
</html>
js
class myProxy {
constructor(options) {
let { el, data, methods } = options
this.el = document.querySelector(el)
this.data = data
this.methods = methods
this.eventPool = new Map()
this.dataPool = new Map()
this.init()
}
init() {
this.initData() //data中的数据添加响应式
this.initDom(this.el) // 收集数据,methods pool
this.initView(this.dataPool) // 将收集到的数据 初始化到具体的节点,控制节点的初始化显示和隐藏
this.initEvent(this.eventPool) // 给收集到的eventPool 绑定事件到具体的节点
}
initData() {
let that = this
this.data = new Proxy(this.data, {
get(target, key) { // 还有一个没有完成的功能,this=>this.data
// console.log("get--", target[key]);
return Reflect.get(target, key)
},
set(target, key, value) {
// console.log("set--", value);
that.changeView(key, that.dataPool)
return Reflect.set(target, key, value)
}
})
}
initDom(el) {
let childNodes = el.childNodes
if (childNodes.length === 0) { // 文本节点
return
}
childNodes.forEach(item => {
if (item.nodeType === 1) { // 元素节点
const vIf = item.getAttribute("v-if")
const vShow = item.getAttribute("v-show")
const vEvent = item.getAttribute("@click")
if (vIf) {
// 收集数据
this.dataPool.set(item, {
type: "if",
show: this.data[vIf],
data: vIf
})
}
if (vShow) {
this.dataPool.set(item, {
type: "show",
show: this.data[vShow],
data: vShow
})
}
if (vEvent) {
this.eventPool.set(item, this.methods[vEvent])
}
}
this.initDom(item)
})
}
initView(dataPool) {
// 切换视图
this.changeView(null, dataPool)
}
changeView(data = null, dataPool) {
if (!data) { // 初始化
for (let [k, v] of dataPool) {
switch (v.type) {
case "if":
v.comment = document.createComment('V-IF') // 创建一个文本节点来替换
!v.show && k.parentNode.replaceChild(v.comment, k)
break;
case "show":
!v.show && (k.style.display = "none")
break;
default:
break;
}
}
return
}
// 数据修改时执行
for (let [k, v] of dataPool) {
if (v.data === data) {
switch (v.type) {
case "if":
v.show ? k.parentNode.replaceChild(v.comment, k)
: v.comment.parentNode.replaceChild(k, v.comment)
v.show = !v.show
break;
case "show":
v.show ? (k.style.display = "none") :
(k.style.display = "block")
v.show = !v.show
break;
default:
break;
}
}
}
}
initEvent(eventPool) {
for (let [k, v] of eventPool) {
k.addEventListener("click", v.bind(this), false)
}
}
}