简单实现 五

问题分析,当 obj.ok = false; 时,此代码的 obj.text 的 关联 effect 函数还存在,当obj.text 发生变化时,还会触发 effect函数执行,此时 视图层 还是现实 not,触发不必要的变化了

  1. const bucket = new WeakMap();
  2. const data = {ok: true, text: "hello world vue"};
  3. const track = (target, key) => { // [træk] 跟踪
  4. if (!activeEffect) {
  5. return;
  6. }
  7. let depsMap = bucket.get(target);
  8. if (!depsMap) {
  9. bucket.set(target, (depsMap = new Map()));
  10. }
  11. let deps = depsMap.get(key);
  12. if (!deps) {
  13. depsMap.set(key, (deps = new Set()));
  14. }
  15. deps.add(activeEffect);
  16. };
  17. const trigger = (target, key) => { // [ˈtrɪɡə(r)] 触发
  18. const depsMap = bucket.get(target);
  19. if (!depsMap) return;
  20. const effects = depsMap.get(key);
  21. effects && effects.forEach(fn => fn());
  22. };
  23. const obj = new Proxy(data, {
  24. get(target, key) {
  25. track(target, key);
  26. return target[key];
  27. },
  28. set(target, key, newVal) {
  29. target[key] = newVal;
  30. __key = key;
  31. trigger(target, key);
  32. return true;
  33. }
  34. });
  35. window.__self = obj;
  36. let __key;
  37. let activeEffect;
  38. function effect(fn) {
  39. activeEffect = fn;
  40. fn();
  41. }
  42. // 初始化
  43. effect(
  44. // 一个匿名的副作用函数
  45. () => {
  46. console.log(__key);
  47. document.body.innerText = obj.ok ? obj.text : "not";
  48. }
  49. );
  50. setTimeout(() => {
  51. obj.text = "hello vue3";
  52. });

简单实现 六

  1. const bucket = new WeakMap();
  2. window.__weakMap = bucket;
  3. const data = {ok: true, text: "hello world vue"};
  4. const track = (target, key) => { // [træk] 跟踪
  5. if (!activeEffect) {
  6. return;
  7. }
  8. let depsMap = bucket.get(target);
  9. if (!depsMap) {
  10. bucket.set(target, (depsMap = new Map()));
  11. }
  12. let deps = depsMap.get(key);
  13. if (!deps) {
  14. depsMap.set(key, (deps = new Set()));
  15. }
  16. deps.add(activeEffect);
  17. activeEffect.desp.push(deps);
  18. };
  19. const trigger = (target, key) => { // [ˈtrɪɡə(r)] 触发
  20. const depsMap = bucket.get(target);
  21. if (!depsMap) return;
  22. const effects = depsMap.get(key);
  23. const effectsToRun = new Set(effects);
  24. effectsToRun.forEach(effectFn => effectFn());
  25. // effects && effects.forEach(fn => fn());
  26. };
  27. const obj = new Proxy(data, {
  28. get(target, key) {
  29. track(target, key);
  30. return target[key];
  31. },
  32. set(target, key, newVal) {
  33. target[key] = newVal;
  34. __key = key;
  35. trigger(target, key);
  36. return true;
  37. }
  38. });
  39. window.__self = obj;
  40. let __key;
  41. let activeEffect;
  42. function cleanup (effectFn) {
  43. for(let i = 0; i < effectFn.desp.length; i += 1) {
  44. const desp = effectFn.desp[i];
  45. desp.delete(effectFn);
  46. }
  47. effectFn.desp.length = 0;
  48. }
  49. function effect(fn) {
  50. const effectFn = () => {
  51. cleanup(effectFn);
  52. activeEffect = effectFn;
  53. fn();
  54. };
  55. effectFn.desp = [];
  56. effectFn();
  57. }
  58. // 初始化
  59. effect(
  60. // 一个匿名的副作用函数
  61. () => {
  62. console.log(__key);
  63. document.body.innerText = obj.ok ? obj.text : "not";
  64. }
  65. );
  66. setTimeout(() => {
  67. obj.text = "hello vue3";
  68. });