简单实现Vue的observer和watcher

yizhihongxing

首先,要实现Vue的Observer和Watcher,需要进行以下步骤:

  1. Observer:

Vue中的Observer实现了数据响应式,它可以监听数据的变化并自动更新相应的视图。实现Observer需要使用ES6的Proxy对象来劫持对象或数组的访问。代码示例:

function observe(obj) {
  if(!obj || typeof obj !== 'object') {
    return;
  }
  Object.keys(obj).forEach((key) => {
    defineReactive(obj, key, obj[key]);
  });
}

function defineReactive(obj, key, val) {
  observe(val); // 递归处理
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      dep.depend();
      return val;
    },
    set: function reactiveSetter(newVal) {
      if(val === newVal) {
        return;
      }
      val = newVal;
      observe(newVal);
      dep.notify();
    }
  });
}

class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  removeSub(sub) {
    remove(this.subs, sub);
  }

  depend() {
    if(window.target) {
      this.addSub(window.target);
    }
  }

  notify() {
    const subs = this.subs.slice();
    for(let i = 0, l = subs.length; i < l; i++) {
      subs[i].update();
    }
  }
}

function remove(arr, item) {
  if(arr.length) {
    const index = arr.indexOf(item);
    if(index > -1) {
      return arr.splice(index, 1);
    }
  }
}

在这段代码中,我们使用Object.defineProperty方法重写所需要劫持的对象属性,实现其get和set方法。在get方法中,我们添加了一个依赖收集器Dep,它负责收集Watcher对象,而在set方法中,当其值被更改时,会触发notify方法,通知所有依赖(对应的Watcher对象)更新其视图。

  1. Watcher:

Watcher作为Observer和Vue之间的桥梁,负责监听数据的变化,并触发响应的更新。它需要接收一个update函数作为参数,在数据变化时调用。代码示例:

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    this.getter = parsePath(expOrFn);
    this.cb = cb;
    this.value = this.get();
  }

  get() {
    window.target = this;
    const vm = this.vm;
    let value = this.getter.call(vm, vm);
    window.target = undefined;
    return value;
  }

  update() {
    const oldValue = this.value;
    this.value = this.get();
    this.cb.call(this.vm, this.value, oldValue);
  }
}

const bailRE = /[^\w.$]/;
function parsePath(path) {
  if(bailRE.test(path)) {
    return;
  }
  const segments = path.split('.');
  return function(obj) {
    for(let i = 0; i < segments.length; i++) {
      if(!obj) {
        return;
      }
      obj = obj[segments[i]];
    }
    return obj;
  }
}

在这段代码中,我们实现了一个Watcher类,它需要接收Vue实例、监听的表达式和回调函数。在get方法中,我们通过parsePath方法解析传入的表达式,获取相应数据,并将当前Watcher对象添加到收集器Dep中。在update方法中,我们触发回调函数,并传递新旧值作为参数。

至此,我们已经成功实现了Vue的Observer和Watcher。

下面是一个简单的示例,演示了如何使用Observer监听对象变化并触发响应的Watcher:

const obj = {a: 1, b: {c: 2}};
observe(obj);
new Watcher(obj, 'b.c', value => {
    console.log('b.c changed', value);
});
obj.b.c = 3; // 输出 "b.c changed 3"

再来一个示例,演示如何通过Watcher监听数组元素的变化:

const arr = [1, 2, 3];
observe(arr);
new Watcher(arr, 'length', value => {
    console.log('array length changed', value);
});
new Watcher(arr, '1', value => {
    console.log('array element changed', value);
});
arr.push(4); // 输出 "array length changed 4"
arr[1] = 5; // 输出 "array element changed 5"

