Vue3入門到精通 --ref 以及 ref相關(guān)函數(shù)

傳送門

Vue3入門到精通-setup
Vue3入門到精通 -reactive 以及reactive相關(guān)函數(shù)

ref 以及 ref相關(guān)函數(shù)
\color{#FF8C00}{\rm\large{是什么}}
  • 將基礎(chǔ)數(shù)據(jù) --> 響應式數(shù)據(jù) == 把值類型的數(shù)據(jù)包裝編程響應式的引用類型的數(shù)據(jù)。
  • 函數(shù)
  • 通過返回值的value屬性獲取響應式的值,修改也需要對.value進行修改。
  • 獲取元素
  • 在Vue2.x通過給元素添加 ref ='XXX',然后使用refs.xxx的方式來獲取元素。
  • 在VUe3.x中我們也可以通過ref來獲取元素。
\color{#FF8C00}{\rm\large{用法}}
創(chuàng)建變量
import { ref } from 'vue'
const count = ref(0)
console.log(count.value)  // 0
count.value = 2
console.log(count.value)  // 2  

\color{#B22222}{\rm\small{ref也可以接收復雜的數(shù)據(jù)類型作為參數(shù),只是建議不使用ref處理復雜類型數(shù)據(jù)。}}

在單文件組件中,不必寫value,因為setup方法會自動解析。
<template>
  <div>
    <span>{{ count }}</span>
    <button @click="count ++">Increment count</button>
  </div>
</template>

\color{#FF8C00}{\rm\large{獲取元素}}
<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(refDiv.value);
        // null

        return {refDiv};
    }
}
</script>

\color{#FF8C00}{\rm\large{ref}}?和?\color{#FF8C00}{\rm\large{reactive}}?區(qū)別
  • ref是把值類型添加一層包裝,使其變成響應式的引用類型的值。
  • reactive 則是將引用類型的值變成響應式的值。
  • \color{#B22222}{\rm\small{區(qū)別}}: 是否需要添加一層引用包裝。
  • 本質(zhì)上: ref(0) 等價于 reactive({value:0})
\color{#DC143C}{\rm\large{注意點}}
ref 對于 \color{#4169E1}{\rm\small{基本類型}}
  • ref - 創(chuàng)建出來的數(shù)據(jù) 和以前無關(guān)(復制)與js中的 基本類型 表現(xiàn)一致
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 對于 \color{#4169E1}{\rm\small{引用數(shù)據(jù)類型}}
  • ref-創(chuàng)建出來的數(shù)據(jù)和以前相關(guān)(引用) 與js中的 引用數(shù)據(jù)類型 表現(xiàn)一致
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

相關(guān)API
\color{#FF8C00}{\rm\large{isRef}}
作用
  • 判斷是否都是ref對象
  • 其實內(nèi)部是判斷數(shù)據(jù)對象上是否包含__v_isRef 屬性并且其值為 true。
用法
const a = ref(a)
const b = 'b'
cosnole.log(isRef(a)) // true
console.log(isRef(b)) // false

\color{#FF8C00}{\rm\large{unref}}
  • 如果參數(shù)為 ref,則返回內(nèi)部值,否則返回參數(shù)本身。這是 val = isRef(val) ? val.value : val。
 // isRef 判斷是否為ref對象
 const info = ref({name :'名字',info:{age:18,height:1111,}})
 const infos = {name :'名字',info:{age:18,height:1111, }}
 console.log(isRef(info)) // true
 console.log(isRef(infos)) // false

 console.log(unref(info)) // Proxy {name: '名字', info: {…}}
 console.log(unref(infos))//       {name: '名字', info: {…}}

  • isRef(info) ? info.value : 'info' 等同unref(info)
\color{#FF8C00}{\rm\large{toRef}}
作用
  • 引用數(shù)據(jù)類型 轉(zhuǎn)換為 ref 數(shù)據(jù)類型。
  • 將 reactive 數(shù)據(jù)類型轉(zhuǎn)換為 ref 數(shù)據(jù)類型。
用法
引用數(shù)據(jù)類型
 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 數(shù)據(jù)類型
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

\color{#FF6347}{\rm\small{注意點: 數(shù)據(jù)發(fā)生改變, 界面也不會自動更新}}

\color{#FF8C00}{\rm\large{案例分析}}
案例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的結(jié)果是
// 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觸發(fā)了ui更新,導致toref的值也進行了更新

其實不把這個ref的更新寫到這個函數(shù)里面,比如新建函數(shù),也會導致這個現(xiàn)象

這個現(xiàn)象對其他函數(shù)也出現(xiàn),例如shallowRef。

\color{#FF8C00}{\rm\large{toRefs}}
作用

批量轉(zhuǎn)換。將響應式對象轉(zhuǎn)換為普通對象,會將傳入對象的每個屬性處理為 ref 的值。

官方例子
  • 當從合成函數(shù)返回響應式對象時,toRefs 非常有用,這樣消費組件就可以在不丟失響應性的情況下對返回的對象進行分解/擴散:
function useFeatureX() {
const state = reactive({
  foo: 1,
  bar: 2
})
// 返回時轉(zhuǎn)換為ref
return toRefs(state)
}

export default {
  setup() {
    // 可以在不失去響應性的情況下破壞結(jié)構(gòu)
    const { foo, bar } = useFeatureX()

    return {
      foo,
      bar
    }
  }
}

\color{#FF8C00}{\rm\large{shallowRef}}\color{#FF8C00}{\rm\large{triggerRef}}

創(chuàng)建一個 ref,它跟蹤自己的 \color{#FF8C00}{\rm\small{.value}} 更改,但不會使其值成為響應式的。也就是對 \color{#FF8C00}{\rm\small{value}}進行更新
才會觸發(fā)頁面的更新,但是如果是一個引用數(shù)據(jù)類型,只對改引用數(shù)據(jù)進行值的修改,但不會觸發(fā)更新。

\color{#FF8C00}{\rm\small{案例一}} 基本數(shù)據(jù)類型
<p>{{ state1 }}</p>
<button @click="myFn1">基本數(shù)據(jù)類型</button>

let state1 = shallowRef(1);
function myFn1() {
  state1.value = 2;
}
// 點擊按鈕,頁面會顯2
// 也就是對value進行修改可以觸發(fā)頁面更新

\color{#FF8C00}{\rm\small{案例二}} 引用數(shù)據(jù)類型
<p>{{ state.a }}</p>
<p>{{ state.b.c }}</p>
<button @click="myFn1">引用數(shù)據(jù)類型-直接修改value</button>
<button @click="myFn2">引用數(shù)據(jù)類型-對數(shù)據(jù)進行修改</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進行修改可以觸發(fā)頁面更新

function myFn2() {
    state.value.a = "1";
    state.value.b.c = "1";
    console.log(state.value.a , state.value.b.c )
}
// 點擊mufun2 頁面仍然顯示
a
c
// console的結(jié)果是1 1

\color{#FF8C00}{\rm\large{triggerRef}}

通常與shallowRef 一起使用,主要是主動觸發(fā)界面更新的
參數(shù)是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

\color{#FF8C00}{\rm\large{customRef}}

自定義ref
返回一個ref對象,可以顯式地控制依賴追蹤和觸發(fā)響應

<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這個數(shù)據(jù)是需要追蹤變化的
        console.log('get', value);
        return value;
      },
      set(newValue){
        console.log('set', newValue);
        value = "我的年齡==="+newValue;
        trigger(); // 告訴Vue觸發(fā)界面更新
      }
    }
  });
}

  setup() {
    // let age = ref(18); // reactive({value: 18})
    let age = myRef(18);
    function myFn() {
      age.value += 1;
    }
    return {age, myFn}
  }
}

// 頁面顯示的是18
// 點擊button按鈕后,變成了我的年齡===19
// 注意點:
// 不能在get方法中發(fā)送網(wǎng)絡(luò)請求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容