超简易的mvvm,一看就明白数据是如何跟dom打交道

之前面试过几个前端,问到vue数据绑定的原理时几乎都说了 拦截get set,但是数据怎么跟dom打交道却是说不清楚。

心血来潮 ,写个小demo,使用的是遍历数据的方式。

 

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

    <div id="app">
        <input type="text" name="" data-model="inputvalue" id="input1">
        <input type="text" name="" data-model="inputvalue" id="input2">
        <h3 data-model="inputvalue" id="h1"></h3>
        <input type="button" data-click="changedate" value="click" />
    </div>

    <script>

        let olddata = {};
        let newdata = {
            inputvalue: "inputvalue"
        };
        let watchers = {};
        let methods = {
            changedate: function () {
                newdata["inputvalue"] = new Date().toLocaleTimeString();
            }
        }
        //遍历数据
        function diffData() {

            Object.keys(newdata).forEach(key => {

                for (let key in newdata) {
                    var newvalue = newdata[key];
                    var oldvalue = olddata[key];
                    debugger
                    if (newvalue !== oldvalue) {
                        olddata[key] = newvalue;

                        let handlers = watchers[key] || [];
                        handlers.forEach(handler => {
                            try {
                                handler(newvalue);
                            }
                            catch (e) {
                                console.log(e);
                            }
                        })
                    }
                }

            })
        }
        //遍历数据
        function diffThread() {
            setTimeout(() => {
                diffData();
                diffThread();
            }, 10);
        }

        //有value的处理
        function inputhandler(element) {
            let newelement = element;
            return function (newvalue) {
                if (newelement.value !== newvalue) {
                    newelement.value = newvalue
                }
            }
        }
        //其它的值
        function texthandler(element) {
            let newelement = element;
            return function (newvalue) {
                newelement.innerText = newvalue;
            }
        }
        //解析dom
        function initDoms(doms) {
            console.log(doms)

            for (let i = 0; i < doms.length; i++) {
                let element = doms[i];
                console.log(element);
                debugger
                let key = element.dataset.model;
                if (typeof key != 'undefined') {

                    if (typeof watchers[key] == 'undefined')
                        watchers[key] = [];

                    if (element.localName == 'input') {
                        //添加监听事件
                        element.addEventListener("keyup", (e) => {
                            let input = e.target;
                            newdata[input.dataset.model] = input.value;
                        });
                        //添加更新处理方法
                        watchers[key].push(inputhandler(element));
                    }
                    else {
                        //添加更新处理方法
                        watchers[key].push(texthandler(element));
                    }
                }
                let clickkey = element.dataset.click;
                if (typeof clickkey != 'undefined') {
                    //添加事件监听
                    element.addEventListener("click", (e, ev) => {
                        methods[clickkey]();
                    })
                }
                //递归处理
                arguments.callee(element.children);
            }

        }
        //初始化
        function init(id) {
            let doms = document.getElementById(id).children;
            initDoms(doms);
            diffThread();
        }

        //初始化
        init("app");




    </script>
</body>

</html>

demo gif

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值