Vue 3 Composition API: Ref atau Reactive





Sekarang, saat saya menulis artikel ini, kita semakin dekat dengan rilis Vue 3. Menurut saya, hal yang paling menarik adalah mengamati bagaimana pengembang lain akan melihat dan menggunakannya. Saya memiliki kesempatan untuk bermain-main dengan Vue 3 dalam beberapa bulan terakhir, tetapi saya tahu ada yang belum.



Inovasi paling signifikan dalam versi baru adalah API Komposisi. Ini memberikan pendekatan alternatif untuk membuat komponen dan sangat berbeda dari API Opsi yang ada. Tidak sulit bagi saya untuk mengakui bahwa ketika saya pertama kali melihatnya, saya tidak memahaminya. Namun, saat diterapkan, makna mulai muncul. Anda mungkin tidak menulis ulang seluruh aplikasi Anda menggunakan API Komposisi, tetapi artikel ini akan memberi Anda kesempatan untuk memikirkan tentang cara kerja pembuatan dan komposisi komponen.







Saya telah melakukan beberapa presentasi baru-baru ini, dan pertanyaan umum adalah kapan saya menggunakan Ref dan ketika saya menggunakan Reactive untuk menyatakan properti reaktif. Saya tidak memiliki jawaban yang bagus dan membutuhkan waktu beberapa minggu untuk menemukan jawabannya, dan artikel ini adalah hasil dari penelitian saya.



Terlebih lagi, saya ingin mencatat bahwa di atas adalah pendapat saya dan mohon jangan berpikir bahwa hal itu perlu dilakukan “hanya dengan cara ini dan bukan sebaliknya”. Saya berencana untuk menggunakan Ref dan Reactive dengan cara ini sampai seseorang menyarankan sebaliknya, atau sampai saya menemukan pendekatan yang lebih baik untuk diri saya sendiri. Saya pikir perlu beberapa waktu untuk memahami teknologi baru, dan kemudian teknik yang telah terbukti dapat muncul.



Sebelum melanjutkan, saya berasumsi bahwa Anda setidaknya telah membiasakan diri secara singkat dengan API komposisi dan memahami apa isinya. Artikel ini berfokus pada perbedaan antara ref dan reaktif, bukan mekanisme komposisi API.



Reaktivitas Vue 2



Untuk mempercepat Anda, saya akan melihat sekilas cara membuat properti reaktif dalam aplikasi Vue 2. Saat Anda ingin Vue 2 melacak perubahan properti, Anda perlu mendeklarasikannya di objek yang dikembalikan oleh fungsi data.



<template>
  <h1>{{ title }}</h1>
</template>

<script>
  export default {
    data() {
      return {
        title: "Hello, Vue!"
      };
    }
  };
</script>


Di bawah kap Vue 2, Object.defineProperty () dipanggil untuk setiap properti untuk membuat pengambil dan penyetel untuk melacak perubahan. Ini adalah penjelasan proses yang paling sederhana dan saya ingin menyampaikan idenya: tidak ada keajaiban di dalamnya. Anda tidak dapat membuat properti reaktif di mana pun dan berharap Vue melacak perubahannya. Anda perlu menyetel properti reaktif dalam fungsi data.



REF dan REAKTIF



Saat bekerja dengan Options API, kita perlu mengikuti beberapa aturan saat mendeklarasikan properti reaktif, dan hal yang sama berlaku saat bekerja dengan Composition API. Anda tidak bisa begitu saja membuat properti dan mengharapkan reaktivitas. Dalam contoh berikut, saya telah mendeklarasikan properti title dan fungsi setup () mengembalikannya, sehingga membuatnya tersedia untuk template.



<template>
  <h1>{{ title }}</h1>
</template>

<script>
  export default {
    setup() {
      let title = "Hello, Vue 3!";
      return { title };
    }
  };
</script>




Ini akan berfungsi, tetapi properti judul tidak akan reaktif. Itu. jika seseorang mengubah judul, perubahan itu TIDAK akan tercermin di DPR. Misalnya, jika Anda mengubah judul setelah 5 detik, kode di bawah TIDAK akan mengubah Beranda.



<template>
  <h1>{{ title }}</h1>
</template>

<script>
  export default {
    setup() {
      let title = "Hello, Vue 3!";

      setTimeout(() => {
        title = "THIS IS A NEW TITLE";
      }, 5000);

      return { title };
    }
  };
</script>




Kita dapat mengimpor ref dan menggunakannya untuk membuat properti reaktif. Di bawah tenda, Vue 3 akan membuat Proxy .



<template>
  <h1>{{ title }}</h1>
</template>

<script>
  import { ref } from "vue";

  export default {
    setup() {
      const title = ref("Hello, Vue 3!");

      setTimeout(() => {
        //   ,   .value ...
        //   
        title.value = "New Title";
      }, 5000);

      return { title };
    }
  };
</script>




