ホームページ  >  記事  >  ウェブフロントエンド  >  vue3の応答原理とAPIの書き方の分析

vue3の応答原理とAPIの書き方の分析

藏色散人
藏色散人転載
2021-12-10 14:56:591486ブラウズ

序文

vue3 レスポンシブ原則と API 記述、vue3 レスポンシブ原則をすぐに理解する

GitHub ブログ: https://github 。 com/jiejiangzi/blog/issues/8

vue3 レスポンシブ原則の実装

最初にコードを書いて見てみましょう

効果の実装

var name = 'sl', age = 22;
effect1 = () => `我叫${name},今年${age}岁`
effect2 = () => `我叫${name},今年${age+1}岁`
console.log(effect1()) //我叫sl,今年22岁
console.log(effect2()) //我叫sl,今年23岁
age = 30;
console.log(effect1())  //我叫sl,今年30岁
console.log(effect2())  //我叫sl,今年31岁

何を最適化できるか見てみましょう。

まず第一に、複数の関数です。年齢が変更された後、最新の情報を取得するには、複数の関数を手動で再度呼び出す必要があります。

複数の関数は、年齢が変更された後、自動的に呼び出せることが期待されます。

実装方法

gather関数に複数の関数をまとめて格納しておき、時代が変わったときに複数の関数を呼び出すことが考えられます。トリガー呼び出し

収集とトリガーを実装します

var name = "sl",
  age = 22;
var tom, joy;
effect1 = () => (tom = `我叫${name},今年${age}岁`);
effect2 = () => (joy = `我叫${name},今年${age + 1}岁`);
var dep = new Set();
function gather() {
  dep.add(effect1);
  dep.add(effect2);
}
function trigger() {
  dep.forEach((effect) => effect());
}
gather();
effect1()
effect2()
console.log(tom); //我叫sl,今年22岁
console.log(joy); //我叫sl,今年23岁
age = 30;
trigger()
console.log(tom); //我叫sl,今年30岁
console.log(joy); //我叫sl,今年31岁

続けて、最適化できる点があるかどうか確認しましょう

変数が 1 つのオブジェクトまたは複数のオブジェクトの場合はどうするか

  • 変数がプリミティブ型の場合はストレージを設定します

  • ##変数がオブジェクトの場合は、map を使用してそれを格納できます

  • 複数のオブジェクトがある場合は、weakMap を使用してそれを保存できます。

  • var obj1 = { name: "tom", age: 22 };
    var obj2 = { name: "joy", age: 23 };
    var tom, joy;
    effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}岁`);
    effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}岁`);
    var depsMap = new WeakMap();
    function gather(target, key) {
      let depMap = depsMap.get(target);
      if (!depMap) {
        depsMap.set(target, (depMap = new Map()));
      }
      let dep = depMap.get(key);
      if (!dep) {
        depMap.set(key, (dep = new Set()));
      }
      if (target === obj1) {
        dep.add(effect1);
      } else {
        dep.add(effect2);
      }
    }
    function trigger(target, key) {
      let depMap = depsMap.get(target);
      if (depMap) {
        const dep = depMap.get(key);
        if (dep) {
          dep.forEach((effect) => effect());
        }
      }
    }
    gather(obj1, "age");//收集依赖
    gather(obj2, "age");//收集依赖
    effect1();
    effect2();
    console.log(tom); //我叫sl,今年22岁
    console.log(joy); //我叫sl,今年23岁
    obj1.age = 30;
    obj2.age = 10;
    trigger(obj1, "age");
    trigger(obj2, "age");
    console.log(tom); //我叫sl,今年30岁
    console.log(joy); //我叫sl,今年31岁
どの点が最適化できるかを見てみましょう

上記に依存するコレクション収集と関数更新通知トリガーは手動で収集され、毎回更新がトリガーされます。

Proxy

を自動的に収集してトリガーする方法はありますか? ##reactive を実装する #最初に reactive 関数を作成します

function reactive(target) {
  const handle = {
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(receiver,key) // 设置值时触发自动更新
    },
    get(target, key, receiver) {
      gather(receiver, key); // 访问时收集依赖
      return Reflect.get(target, key, receiver);
    },
  };
  return new Proxy(target, handle);
}

次に、reactive 関数を前のコードに適用します

var obj1 = reactive({ name: "tom", age: 22 });
var obj2 = reactive({ name: "joy", age: 23 });
var tom, joy;
effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}岁`);
effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}岁`);
var depsMap = new WeakMap();
function gather(target, key) {
  let depMap = depsMap.get(target);
  if (!depMap) {
    depsMap.set(target, (depMap = new Map()));
  }
  let dep = depMap.get(key);
  if (!dep) {
    depMap.set(key, (dep = new Set()));
  }
  if (target === obj1) {
    dep.add(effect1);
  } else {
    dep.add(effect2);
  }
}
function trigger(target, key) {
  let depMap = depsMap.get(target);
  if (depMap) {
    const dep = depMap.get(key);
    if (dep) {
      dep.forEach((effect) => effect());
    }
  }
}
effect1();
effect2();
console.log(tom); //我叫sl,今年22岁
console.log(joy); //我叫sl,今年23岁
obj1.age = 30;
obj2.age = 10;
console.log(tom); //我叫sl,今年30岁
console.log(joy); //我叫sl,今年31岁

次に、別の問題が発生します。 Gather 関数内にハードコーディングされた dep 追加関数があります

これを解決するにはどうすればよいですか?Effect 関数を書き換えます

let activeEffect = null
function effect(fn) {
  activeEffect = fn;
  activeEffect();
  activeEffect = null; // 执行后立马变成null
}
var depsMap = new WeakMap();
function gather(target, key) {
  // 避免例如console.log(obj1.name)而触发gather
  if (!activeEffect) return;
  let depMap = depsMap.get(target);
  if (!depMap) {
    depsMap.set(target, (depMap = new Map()));
  }
  let dep = depMap.get(key);
  if (!dep) {
    depMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect) //将函数添加到依赖
}
effect(effect1);
effect(effect2);

reactive も実装されており、ref も実装されています

ref

vue3 で ref を使用する方法

var name = ref('tom')
console.log(name.value) // tom
値を取得するには .value を使用する必要があります

function ref(name){
    return reactive(
        {
            value: name
        }
    )
}
const name = ref('tom');
console.log(name.value) //tom

完全なコード

var activeEffect = null;
function effect(fn) {
  activeEffect = fn;
  activeEffect();
  activeEffect = null; 
}
var depsMap = new WeakMap();
function gather(target, key) {
  // 避免例如console.log(obj1.name)而触发gather
  if (!activeEffect) return;
  let depMap = depsMap.get(target);
  if (!depMap) {
    depsMap.set(target, (depMap = new Map()));
  }
  let dep = depMap.get(key);
  if (!dep) {
    depMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect)
}
function trigger(target, key) {
  let depMap = depsMap.get(target);
  if (depMap) {
    const dep = depMap.get(key);
    if (dep) {
      dep.forEach((effect) => effect());
    }
  }
}
function reactive(target) {
  const handle = {
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(receiver, key); // 设置值时触发自动更新
    },
    get(target, key, receiver) {
      gather(receiver, key); // 访问时收集依赖
      return Reflect.get(target, key, receiver);
    },
  };
  return new Proxy(target, handle);
}
function ref(name){
    return reactive(
        {
            value: name
        }
    )
}

推奨される学習: 「
最新の 5 つの vue.js ビデオ チュートリアルの選択

>>

以上がvue3の応答原理とAPIの書き方の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。