美文网首页
用原生js实现Vue单向数据绑定

用原生js实现Vue单向数据绑定

作者: 本一和他的朋友们 | 来源:发表于2020-03-08 16:41 被阅读0次

    问题:Vue的单项数据是如何绑定的

    为了了解vue的的单向数据绑定原理,看了官方文档

    发现Object.defineProperty是其核心,又查看了MDN文档,以下是自己参考文档和其他文章,使用原生js写出的代码,首先让代码跑起来,有个直观的感受,然后再深入解析。

    示例代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            body {
                display: flex;
                justify-content: center;
                align-items: center;
                margin: 0;
                padding: 0;
                height: 100vh;
            }
    
            .main{
                display: flex;
                justify-content: center;
                align-items: center;
                flex-direction: column;
            }
            
        </style>
        <title>用原生js实现单向数据绑定</title>
    </head>
    <body>
        <div class="main">
            <input type="text" id="model">
            
            <div id="modelText"></div>
        </div>
        <script>
            var model = document.querySelector("#model")
            var modelText = document.querySelector("#modelText")
    
            var defaultName = 'hello world'
            var userInfo = {}
            model.value = defaultName
    
            Object.defineProperty(userInfo, 'name', {
                get: function() {
                    return defaultName
                },
                set: function(newValue) {
                    model.value = newValue;
                    console.log("newValue is ===>>>", newValue)
                    modelText.textContent = newValue
                }
            })
    
            userInfo.name = defaultName
            var isEnd = true 
    
            model.addEventListener('keyup', function() {
                if (isEnd) {
                    userInfo.name = this.value
                }
            }, false)
    
            // 监听中文输入法切换
            model.addEventListener('compositionstart', function() {
                console.log('开始中文输入')
                isEnd = false
            })
    
            model.addEventListener('compositionend', function() {
                isEnd = true 
                console.log("结束中文输入")
            })
        </script>
    </body>
    </html>
    

    代码解析

    Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

    用法如下:

    Object.definProperty(
        obj,  // 要在其上定义的对象
        prop, // 要定义或修改的属性的名称
        descriptor  // 将被定义或修改的属性描述符
    )
    

    例子中通过Object.definProperty将userInfo.name的值利用get来获取值,利用set来监听值的变化。

        var userInfo = {}
    
        Object.defineProperty(userInfo, 'name', {
            get: function() {
            },
            set: function(newValue) {
            }
        })
    

    回头看Vue中的实现

    1. 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
    2. 这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。
    3. 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

    同时官方文档有图,更加直观的展示了数据变化过程


    image

    相关文章

      网友评论

          本文标题:用原生js实现Vue单向数据绑定

          本文链接:https://www.haomeiwen.com/subject/yyxjdhtx.html