Saya ingin menjelaskan bahwa berbicara tentang Ref dan Reaktif, saya pikir ada dua kasus berbeda. Yang pertama adalah membuat komponen seperti pada contoh di atas dan Anda memerlukan properti reaktif. Yang kedua adalah saat Anda membuat fungsi yang memungkinkan komposisi digunakan dalam komponen dan fungsi. Kami akan membahas kedua skenario di artikel ini.



REF



Saat membuat properti tipe sederhana, ref () adalah pilihan pertama Anda. Ini bukan peluru perak, tapi itu layak untuk dimulai. Izinkan saya mengingatkan Anda tentang tujuh tipe primitif dalam JavaScript:



  • Tali
  • Jumlah
  • BigInt
  • Boolean
  • Simbol
  • Batal
  • Tidak terdefinisi




import { ref } from "vue";

export default {
  setup() {
    const title = ref("");
    const one = ref(1);
    const isValid = ref(true);
    const foo = ref(null);
  }
};




Pada contoh sebelumnya, judul kita berjenis String, jadi untuk membuat properti reaktif, kita pilih ref (). Jika kode di bawah ini menyebabkan Anda beberapa pertanyaan jangan khawatir, saya memiliki pertanyaan yang sama.



import { ref } from "vue";

export default {
  setup() {
    const title = ref("Hello, Vue 3!");

    setTimeout(() => {
      title.value = "New Title";
    }, 5000);

    return { title };
  }
};




Mengapa kita menggunakan const jika judulnya akan berubah? Mengapa tidak menggunakan let? Jika Anda mencetak judul ke konsol, Anda mungkin berharap melihat Hello, Vue 3!, Tetapi sebaliknya itu akan menampilkan sebuah objek:



{_isRef: true}
value: (...)
_isRef: true
get value: ƒ value()
set value: ƒ value(newVal)
__proto__: Object




Fungsi ref () akan mengambil argumen dan mengembalikan objek ref reaktif dan bisa berubah. Objek Ref memiliki satu properti, nilai, yang mengacu pada argumen. Ini berarti bahwa jika Anda ingin mendapatkan atau mengubah nilainya, Anda harus menggunakan title.value, dan karena ini adalah objek yang tidak akan berubah, saya mendeklarasikannya const.



Menelepon REF



Pertanyaan selanjutnya adalah mengapa kita tidak memanggil title.value dalam template?



<template>
  <h1>{{ title }}</h1>
</template>




Ketika Ref dikembalikan sebagai properti dalam konteks rendering (objek yang dikembalikan oleh fungsi setup ()) dan direferensikan dalam template, Ref secara otomatis mengembalikan nilai. Anda tidak perlu menambahkan .value dalam template.



Properti yang dihitung bekerja dengan cara yang sama, di dalam fungsi setup () Anda menyebutnya sebagai .value.




REAKTIF



Kami baru saja melihat penggunaan ref () untuk menyetel reaktivitas properti pada tipe sederhana. Bagaimana jika kita ingin membuat objek reaktif? Kita masih bisa menggunakan ref (), tetapi di bawah kap Vue akan menggunakan reactive (), jadi saya akan tetap menggunakan reactive ().



Di sisi lain, reactive () tidak akan berfungsi dengan tipe primitif. Fungsi reactive () mengambil objek dan mengembalikan proxy reaktif dari aslinya. Ini sama dengan .observable () di Vue 2, dan nama fungsi ini telah diubah untuk menghindari kebingungan dengan observable di RxJS.



import { reactive } from "vue";

export default {
  setup() {
    const data = reactive({
      title: "Hello, Vue 3"
    });

    return { data };
  }
};




Perbedaan utamanya adalah bagaimana kita merujuk ke objek reaktif di template. Pada contoh sebelumnya, data adalah obyek yang mengandung properti title. Anda perlu merujuknya di template seperti ini - data.title:



<template>
  <h1>{{ data.title }}</h1>
</template>

<script>
  import { ref } from "vue";

  export default {
    setup() {
      const data = ref({
        title: "Hello, Vue 3"
      });

      return { data };
    }
  };
</script>




Perbedaan antara REF dan REACTIVE dalam sebuah komponen



Berdasarkan apa yang telah kita bahas, jawabannya tampaknya menyarankan sendiri? Kami menggunakan ref () untuk tipe sederhana, dan reaktif () untuk objek. Ketika saya mulai membuat komponen, ternyata tidak selalu demikian, dan dokumentasinya mengatakan:



Perbedaan antara menggunakan ref dan reaktif dapat, sampai batas tertentu, sebanding dengan cara Anda menulis logika program standar di JavaScript.




Saya merenungkan kalimat ini dan sampai pada kesimpulan berikut. Saat aplikasi berkembang, saya mendapatkan properti berikut:



export default {
  setup() {
    const title = ref("Hello, World!");
    const description = ref("");
    const content = ref("Hello world");
    const wordCount = computed(() => content.value.length);

    return { title, description, content, wordCount };
  }
};




Dalam JavaScript, saya memahami bahwa ini semua adalah properti halaman saya. Dalam kasus ini, saya akan mengelompokkan mereka menjadi objek halaman, mengapa tidak melakukan hal yang sama sekarang.



<template>
  <div class="page">
    <h1>{{ page.title }}</h1>
    <p>{{ page.wordCount }}</p>
  </div>
</template>

<script>
  import { ref, computed, reactive } from "vue";

  export default {
    setup() {
      const page = reactive({
        title: "Hello, World!",
        description: "",
        content: "Hello world",
        wordCount: computed(() => page.content.length)
      });

      return { page };
    }
  };
</script>




Ini adalah pendekatan saya terhadap Ref atau Reaktif, tetapi akan sangat baik jika Anda memiliki pendapat. Apakah kamu melakukan hal yang sama? Mungkin ini bukan pendekatan yang tepat? Tolong beri komentar anda.



Logika komposisi



Anda tidak bisa salah saat menggunakan ref () atau reactive () di komponen Anda. Kedua fungsi tersebut akan membuat data reaktif, dan jika Anda memahami cara mengaksesnya di fungsi setup () dan template Anda, tidak ada masalah.



Saat Anda mulai menulis fungsi komposisi, Anda perlu memahami perbedaannya. Saya menggunakan contoh dari dokumentasi RFC, karena beberapa menggambarkan nuansanya dengan baik.



Anda perlu membuat logika untuk melacak posisi mouse. Anda juga harus dapat menggunakan logika yang sama ini di semua komponen saat diperlukan. Anda membuat fungsi komposisi yang melacak koordinat x dan y, lalu mengembalikannya ke kode klien.



import { ref, onMounted, onUnmounted } from "vue";

export function useMousePosition() {
  const x = ref(0);
  const y = ref(0);

  function update(e) {
    x.value = e.pageX;
    y.value = e.pageY;
  }

  onMounted(() => {
    window.addEventListener("mousemove", update);
  });

  onUnmounted(() => {
    window.removeEventListener("mousemove", update);
  });

  return { x, y };
}




Jika Anda ingin menggunakan logika ini dalam sebuah komponen dan memanggil fungsi ini, hancurkan objek yang dikembalikan lalu kembalikan koordinat x dan y ke templat.



<template>
  <h1>Use Mouse Demo</h1>
  <p>x: {{ x }} | y: {{ y }}</p>
</template>

<script>
  import { useMousePosition } from "./use/useMousePosition";

  export default {
    setup() {
      const { x, y } = useMousePosition();
      return { x, y };
    }
  };
</script>




Ini akan berhasil, tetapi jika, setelah melihat fungsinya, Anda memutuskan untuk memfaktor ulang dan mengembalikan objek posisi alih-alih x dan y:



import { ref, onMounted, onUnmounted } from "vue";

export function useMousePosition() {
  const pos = {
    x: 0,
    y: 0
  };

  function update(e) {
    pos.x = e.pageX;
    pos.y = e.pageY;
  }

  // ...
}




Masalah dengan pendekatan ini adalah klien fungsi komposisi harus selalu memiliki referensi ke objek yang dikembalikan agar reaktivitas tetap ada. Ini berarti kita tidak dapat merusak objek atau menerapkan operator penyebaran:



//  
export default {
  setup() {
    //  !
    const { x, y } = useMousePosition();
    return {
      x,
      y
    };

    //  !
    return {
      ...useMousePosition()
    };

    //     
    //   `pos`  ,      x  y : `pos.x`  `pos.y`
    return {
      pos: useMousePosition()
    };
  }
};




Tetapi ini tidak berarti bahwa kita tidak dapat menggunakan reaktif dalam kasus ini. Ada fungsi toRefs () yang mengubah objek reaktif menjadi objek sederhana, yang masing-masing propertinya merupakan ref dari properti terkait dari objek aslinya.



function useMousePosition() {
  const pos = reactive({
    x: 0,
    y: 0
  });

  // ...
  return toRefs(pos);
}

// x & y  ref!
const { x, y } = useMousePosition();




Jadi, ada beberapa aspek yang perlu diperhatikan saat membuat fungsi komposisi. Jika Anda memahami cara kerja kode klien dengan fungsi Anda, maka semuanya akan baik-baik saja.



TOTAL



Ketika saya pertama kali mulai menggunakan Composition API, saya bingung dengan pertanyaan kapan harus menerapkan ref () dan kapan harus reaktif (). Mungkin saya masih belum melakukannya dengan benar, dan sampai seseorang memberi tahu saya hal ini, saya akan tetap menggunakan pendekatan ini. Semoga membantu memperjelas beberapa masalah, dan ingin mendengar tanggapan Anda.



Selamat membuat kode



All Articles