当前位置: 首页 > article >正文

深入解析Vue中的双向数据绑定机制

文章目录

    • 一、双向数据绑定的概念
      • 单向绑定与双向绑定的区别
      • 双向绑定的实例
    • 二、双向绑定的原理
      • MVVM架构
      • ViewModel的工作原理
    • 三、Vue中的双向绑定实现
      • 双向绑定流程
      • 实现双向绑定的关键代码

一、双向数据绑定的概念

单向绑定与双向绑定的区别

单向绑定是将模型(Model)的数据绑定到视图(View)上,当模型数据发生变化时,视图会自动更新。而双向绑定在此基础上增加了视图到模型的反馈机制,即视图状态的变化也能自动反映到模型数据上。

双向绑定的实例

以表单输入为例,当用户在输入框中填写信息时,视图的状态发生变化,如果这种变化能实时更新到模型数据,那么就实现了双向绑定。

二、双向绑定的原理

MVVM架构

双向绑定是MVVM(Model-View-ViewModel)架构的核心特性之一。在MVVM中,ViewModel负责将模型和视图关联起来,实现数据的双向流动。

ViewModel的工作原理

ViewModel包含两个主要部分:

  • 监听器(Observer):负责监听模型数据的变化。
  • 解析器(Compiler):负责解析视图中的指令,并根据指令模板替换数据,同时绑定更新函数。

三、Vue中的双向绑定实现

双向绑定流程

在Vue中,双向绑定的流程包括以下几个步骤:

  1. 初始化Vue实例,对数据进行响应化处理。
  2. 编译模板,找到动态绑定的数据,并初始化视图。
  3. 定义更新函数和Watcher,用于数据变化时更新视图。
  4. 使用Dep管理多个Watcher,确保数据变化时能够通知所有相关的Watcher。

实现双向绑定的关键代码

以下是对Vue双向绑定关键部分的代码实现:

// Vue构造函数
class Vue {
  constructor(options) {
    this.$options = options;
    this.$data = options.data;
    observe(this.$data);
    proxy(this);
    new Compile(options.el, this);
  }
}
// 数据响应化处理
function observe(obj) {
  if (typeof obj !== "object" || obj == null) {
    return;
  }
  new Observer(obj);
}
class Observer {
  constructor(value) {
    this.value = value;
    this.walk(value);
  }
  walk(obj) {
    Object.keys(obj).forEach((key) => {
      defineReactive(obj, key, obj[key]);
    });
  }
}
// 编译器
class Compile {
  constructor(el, vm) {
    this.$vm = vm;
    this.$el = document.querySelector(el);
    if (this.$el) {
      this.compile(this.$el);
    }
  }
  compile(el) {
    const childNodes = el.childNodes;
    Array.from(childNodes).forEach((node) => {
      if (this.isElement(node)) {
        console.log("编译元素" + node.nodeName);
      } else if (this.isInterpolation(node)) {
        console.log("编译插值文本" + node.textContent);
      }
      if (node.childNodes && node.childNodes.length > 0) {
        this.compile(node);
      }
    });
  }
  isElement(node) {
    return node.nodeType == 1;
  }
  isInterpolation(node) {
    return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent);
  }
}
// 依赖收集
class Watcher {
  constructor(vm, key, updater) {
    this.vm = vm;
    this.key = key;
    this.updaterFn = updater;
    Dep.target = this;
    vm[key];
    Dep.target = null;
  }
  update() {
    this.updaterFn.call(this.vm, this.vm[this.key]);
  }
}
class Dep {
  constructor() {
    this.deps = [];
  }
  addDep(dep) {
    this.deps.push(dep);
  }
  notify() {
    this.deps.forEach((dep) => dep.update());
  }
}
function defineReactive(obj, key, val) {
  this.observe(val);
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    get() {
      Dep.target && dep.addDep(Dep.target);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      dep.notify();
    },
  });
}

http://www.kler.cn/news/359398.html

相关文章:

  • HCIP——以太网交换安全(四)DHCP Snooping
  • 设计模式——装饰者模式(8)
  • Go语言实现黑马点评项目
  • 子比主题美化-独立下载页美化样式
  • 【算法题】数组中只出现一次的两个数字
  • 一款基于 Vue 3 的现代化数据可视化组件库,功能强大,颜值爆表,开发者必备!(带私活源码)
  • MATLAB针对模型外表面画出机械臂喷涂轨迹
  • 1.计算机网络_基本知识
  • jenkins添加新服务
  • Vue2的依赖注入(跨级通信)基本使用
  • 【从零开始的LeetCode-算法】945. 使数组唯一的最小增量
  • 五款最佳免费解压软件APP推荐:手机端高效解压工具盘点
  • SHELL脚本之循环语句的for循环以及中断循环的语句
  • 暖水毯/取暖毯语音识别控制芯片IC方案
  • 使用Verilog设计分频模块(2Hz)
  • 外贸商城源码,进出口跨境电商平台电脑端+移动端网站+客服系统 网站设计及源码输出
  • 基于Java+Springboot+Vue开发的体育用品商城管理系统
  • @RequestMapping对不同参数的接收方式
  • Bluetooth Channel Sounding中关于CS Step及Phase Based Ranging相应Mode介绍
  • 算法|牛客网华为机试1-10C++