基于Proxy的双向数据绑定尝试

基于Proxy的双向数据绑定尝试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基于Proxy的双向数据绑定尝试</title>
</head>
<body>
    <div id="root">
        名字:<input id="inputName" type="text" oninput="reWrite('name')">
        年龄:<input id="inputAge" type="text" oninput="reWrite('age')">
        <div id="content">
            <p>name: {{name}}</p>
            <p>age: {{age}}</p>
        </div>
    </div>
    <script>
        let temp = {
            name: '王艳军',
            age: 21
        }
        let htmls
        // 对模板进行处理后渲染到页面
        function render(template, variable) {
            // JS编译原理
            // 此处省略词素生成器,直接用表达式
            const Extractor = /{{(.+)}}/g
            let hasNext = true
            while (hasNext) {
                let res = Extractor.exec(template)
                let str, varName
                if(res && res.length >= 2) {
                    str = res[0]
                    varName = res[1]
                    console.log(str, varName)
                    template = template.replace(str, variable[varName])
                }else {
                    hasNext = false
                }
            }

            // 获取作用域,进行代码替换重新渲染
            // 此处省略了虚拟DOM中diff算法部分,因为比较麻烦,就直接全替换了
            let content = document.getElementById("content")
            content.innerHTML = template

            // 此处省略v-model写法,其实原理一样,都是编译原理
            // 首先js会解析作用域内的代码
            // 然后对解析出的代码进行指定语法部分的替换,如{{}}\@click等
            // 对一些属性,如v-model\v-bind进行记录,将使用同一变量的进行归类,统一控制
            document.getElementById("inputName").value = temp.name
            document.getElementById("inputAge").value = temp.age
        }
        // 代理,实现双向数据绑定的核心
        let tempPrpxy = new Proxy(temp, {
            set(target, p, value, receiver) {
                target[p] = value
                // 进行数据重渲染
                render(htmls, target)
                return true
            }
        })

        // 当数值改变时,先将数据层改变,通过代理重新渲染页面
        function reWrite(type) {
            let input
            if(type === 'name') {
                input = document.getElementById("inputName")
            }else if(type === 'age') {
                input = document.getElementById("inputAge")
            }
            let value = input.value
            tempPrpxy[type] = value
        }

        function onready() {
            // 获取模板
            htmls = document.getElementById('content').innerHTML
            // 进行第一次渲染
            render(htmls,temp)
        }

        window.onload = onready
    </script>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值