系列文章目錄
創作不易 拒絕白嫖 點個贊呗
關注我,帶你走進前端的世界!!!
是什麼
- 将基礎資料–>響應式資料 ==> 把值類型的資料包裝程式設計響應式的引用類型的資料
- 函數
- 通過傳回值的
屬性擷取響應式的值 ,修改也需要對 .value進行修改。value
-
擷取元素
在Vue2.x通過給元素添加ref=‘xxx’,,然後使用refs.xxx的方式來擷取元素
在Vue3.x中我們也可以通過ref來擷取元素
用法
建立變量
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value = 2
console.log(count.value) // 2
ref也可以接收複雜的資料類型作為參數,隻是建議不使用ref處理複雜類型資料。
在單檔案元件中,不必寫value,因為setup方法會自動解析
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++">Increment count</button>
</div>
</template>
<template>
<div ref="refDiv">我是div</div>
</template>
<script>
import {ref, onMounted} from 'vue';
export default {
name: 'App',
setup() {
let refDiv = ref(null);
onMounted(()=>{
console.log('onMounted',refDiv.value);
// onMounted <div style="color: red;">我是div</div>
refDiv.value.style.color="red"
// 字型顔色變成紅色
});
// setup 生命周期在mounted之前
console.log(box.value);
// null
return {box};
}
}
</script>
ref和reactive的差別
ref是把值類型添加一層包裝,使其變成響應式的引用類型的值。
reactive 則是引用類型的值變成響應式的值。
是以兩者的差別隻是在于是否需要添加一層引用包裝
本質上
ref(0) --> reactive( { value:0 })
注意點
ref 對于 基本類型
ref-建立出來的資料和以前無關(複制) 與js中的基本類型表現一緻
let a = 1;
let aRef = ref(a);
console.log(a, aRef.value); //1 1
a = 2;
console.log(a, aRef.value);// 2 1
aRef.value = 3;
console.log(a, aRef.value);// 2 3
ref 對于 引用資料類型
ref-建立出來的資料和以前相關(引用) 與js中的引用資料類型表現一緻
let obj = { name: "1" };
let stateRef = ref(obj);
console.log("obj", obj.name);
console.log("ref", stateRef.value.name);
// obj 1
// ref 1
stateRef.value.name = '2';
console.log("obj", obj.name);
console.log("ref", stateRef.value.name);
// obj 2
// ref 2
obj.name='3'
console.log("obj", obj.name);
console.log("ref", stateRef.value.name);
// obj 3
// ref 3
相關API
isRef
作用
判斷是都是ref對象
其實内部是判斷資料對象上是否包含屬性并且其值為
__v_isRef
。
true
const a = ref(a)
const b = 'b'
cosnole.log(isRef(a)) // true
console.log(isRef(b)) // false
unref
如果參數為
ref
,則傳回内部值,否則傳回參數本身。這是
val = isRef(val) ? val.value : val
const temp=ref(3)
const newTemp = unref(1) // newTemp 確定現在是數字類型 3
const a = unref(1) // a 確定現在是數字類型 1
toRef
将引用資料類型轉換為ref資料類型
将reavtive資料類型轉換為ref資料類型
引用資料類型
let obj = { name: "syl", age: "123" };
let stateToref = toRef(obj, "name"); // 将name拿出來
stateToref.value = "zs";
console.log("obj", obj.name);
console.log("ref", stateToref.value);
// obj zs
// ref zs
obj.name = "ls";
console.log("obj", obj.name);
console.log("ref", stateToref.value);
// obj ls
// ref ls
reactive資料類型
let obj = reactive({ name: "syl", age: "123" });
let stateToref = toRef(obj, "name"); // 将name拿出來
stateToref.value = "zs";
console.log("obj", obj.name);
console.log("ref", stateToref.value);
// obj zs
// ref zs
obj.name = "ls";
console.log("obj", obj.name);
console.log("ref", stateToref.value);
// obj ls
// ref ls
資料發生改變, 界面也不會自動更新
案例1
<p>toref----------{{ stateToref }}</p> // 這裡顯示的是zs
let obj = { name: "syl" };
let stateToref = toRef(obj, "name");
stateToref.value = "zs";
console.log("obj", obj.name);
console.log("ref", stateToref.value);
// obj zs
// ref zs
案例2
<p>toref----------{{ stateToref }}</p>
<button @click="changeToref">changeToref</button>
let obj = { name: "syl" };
let stateToref = toRef(obj, "name");
function changeToref() {
stateToref.value = "ls";
console.log("obj", obj.name);
console.log("toref", stateToref.value);
}
// 點選changeToref,頁面沒有任何變化,仍然顯示syl
// console的結果是
// obj ls
// toref ls
一個有意思的例子
<p>toref----------{{ stateToref }}</p>
<p>temp----------{{ temp }}</p>
<button @click="changeToref">changeToref</button>
let obj = { name: "syl" };
let stateToref = toRef(obj, "name");
let temp = ref("我是ref");
function changeToref() {
temp.value = "我是ref我改變啦!";
stateToref.value = "ls";
}
// 點選按鈕,頁面的ui從
toref----------syl
temp----------我是ref
// 變成
oref----------ls
temp----------我是ref我改變啦!
這裡可以看到ref觸發了ui更新,導緻toref的值也進行了更新
其實不把這個ref的更新寫到這個函數裡面,比如建立函數,也會導緻這個現象
這個現象對其他函數也出現,例如shallowRef。
toRefs
批量轉換。将響應式對象轉換為普通對象,會将傳入對象的每個屬性處理為 ref 的值。
官網例子
當從合成函數傳回響應式對象時,
toRefs
非常有用,這樣消費元件就可以在不丢失響應性的情況下對傳回的對象進行分解/擴散:
function useFeatureX() {
const state = reactive({
foo: 1,
bar: 2
})
// 傳回時轉換為ref
return toRefs(state)
}
export default {
setup() {
// 可以在不失去響應性的情況下破壞結構
const { foo, bar } = useFeatureX()
return {
foo,
bar
}
}
}
shallowRef 與triggerRef
shallowRef
建立一個 ref,它跟蹤自己的
.value
更改,但不會使其值成為響應式的。也就是對value進行更新
才會觸發頁面的更新,但是如果是一個引用資料類型,隻對改引用資料進行值的修改,則不會觸發更新。
案例- 基本資料類型
<p>{{ state1 }}</p>
<button @click="myFn1">基本資料類型</button>
let state1 = shallowRef(1);
function myFn1() {
state1.value = 2;
}
// 點選按鈕,頁面會顯2
// 也就是對value進行修改可以觸發頁面更新
案例- 引用資料類型
<p>{{ state.a }}</p>
<p>{{ state.b.c }}</p>
<button @click="myFn1">引用資料類型-直接修改value</button>
<button @click="myFn2">引用資料類型-對資料進行修改</button>
let state = shallowRef({
a: "a",
b: {
c: "c",
},
});
function myFn1() {
state.value={
a: "a-new",
b: {
c: "c-new",
},
}
}
// 點選mufun1 頁面從
a
c
// 變成
a-new
c-new
// 由此可以看出直接對value進行修改可以觸發頁面更新
function myFn2() {
state.value.a = "1";
state.value.b.c = "1";
console.log(state.value.a , state.value.b.c )
}
// 點選mufun2 頁面仍然顯示
a
c
// console的結果是1 1
triggerRef
通常與shallowRef 一起使用,主要是主動觸發界面更新的
參數是ref變量
<p>{{ state.a }}</p>
<p>{{ state.b.c }}</p>
<button @click="myFn2">使用triggerRef</button>
let state = shallowRef({
a: "a",
b: {
c: "c",
},
});
function myFn2() {
state.value.a = "1";
state.value.b.c = "1";
triggerRef(state);
}
// 點選mufun2 頁面變成
1
1
customRef
自定義ref
傳回一個ref對象,可以顯式地控制依賴追蹤和觸發響應
<template>
<div>
<p>{{age}}</p>
<button @click="myFn">按鈕</button>
</div>
</template>
import {ref, customRef} from 'vue';
function myRef(value) {
return customRef((track, trigger)=>{
return {
get(){
track(); // 告訴Vue這個資料是需要追蹤變化的
console.log('get', value);
return value;
},
set(newValue){
console.log('set', newValue);
value = "我的年齡==="+newValue;
trigger(); // 告訴Vue觸發界面更新
}
}
});
}
setup() {
// let age = ref(18); // reactive({value: 18})
let age = myRef(18);
function myFn() {
age.value += 1;
}
return {age, myFn}
}
}
// 頁面顯示的是18
// 點選button按鈕後,變成了我的年齡===19
// 注意點:
// 不能在get方法中發送網絡請求