在这个示例中,我们监听了数组的长度变化和第二个元素的变化,当数组长度或第二个元素发生变化时,Watcher对象会触发相应的回调函数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:简单实现Vue的observer和watcher - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • vue中清除定时器的方法实例详解

    首先让我来讲解一下“Vue中清除定时器的方法实例详解”。 简介 在Vue开发中,经常使用定时器来完成一些定时触发的任务。但是,在组件销毁之前需要清除定时器,否则旧的定时器会一直存在,导致内存泄漏和可能的性能问题。因此,了解如何在Vue中清除定时器是非常重要的。 清除定时器的方法 Vue中清除定时器,可以使用 clearInterval() 和 clearTi…

    Vue 2023年5月29日
    00
  • 打印Proxy对象和ref对象的包实现详解

    “打印Proxy对象和ref对象的包实现详解”是一个介绍JavaScript中 Proxy 对象和 Reflect 对象的文章,为了更好地理解这个主题,我们需要了解以下几个方面: Proxy对象和Reflect对象的概念和作用; Proxy对象和Reflect对象的使用场景; Proxy对象和Reflect对象的包实现方式。 什么是Proxy对象和Refle…

    Vue 2023年5月28日
    00
  • SpringBoot实现滑块验证码验证登陆校验功能详解

    下面我将为你详细讲解“SpringBoot实现滑块验证码验证登陆校验功能”的完整攻略。 1. 概述 在本文中,我们将介绍使用SpringBoot来实现滑块验证码验证登陆校验功能的完整攻略。其中,我们使用了阿里云的滑块验证码服务和Spring Security框架来完成。 本文将分为以下几个部分: 阿里云滑块验证码服务介绍 SpringBoot集成阿里云滑块验…

    Vue 2023年5月28日
    00
  • VSCode创建Vue项目的完整步骤教程

    下面是创建Vue项目的完整步骤教程: 准备工作 首先,你需要安装一些软件,包括: Node.js(可以在官网上下载安装包) Visual Studio Code(可以在官网上下载安装包) 安装好Node.js后,你可以在命令行界面输入以下命令,查看其版本号,以确认是否安装成功: node -v 安装好Visual Studio Code后,你需要安装Vue.…

    Vue 2023年5月27日
    00
  • vue项目中在外部js文件中直接调用vue实例的方法比如说this

    在 Vue 项目中,我们通常会将 JS 代码放在 Vue 组件中,这种方式可以方便地获取 Vue 实例和数据,但是有些场景需要在外部 JS 文件中直接调用 Vue 实例的方法,这时我们需要一些特殊的处理。 在外部 JS 文件中调用 vue 实例方法的参考步骤 先在外部 JS 文件中引入 Vue 库 js import Vue from “vue”; 注意: …

    Vue 2023年5月27日
    00
  • Vue中保存数据到磁盘文件的方法

    保存数据到磁盘文件通常需要后端来完成,但是在一些简单的场景下,我们可以直接使用前端技术来实现。下面我将介绍两种在Vue中保存数据到磁盘文件的方法。 使用axios向后端发送请求保存数据 在Vue中,我们可以借助axios实现向后端发送请求保存数据的操作。具体步骤如下: 引入axios <script src="https://cdn.jsde…

    Vue 2023年5月28日
    00
  • vitejs预构建理解及流程解析

    ViteJS 预构建理解及流程解析 简介 ViteJS 是一款基于 ES modules 构建的前端开发工具,它具有快速的开发速度和优秀的开发体验。其中,预构建是 ViteJS 的重点特性之一。 预构建,即根据源代码提前展开模块之间的依赖关系,以在后续的开发过程中减少许多不必要的耗时和额外请求。具体而言,预构建会将每个模块和它所依赖的模块转化为一个 Java…

    Vue 2023年5月27日
    00
  • ts中的void和never类型及区别

    下面是详细讲解“ts中的void和never类型及区别”的完整攻略。 Void类型 Void类型表示函数没有返回值(或值为undefined)。在TS中,定义函数时可以显式指定函数的返回类型为void,例如以下代码: function sayHello(): void { console.log("Hello!"); } 上述代码中,定义…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部