给jQuery添加vue的响应式简单封装 2022-01-20

咸浩初
2023-12-01

demo

参照 使用jquery treetable生成数表,并且支持多选择列

源码

(function (root, factory) {
  if (typeof define === "function" && define.amd) {
    // AMD
    define(["jquery"], factory);
  } else if (typeof exports === "object") {
    // Node, CommonJS之类的
    module.exports = factory(require("jquery"));
  } else {
    // 浏览器全局变量(root 即 window)
    root.$r = factory(root.jQuery);
  }
})(this, function ($) {
  let activeEffect = null; // 能收集观察者的关键

  // 转换成响应式对象
  function reactive(target) {
    let depsMap = null; // 源码用到的是 WeakMap,将所有的观察者集合进行了全局存储
    return new Proxy(target, {
      get(obj, key, receiver) {
        const val = Reflect.get(obj, key, receiver); // 最后,返回属性值
        if(!activeEffect) return val; // 存在焦点观察者时,再进行收集逻辑
        if (!depsMap) {
          // 初始化对象的观察者集合
          depsMap = new Map();
        }
        let dep = depsMap.get(key);
        if (!dep) {
          // 初始化每个属性的观察者集合
          depsMap.set(key, (dep = new Set()));
        }

        // 收集观察者
        dep.add(activeEffect);

        return val;
      },
      set(obj, key, val, receiver) {
        let res = Reflect.set(obj, key, val, receiver); // 先设置属性值
        if (!depsMap) return res;
        let dep = depsMap.get(key);
        if (!dep) return res;
        dep.forEach((x) => x()); // 获取到属性的观察者集合,并触发
      },
    });
  }

  // 注册观察者
  // TODO: 目前没有做注销观察者
  function effect(eft) {
    activeEffect = eft;
    activeEffect();
    activeEffect = null;
  }

  const jqueryFuns = {};
  // attr使用时,需要使用单个的键值对,如果传对象,每次都会更新对象内的所有属性
  ["text", "attr", "prop"].forEach((x) => {
    jqueryFuns[x] = function ($el, getArgs) {
      effect(() => {
        $el[x](...getArgs())
      });
    };
    $.prototype[`r_${x}`] = function (getArgs) {
      jqueryFuns[x](this, getArgs);
    };
  });

  return { reactive, effect, ...jqueryFuns };
  // ————————————————
  // 版权声明:本文为CSDN博主「anywo01」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
  // 原文链接:https://blog.csdn.net/y1377593732/article/details/122590479
});

 类似资料: