jq的方法实现data的数据跟页面双向绑定_[vue基础][万字长文]浅析vue2中的双向绑定...

前言

单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。

有单向绑定,就有双向绑定。如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定。

双向绑定在MVVM模式中发挥着及其重要的作用,它将视图与数据绑定起来,让我们得以关注于前后端交互的数据变动,而不必过度费心于页面的刷新上。

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。

一些关键解释如下。

模型

  • 模型是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。

视图

  • 就像在MVC和MVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观(UI)。

视图模型

  • 视图模型是暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器之间进行通信。

绑定器

  • 声明性数据和命令绑定隐含在MVVM模式中。绑定器使开发人员免于被迫编写样板式逻辑来同步视图模型和视图。在微软的堆之外实现时,声明性数据绑定技术的出现是实现该模式的一个关键因素。

数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更

数据劫持: vue3.0之前的版本是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调。

接下来,我将基于Object.defineProperty()和观察者模式,一步步实现双向绑定,构建一个简单的MVVM模式的雏形。如果还不了解Object.defineProperty()和观察者模式原理,建议可以先看看我之前的两篇博文。

  • 双向绑定基础原理——Object.defineProperty()的使用 https://blog.csdn.net/qq_41996454/article/details/107988996

  • 设计模式之观察者模式——Js实现  https://blog.csdn.net/qq_41996454/article/details/108042475

参考资料

《用ES6的class模仿Vue写一个双向绑定》 https://www.jianshu.com/p/78058c7922bf

剖析Vue原理&实现双向绑定MVVM

vue的双向绑定原理及实现

《Vue原理解析(八):一起搞明白令人头疼的diff算法》https://blog.csdn.net/u011199186/article/details/103668263

processon在线画图 https://www.processon.com/diagrams

初级版本

实现publisher

这个publisher实现的时候,要注意一下几点:

①监听data(对data中每个属性都使用Object.defineProperty加上setter和getter)

②对所有订阅者发布data的更新消息(调用订阅者的公共接口receiveTips)

那么监听到变化之后就是怎么通知订阅者了,所以接下来我们需要实现一个消息订阅器,很简单,维护一个数组,用来收集订阅者,数据变动触发notify,再调用订阅者的update方法

下面是封装成一个MVVM形式的样子。

let myMvvm = {
     
    $data: {
        data01: "test01",
        data02: "test02",
        data03: "test03",
    },

    // 指定元素
    $el: {}
};

// 对data中每个属性都使用Object.defineProperty加上 setter和getter
myMvvm._initPublisher = function (data = this.$data) {
    let that = this;

    Object.keys(data).forEach((key) => {
        let value = data[key];

        // 设置
        Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                console.log("这是get()方法");
                return value;
            },
            set: function (newVal) {
                if (value !== newVal) {
                    console.log("拦截到数据变化" + value + "---->" + newVal);
                    value = newVal;
                }
            },
        });
    });
    console.log(that);
};

myMvvm._initPublisher();

myMvvm.$data.data01 = 1;
console.log(myMvvm.$data.data01);
6a250733648c9f45081cc2379ffb38ea.png
img

当然,从简单的方式下入手,我们可以先不用封装成一个MVVM对象的样子。

 // 初始化发布者
initPublisher = function (data, subCenter) {
    Object.keys(data).forEach((key) => {
        let value = data[key];

        // 设置
        Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                console.log("这是get()方法");
                return value;
            },
            set: function (newVal) {
                if (value !== newVal) {
                    console.log("拦截到数据变化" + value + "---->" + newVal);
                    subCenter.notify(key, value, newVal)
                    value = newVal;     
                }
            },
        });
    });
};
let data = {
        data01: "test01",
        data02: "test02",
        data03: "test03",
      };
      
// --------------初始化发布者-------------
initPublisher(data, mySubCenter)

实现消息订阅中心

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值