通过原生js 实现vue的数据双向绑定

双向绑定原理

首先,vue实现数据双向绑定的原理是:采用数据劫持结合发布者-订阅者模式,通过Object.defineProperty(obj,props)来劫持各个属性的setter和getter方法,在数据变动时发布消息给订阅者,触发相应的回调函数。当把一个普通object对象传给
Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为
getter/setter。

Object.defineProperty()

定义

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

语法

Object.defineProperty(obj, prop, descriptor)

参数介绍

参数说明
obj要定义属性的对象。
prop要定义或修改的属性的名称或 Symbol 。
descriptor要定义或修改的属性描述符。

实现思路

  1. 首先定义一个普通的劫持对象,也就是defineObj,通过Object.defineProperty()来劫持对象,同时添加好被劫持对象的setter和getter方法。在劫持对象被访问取值时触发getter方法,赋值值时触发setter方法
  2. 给页面的input添加一个监听方法,来监听input输入值的改变,当input输入改变时,将新值赋值给劫持对象,这个时候就会触发接触对象的setter方法。来改变视图模型的值。在我们直接访问劫持对象属性时,触发getter,直接返回被访问的值。并反应在视图模型中。

代码片段

<div class="body">
        <label for="input">输入</label>
        <input type="text" id="input">
        <span>输出:</span><span id="output"></span>
    </div>
    <script>
        /**
         * 原生js实现vue数据双向绑定:
         * 
         * 首先,vue实现数据双向绑定的原理是:采用数据劫持结合发布者-订阅者模式,通过Object.defineProperty(obj,props)来劫持各个属性的setter和getter方法,
         * 在数据变动时发布消息给订阅者,触发相应的回调函数。
         * 当把一个普通object对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,
         * 用 Object.defineProperty() 将它们转为 getter/setter。
         * 
         * 
         * Object.defineProperty()
         * 
         * Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
         * 语法:
         * Object.defineProperty(obj, prop, descriptor)
         * obj  要定义属性的对象。
         * prop 要定义或修改的属性的名称或 Symbol 。
         * descriptor 要定义或修改的属性描述符。
         *  
         * 思路:
         * 1、首先定义一个普通的劫持对象,也就是defineObj,通过Object.defineProperty()来劫持对象,同时添加好被劫持对象的setter和getter方法。
         *    在劫持对象被访问取值时触发getter方法,赋值值时触发setter方法
         * 2、给页面的input添加一个监听方法,来监听input输入值的改变,当input输入改变时,将新值赋值给劫持对象,这个时候就会触发接触对象的setter方法。
         *    来改变视图模型的值。在我们直接访问劫持对象属性时,触发getter,直接返回被访问的值。并反应在视图模型中。
         * */
        let input = document.getElementById("input")
        let output = document.getElementById("output")

        //劫持对象
        let defineObj = {}

        input.addEventListener("input", function (e) {
            let { value } = e.target
            defineObj.value = value
        })

        Object.defineProperty(defineObj, "value", {
            configurable: true,
            enumerable: true,
            set: function (nVal) {
                value = nVal
                input.value = nVal
                output.innerHTML = nVal
            },
            get: function () {
                return value
            }
        })

    </script>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值