将以下代码保留为文件 即可查看成果!
<script type="text/javascript">
const weakMap = new WeakMap
const effectStack = []
let activeEffect
function pushStack(o) {effectStack.push(o); activeEffect = o }
function popStack() { effectStack.pop(); activeEffect = effectStack[effectStack.length - 1] }
function trigger(obj, k) {let k2depMap = weakMap.get(obj)
if (!k2depMap) return
const dep = k2depMap[k]
if (!dep) return
dep.forEach(e => e())
}
function track(obj, k) {if (!activeEffect) return
let k2depMap = weakMap.get(obj)
if (!k2depMap) weakMap.set(obj, k2depMap = {})
let dep = k2depMap[k]
if (!dep) dep = k2depMap[k] = new Set
dep.add(activeEffect)
}
function effect(fn, option = {}) {const effect = function() {
try {pushStack(fn)
return fn()} finally {popStack()
}
}
if (!option.lazy) effect()
return effect
}
function reactive(state) {
return new Proxy(state, {set(target, k, v) {target[k] = v
trigger(target, k, v)
},
get(target, k) {track(target, k)
return target[k]
}
})
}
</script>
<button id="btn" onclick="btn_click()"></button>
<div id="circle" onclick="circle_click()"> 切换圆角 </div>
<script type="text/javascript">
const state = reactive({count: 1, circle: true})
effect(() => {const div = document.getElementById('btn')
div.innerText = '计数 _' + state.count
})
effect(() => {const div = document.getElementById('circle')
const style = {borderRadius: state.circle ? '20px' : 0}
Object.assign(div.style, style)
})
function btn_click() {state.count++}
function circle_click() {state.circle = !state.circle}
</script>
<style type="text/css">
#circle {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
width: 100px;
height: 100px;
background-color: #dd8538;
}
</style>