模拟实现vue响应式

51 阅读1分钟

1.html代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

</head>

<body>
    <div class="container">
        <div class="username"></div>
        <div class="userage"></div>
    </div>
</body>

</html>
<style>
    * {
        box-sizing: border-box;
    }

    .container {
        width: 200px;
        height: 200px;
        background-color: skyblue;
        text-align: center;
        padding-top: 50px;
    }
</style>
<script src="./vue.js"></script>
<script src="./index.js"></script>

2.vue.js代码

function observer(data) {
    for (let key in data) {
        let intervalData = data[key]
        // 依赖函数队列
        const fns = []
        Object.defineProperty(data, key, {
            get() {
                if (!fns.includes(window.__fn)) {
                    fns.push(window.__fn)
                }
                return intervalData
            },
            set(val) {
                intervalData = val
                for (let i = 0; i < fns.length; i++) {
                    fns[i] && fns[i]()
                }
            }
        })
    }
}

// 收集依赖函数
function autoRun(fn) {
    window.__fn = fn
    fn()
    window.__fn = null
}

3.使用vue.js实现响应式

const user = {
    username: '张三',
    userage: 12
}

observer(user)

const doms = {
    username: document.querySelector('.username'),
    userage: document.querySelector('.userage')
}


const changeName = () => {
    doms.username.textContent = '姓名:' + user.username
}
const changeAge = () => {
    doms.userage.textContent = '年龄:' + user.userage
}

autoRun(changeName)
autoRun(changeAge)
user.username = '王八'

image.png