vue.js - 学习vue的双向数据绑定的过程中,发现JavaScript的一个非常诡异的现象

查看:110
本文介绍了vue.js - 学习vue的双向数据绑定的过程中,发现JavaScript的一个非常诡异的现象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

现在vue如日中天,于是也凑个热闹学习一下。在学习vue的双向数据绑定的过程中,发现一个非常诡异的现象,百思不得其解,还望哪位大侠指点一下。

先看如下代码(熟悉vue的应该很好懂):

<!DOCTYPE html>
<html>
    <head>
        <title>ideal</title>
        <meta charset="utf-8">
    </head>

    <body>
        <input class="test" type="text" name="asd" onkeyup="handleChange()" v-model="hey">
        <input class="test" type="" name="" onkeyup="handleChange()" v-model="msg">
        <script>
            var bindingMark = 'data-element-binding'

            function Element(classa, initData) {
                var self = this,
                    el = self.el = document.getElementsByClassName(classa),
                    bindings = {}
                data = self.data = {}

                for (var i = 0; i < el.length; i++) {
                    //content = el[i].outerHTML.replace(/v-model=\"(.*)\"/g, markToken);
                    content = el[i].outerHTML.replace(/v-model=\"(.*)\"/g, function(match, variable) {
                        bindings[variable] = {}
                        return bindingMark + '="' + variable + '"'
                    });
                    el[i].outerHTML = content
                }

                for (var variable in bindings) {
                    //bind(variable);
                    bindings[variable].els = document.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
                    Object.defineProperty(data, variable, {
                        set: function (newVal) {
                            [].forEach.call(bindings[variable].els, function (e) {
                                bindings[variable].value = e.value = newVal
                            })
                        },
                        get: function () {
                            return bindings[variable].value
                        }
                    })
                }

                if (initData) {
                    for (var variable in initData) {
                        data[variable] = initData[variable]
                    }
                }

                function markToken(match, variable) {
                    bindings[variable] = {}
                    return bindingMark + '="' + variable + '"'
                }

                function bind(variable) {
                    bindings[variable].els = document.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
                    Object.defineProperty(data, variable, {
                        set: function (newVal) {
                            [].forEach.call(bindings[variable].els, function (e) {
                                //textContent改为input的value
                                bindings[variable].value = e.value = newVal
                            })
                        },
                        get: function () {
                            return bindings[variable].value
                        }
                    })
                }
            }

            var app = new Element('test', {
                msg: 'hello',
                hey: 'aaa'
            })

            function handleChange(e) {
                e = e || window.event
                var key = e.target.outerHTML.match(/data-element-binding=\"(.*)\"/)[1];
                data[key] = e.target.value
                console.log(data.hey, data.msg);
            }
        </script>
    </body>
</html>

上面这段代码,原来的代码中涉及到两个只调用了一次的函数:markToken和bind,于是我将其合并到调用的地方,结果诡异的事情出现了:原来互不影响的两个input的值,现在如果改变第二个input的值竟然会影响第一个input的值!进一步测试后发现,这与将markToken函数合并无关,而只与将bind函数合并有关。

如果在Chrome控制台查看data对象的值发现,改之前其两个属性(data.hey、data.msg)的值不同,改之后这两个属性的值相同:

问题出在哪里?

解决方案

for (var variable in bindings) {
    // ...
}

这里,闭包啊,set和get里variable都指向一个了

这篇关于vue.js - 学习vue的双向数据绑定的过程中,发现JavaScript的一个非常诡异的现象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