Rumah > Artikel > hujung hadapan web > vue3 penyelesaian tindak balas nilai asal dan cara menyelesaikan masalah kehilangan tindak balas
ref adalah untuk menyelesaikan masalah yang proksi tidak boleh proksi secara langsung nilai asal. Mari kita lihat penggunaan ref:
const name = ref('小黑子')
Bagaimana ref dilaksanakan? Malah, ia adalah untuk "membungkus" nilai asal dengan objek. Mari kita lihat pelaksanaan ref:
function ref(val){ // 使用对象包裹原始值 const wrapper = { value:val } // 利用 reactive 将对象变成响应式数据 return reactive(wrapper) }
ref Pelaksanaannya semudah itu.
ref melakukan dua perkara ini sebagai tindak balas kepada nilai asal:
1 Gunakan objek untuk membungkus nilai asal.
2. Gunakan reaktif untuk menukar objek pakej menjadi data responsif.
Kami menggunakan ref untuk mencipta objek responsif, tetapi bagaimana kita membezakan sama ada objek adalah objek biasa atau objek ref? Jadi isref kami muncul.
Mari kita lihat penggunaannya:
const name = ref('cj') console.log(isRef(name)); // true
Jadi apakah prinsip pelaksanaannya? Pelaksanaan utama masih dalam ref API Mari kita lihat pada kod pelaksanaan khusus:
function ref(val){ const wrapper = { value:val } Object.defineProperty(warpper,'__v_isRef',{ value:true }) return reactive(wrapper) }
Ternyata ia menambahkan atribut yang tidak boleh dikira dan tidak boleh ditulis pada objek pakej di dalam ref, dan nilainya adalah benar. Dengan cara ini kita boleh menyemak atribut untuk menentukan sama ada ia adalah rujukan.
function isRef(val) { return val.__v_isRef ?? false }
Apakah kehilangan tindak balas? Kehilangan tindak balas bermakna data responsif tidak dijawab. Mari lihat kod di bawah:
const obj = reactive({foo:1,bar:2}) const {foo,bar} = obj obj.foo++ // foo不会改变,还是 1
Respons obj di atas telah hilang, jadi pemaparan semula tidak akan dicetuskan. Mengapa ini berlaku? Malah, kerana penggunaan tugasan struktur, pengendali pengembangan juga akan membatalkannya.
const obj = reactive({foo:1,bar:2}) const newObj = {...obj} obj.foo++ // newObj.foo不会改变,还是 1
Ini bersamaan dengan mentakrifkan semula data baharu, yang bukan lagi data respons asal dan secara semula jadi tidak mempunyai keupayaan responsif.
toRef adalah untuk menyelesaikan masalah kehilangan tindak balas. Mari kita lihat pelaksanaannya:
function toRef(obj,key) { const wrapper = { get value() { return obj[key] }, set value(val) { obj[key] = val } } Object.defineProperty(wrapper,'__v_isRef',{ value:true }) return wrapper }
Pass dalam dua parameter, yang pertama ialah data responsif dan yang kedua ialah kunci obj.
Bahagian pertama ialah menyediakan dan mengisytiharkan objek terlebih dahulu menetapkan atribut get value Apabila mengakses nilai toRef, nilai atribut yang sepadan dengan data responsif yang masuk dikembalikan, dan kemudian Set dengan atribut nilai digunakan untuk menetapkan nilai toRef dan mengemas kini nilai atribut yang sepadan dengan data responsif dengan set nilai baharu. Dalam erti kata lain, objek yang dikembalikan oleh toRef masih merupakan data responsif yang digunakan.
Bahagian kedua digunakan untuk menetapkan data yang dikembalikan menjadi data rujukan. Oleh kerana data yang dikembalikan oleh toRef adalah serupa dengan data rujukan, ia secara langsung dianggap sebagai data rujukan demi penyatuan.
Bahagian ketiga ialah mengembalikan objek atribut yang diisytiharkan sepadan dengan data responsif
Dengan cara ini toRef menyelesaikan masalah kehilangan tindak balas.
toRefs adalah untuk menyahbina keseluruhan objek responsif dan menjadikannya responsif. Kod pelaksanaan adalah seperti berikut:
function toRefs() { const ret = {} for (const key in obj) { ret[key] = toRef(obj,key) } return ret }
Gunakan gelung for untuk menukar atribut satu demi satu. Sekarang mari kita lihat penggunaan:
const obj = reactive({foo:1,bar:2}) const {foo,bar} = toRefs(obj) obj.foo++ // foo.value变为2了
Apabila atribut ialah nilai bukan asal, ia masih boleh bertindak balas selepas penyahbinaan
const obj = reactive({foo:{age:18},bar:2}) const {foo,bar} = obj obj.foo.age++ // foo.age变为2了 obj.bar++ // bar没有改变,还是1<.>Kenapa ni? Sebabnya sebenarnya sangat mudah, kerana nilai bukan asal diberikan alamat rujukan, yang bermaksud bahawa pembolehubah yang dimusnahkan sebenarnya masih menunjuk kepada atribut data responsif asal. Nilai asal adalah tugasan yang mudah dan tidak akan bertindak balas.
reactive 响应数据重新赋值后不再响应,ref 响应数据赋值后依然响应 let obj1 = reactive({foo:1,bar:2}) let obj2 = ref({foo:1,bar:2}) // 假如 obj1 与 obj2 直接展示在页面上 obj1 = {boo:2,far:3} // 页面 obj1 还是 {foo:1,bar:2} obj2.value = {boo:2,far:3} // 页面 obj2 变为 {boo:2,far:3} 了Apakah sebabnya? Respons penugasan semula reaktif hilang, iaitu, objek baharu ditetapkan semula, dan ia secara semula jadi menjadi data biasa dan tidak lagi bertindak balas. Dan ref masih boleh bertindak balas kerana ref ditetapkan secara dalaman. Kodnya adalah seperti berikut:
function ref(val){ const wrapper = { value:val set value(val) { // isObject 这里代表判断是否是非原始值的一个方法 value = isObject(val) === 'Object' ? reactive(val) : val } } Object.defineProperty(warpper,'__v_isRef',{ value:true }) return reactive(wrapper) }Kami faham sebenarnya, ref menentukan sama ada nilai baharu dalam set adalah nilai bukan asal, hubungi reaktif untuk mengubahnya menjadi data responsif. 4. Unref secara automatik mengalih keluar ref Apabila kami menggunakan data ref responsif, kami sentiasa merasakan bahawa .value diperlukan untuk mendapatkan nilai, yang meningkatkan beban mental pengguna. Adakah mungkin untuk mengakses nilai secara terus dan bukannya menggunakan .value? Dengan cara ini, anda tidak perlu risau sama ada data tertentu adalah data rujukan atau sama ada anda perlu mendapatkan nilai melalui atribut nilai. Di sinilah unref kami berperanan. unref melaksanakan keupayaan untuk mengalih keluar ref secara automatik bermakna jika atribut baca ialah ref, nilai atribut nilai yang sepadan dengan ref akan dikembalikan terus. Mari kita lihat pelaksanaan unref:
function unref(target) { return new Proxy(target,{ get(target,key,receiver) { const value = Reflect.get(target,key,receiver) return value.__v_isRef ? value.value : value }, set(target,key,newValue,receiver) { const value = target[key] if (value.__v_isRef) { value.value = newValue return true } return Reflect.set(target,key,newValue,receiver) } }) }Kami mendapati bahawa unref secara dalaman menggunakan Proksi untuk memproksi objek sasaran, menerima objek sebagai parameter dan mengembalikan objek proksi bagi objek. Apabila kami mengakses data unref, get catcher dicetuskan, dan kemudian catcher secara dalaman menentukan sama ada objek masuk ialah objek ref, dan jika ya, ia mengembalikan nilai .ref secara langsung. Jika tidak, objek proksi dikembalikan secara langsung. Apabila nilai ditetapkan kepada objek proksi yang dikembalikan oleh unref, penangkap set dicetuskan Jika objek proksi ialah ref, nilai baharu yang perlu ditetapkan ditetapkan kepada .value proses tugasan dilakukan secara langsung. Peluasan PengetahuanSelepas kami menggunakan ref untuk mencipta data responsif dan memaparkannya dalam templat, mengapa tidak menggunakan .value?
{{ name }}
其实原因很简单,在组件 setup 中声明的 ref 响应式数据会传递给 unref 函数进行处理。所以在模板中访问 ref 的值,无需通过 value 属性来访问。
我们使用的 reactive 其实也是有 自动脱 ref 功能的,看一下下方例子:
const count = ref(0) const obj = reactive({conut}) obj.count // 0
我们可以看见 obj.count 是一个 ref 响应式数据。在 count 外层包裹一层对象,再传递给 reactive 后,再访问 obj.count 时就不需要再通过 value 属性访问值了。
也正是因为 reactive 内部也同样实现了自动脱 ref 的能力。
Atas ialah kandungan terperinci vue3 penyelesaian tindak balas nilai asal dan cara menyelesaikan masalah kehilangan tindak balas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!