Rumah  >  Artikel  >  hujung hadapan web  >  Apakah prinsip tindak balas Vue3

Apakah prinsip tindak balas Vue3

王林
王林ke hadapan
2023-05-24 17:55:231239semak imbas

Proksi

API teras Proksi bergantung pada prinsip reaktif Vue3 boleh digunakan untuk memintas beberapa operasi objek.

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

p.a; // 输出 --> get
p.a = 2; // 输出 --> set
"a" in p; // 输出 --> has
delete p.a; // 输出 --> deleteProperty

Seperti yang ditunjukkan dalam contoh di atas, kami menggunakan Proksi untuk memproksi akses harta, penetapan harta, dalam pengendali dan memadamkan operasi objek Obj dan melaksanakan output console.log.

Reflect

Reflect ialah API yang digunakan bersama dengan Proxy Apabila kami merampas operasi tertentu, jika kami perlu mencerminkan operasi ini, kami memerlukan Reflect API.

Memandangkan kami memintas operasi objek, fungsi operasi ini hilang Contohnya, mengakses atribut p.a sepatutnya mendapat nilai atribut, tetapi tidak akan ada hasil pada masa ini kita masih Jika kita ingin mempunyai fungsi sebelum pemintasan, kita perlu menggunakan Reflect untuk mencerminkan kembali.

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

Berikan contoh

Kami akan menggunakan contoh ini untuk menerangkan prinsip responsif Vue3 sepanjang teks berikut.

<div id="app"></div>

<script>
  // 创建一个响应式对象
  const state = reactive({ counter: 1 });

  // 立即运行一个函数,当响应式对象的属性发生改变时重新执行。
  effect(() => {
    document.querySelector("#app").innerHTML = state.counter;
  });

  // 2s 后视图更新
  setTimeout(() => {
    state.counter += 1;
  }, 2000);
</script>

Kami menggunakan reaktif untuk mencipta keadaan objek reaktif dan memanggil kaedah kesan, yang menerima fungsi kesan sampingan Perlaksanaan kesan akan segera memanggil fungsi kesan sampingan dan menetapkan state.counter kepada #app ; selepas dua saat, state.counter += 1. Pada masa ini, fungsi kesan sampingan kesan akan dilaksanakan semula dan halaman akan menjadi 2.

Proses pelaksanaan dalaman secara kasar seperti yang ditunjukkan dalam rajah di bawah:

Apakah prinsip tindak balas Vue3

  • Panggil reactive() untuk mengembalikan objek Proksi dan merampas operasi dapatkan dan tetapkan objek

  • Kaedah kesan panggilan (), state.counter hartanah akan diakses dan operasi dapatkan proksi akan dicetuskan.

  • Kaedah get akan memanggil track() untuk mengumpul kebergantungan; 🎜>

  • Kaedah yang ditetapkan akan memanggil trigger() untuk mengemas kini kebergantungan; mencari fungsi kesan sampingan kesan yang sepadan melalui objek (keadaan) dan atribut (coutner), dan kemudian laksanakannya semula.
  • reaktif

reaktif akan mengembalikan objek Proksi berikut

const reactive = (target) => {
  return new Proxy(target, {
    get(target, key, receiver) {
      const res = Reflect.get(target, key, receiver);

      track(target, key); // 收集依赖

      if (isObject(res)) {
        // 如果当前获取的属性值是一个对象,则继续将为此对象创建 Proxy 代理
        return reactive(res);
      }

      return res;
    },

    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 依赖更新
    },
  });
};

effect

let activeEffect;
function effect(fn) {
  const _effect = function reactiveEffect() {
    activeEffect = _effect;
    fn();
  };

  _effect();
}

Tentukan pembolehubah activeEffect global, yang menunjuk kepada fungsi kesan sampingan kesan yang sedang dilaksanakan dan memastikan ia dikemas kini. effect mencipta fungsi kesan sampingan dalaman untuk fn dan kemudian melaksanakannya dengan segera Pada masa ini, operasi get objek akan dicetuskan dan kaedah track() akan dipanggil.

effect(() => {
  // effect 的立即执行会访问 state.counter,触发了对象的 get 操作。
  document.querySelector("#app").innerHTML = state.counter;
});

track

track akan mencipta objek (keadaan) => atribut (counter) => kebergantungan kesan

const targetMap = new WeakMap();
function track(target, key) {
  if (!activeEffect) {
    return;
  }

  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }

  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }

  if (!dep.has(activeEffect)) {
    dep.add(activeEffect);
  }
}

Selepas pelaksanaan selesai, kita mendapat A struktur data seperti berikut:

[ // map 集合
  {
    key: {counter: 1} // state 对象,
    value: [ // map 集合
      {
        key: "counter",
        value: [ // set
          function reactiveEffect() {} // effect 副作用函数
        ],
      }
    ],
  },
];

Nota: Apabila kita memanggil kesan, fungsi kesan sampingan semasa akan diberikan kepada activeEffect global, jadi kita boleh mengaitkan kebergantungannya dengan betul pada masa ini.

cetus

Apabila kami menetapkan nilai kepada state.counter, operasi set objek proksi akan dicetuskan, dengan itu memanggil kaedah pencetus

setTimeout(() => {
  // 给 counter 属性赋值会触发 set 操作
  state.counter += 1;
}, 2000);
function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;

  const effects = depsMap.get(key);
  effects && effects.forEach((effect) => effect());
}

Atas ialah kandungan terperinci Apakah prinsip tindak balas Vue3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam