简单实现Vue的observer和watcher

首先,要实现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.js的生命周期钩子函数:created、mounted、updated、destroyed setInterval和clearInterval的用法 二、方法一:使用Vue.js的watch属性 如果在Vue组件中同时使用多个定时器…

    Vue 2023年5月29日
    00
  • 解决在Vue中使用axios用form表单出现的问题

    当在Vue项目中使用axios进行POST请求时,经常会遇到使用表单提交数据的情况,但是,表单需要以特定格式进行编码,否则服务器无法正常解析表单内容。本文将为大家详细讲解如何解决这一问题。 问题描述 我们在使用axios进行POST请求时,一般需要将数据封装在一个对象参数中,如下所示: axios.post(‘/api/login’, { username:…

    Vue 2023年5月28日
    00
  • element如何初始化组件功能详解

    在使用Vue.js开发应用时,我们通常会使用Element UI这样的第三方UI组件库来快速搭建和设计我们的应用。Element UI提供了很多常用的UI组件和工具,如表单、按钮、弹窗、分页、图表等,以及主题定制等功能,方便了我们进行快速开发。但在使用之前,需要了解Element组件的初始化。 首先,我们需要安装Element UI,使用npm安装命令: n…

    Vue 2023年5月28日
    00
  • 详解vue-cli脚手架中webpack配置方法

    以下是详解vue-cli脚手架中webpack配置方法的完整攻略。 1. 什么是Vue-cli脚手架和Webpack 1.1 Vue-cli脚手架 Vue-cli是Vue.js官方提供的一个包含脚手架工具和预设的完整系统。它可以帮助我们快速搭建Vue.js开发环境、开发模板及Webpack打包工具。 1.2 Webpack Webpack是一款模块化的打包工…

    Vue 2023年5月28日
    00
  • Vue中使用axios调用后端接口的坑及解决

    当在Vue中使用axios调用后端接口时,可能会遇到一些坑,例如跨域、请求头、响应数据处理等问题。下面是一个完整的攻略,解释了如何使用axios解决这些问题。 一、安装和引入axios 首先需要安装axios,可以使用npm或者yarn命令进行安装: npm install axios –save 或者 yarn add axios 然后在Vue项目中引入…

    Vue 2023年5月28日
    00
  • Vue项目打包并发布的完整步骤记录

    以下是Vue项目打包并发布的完整步骤记录的攻略。 1. 环境准备 首先,需要确保在本地环境中正确安装了Node.js和Vue CLI。Node.js可以从官网下载安装包来安装,安装完成后可以在终端中通过node -v和npm -v来检查安装是否成功。Vue CLI可以通过npm全局安装,命令为npm install -g @vue/cli。 2. 打包项目 …

    Vue 2023年5月28日
    00
  • Vue + better-scroll 实现移动端字母索引导航功能

    让我为你详细讲解“Vue + better-scroll 实现移动端字母索引导航功能”的完整攻略。 简介 better-scroll 是一款移动端的滚动库,可以使包裹内容的容器进行滚动并提供丰富的滚动特效。同时,Vue 是一款非常流行的前端框架,能够方便地将应用程序的数据和用户界面组件化,以及提供方便的指令和组件功能。在本攻略中,将 Vue 和 better…

    Vue 2023年5月27日
    00
  • Vue组件之非单文件组件的使用详解

    下面我将为您详细讲解“Vue组件之非单文件组件的使用详解”的完整攻略。 什么是非单文件组件? 非单文件组件是指将组件的HTML、JS、CSS等代码都写在同一个文件中,并使用Vue.extend()方法将其构造成组件的一种方式。这种方式比较旧,但在一些老的Vue项目中仍有应用。目前Vue的官方文档已经不推荐使用这种方式。 非单文件组件的优缺点 优点 代码简单。…

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