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ù) --> 響應(yīng)式數(shù)據(jù) == 把值類型的數(shù)據(jù)包裝編程響應(yīng)式的引用類型的數(shù)據(jù)都弹。
  • 函數(shù)
  • 通過(guò)返回值的value屬性獲取響應(yīng)式的值圾亏,修改也需要對(duì).value進(jìn)行修改豺憔。
  • 獲取元素
  • 在Vue2.x通過(guò)給元素添加 ref ='XXX',然后使用refs.xxx的方式來(lái)獲取元素允跑。
  • 在VUe3.x中我們也可以通過(guò)ref來(lái)獲取元素莽使。
\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也可以接收復(fù)雜的數(shù)據(jù)類型作為參數(shù)凑懂,只是建議不使用ref處理復(fù)雜類型數(shù)據(jù)腥椒。}}

在單文件組件中勾笆,不必寫value敌蚜,因?yàn)閟etup方法會(huì)自動(dòng)解析。
<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是把值類型添加一層包裝窝爪,使其變成響應(yīng)式的引用類型的值弛车。
  • reactive 則是將引用類型的值變成響應(yīng)式的值齐媒。
  • \color{#B22222}{\rm\small{區(qū)別}}: 是否需要添加一層引用包裝。
  • 本質(zhì)上: ref(0) 等價(jià)于 reactive({value:0})
\color{#DC143C}{\rm\large{注意點(diǎn)}}
ref 對(duì)于 \color{#4169E1}{\rm\small{基本類型}}
  • ref - 創(chuàng)建出來(lái)的數(shù)據(jù) 和以前無(wú)關(guān)(復(fù)制)與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 對(duì)于 \color{#4169E1}{\rm\small{引用數(shù)據(jù)類型}}
  • ref-創(chuàng)建出來(lái)的數(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對(duì)象
  • 其實(shí)內(nèi)部是判斷數(shù)據(jù)對(duì)象上是否包含__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對(duì)象
 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拿出來(lái)

 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拿出來(lái)

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{注意點(diǎn): 數(shù)據(jù)發(fā)生改變, 界面也不會(huì)自動(dòng)更新}}

\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);
}
// 點(diǎn)擊changeToref拷恨,頁(yè)面沒(méi)有任何變化,仍然顯示syl
// console的結(jié)果是
// obj ls
// toref ls

一個(gè)有意思的案例
<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";
}
// 點(diǎn)擊按鈕腕侄,頁(yè)面的ui從
toref----------syl
temp----------我是ref
// 變成
oref----------ls
temp----------我是ref我改變啦!

這里可以看到ref觸發(fā)了ui更新勒叠,導(dǎo)致toref的值也進(jìn)行了更新

其實(shí)不把這個(gè)ref的更新寫到這個(gè)函數(shù)里面兜挨,比如新建函數(shù),也會(huì)導(dǎo)致這個(gè)現(xiàn)象

這個(gè)現(xiàn)象對(duì)其他函數(shù)也出現(xiàn)眯分,例如shallowRef拌汇。

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

批量轉(zhuǎn)換。將響應(yīng)式對(duì)象轉(zhuǎn)換為普通對(duì)象,會(huì)將傳入對(duì)象的每個(gè)屬性處理為 ref 的值弊决。

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

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

    return {
      foo,
      bar
    }
  }
}

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

創(chuàng)建一個(gè) ref飘诗,它跟蹤自己的 \color{#FF8C00}{\rm\small{.value}} 更改与倡,但不會(huì)使其值成為響應(yīng)式的。也就是對(duì) \color{#FF8C00}{\rm\small{value}}進(jìn)行更新
才會(huì)觸發(fā)頁(yè)面的更新昆稿,但是如果是一個(gè)引用數(shù)據(jù)類型纺座,只對(duì)改引用數(shù)據(jù)進(jìn)行值的修改,但不會(huì)觸發(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;
}
// 點(diǎn)擊按鈕净响,頁(yè)面會(huì)顯2
// 也就是對(duì)value進(jìn)行修改可以觸發(fā)頁(yè)面更新

\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ù)類型-對(duì)數(shù)據(jù)進(jìn)行修改</button>

let state = shallowRef({
  a: "a",
  b: {
      c: "c",
  },
});

function myFn1() {
    state.value={
        a: "a-new",
        b: {
            c: "c-new",
        },
    }
}
// 點(diǎn)擊mufun1 頁(yè)面從
a
c
// 變成
a-new
c-new
// 由此可以看出直接對(duì)value進(jìn)行修改可以觸發(fā)頁(yè)面更新

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

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

通常與shallowRef 一起使用喳瓣,主要是主動(dòng)觸發(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);
}
// 點(diǎn)擊mufun2 頁(yè)面變成
1
1

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

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

<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這個(gè)數(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}
  }
}

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市畏陕,隨后出現(xiàn)的幾起案子配乓,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犹芹,死亡現(xiàn)場(chǎng)離奇詭異崎页,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)羽莺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門实昨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盐固,你說(shuō)我怎么就攤上這事≌尚” “怎么了刁卜?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)曙咽。 經(jīng)常有香客問(wèn)我蛔趴,道長(zhǎng),這世上最難降的妖魔是什么例朱? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任孝情,我火速辦了婚禮,結(jié)果婚禮上洒嗤,老公的妹妹穿的比我還像新娘箫荡。我一直安慰自己,他們只是感情好渔隶,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布羔挡。 她就那樣靜靜地躺著,像睡著了一般间唉。 火紅的嫁衣襯著肌膚如雪绞灼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天呈野,我揣著相機(jī)與錄音低矮,去河邊找鬼。 笑死被冒,一個(gè)胖子當(dāng)著我的面吹牛军掂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姆打,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼良姆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了幔戏?” 一聲冷哼從身側(cè)響起玛追,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后痊剖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體韩玩,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年陆馁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了找颓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叮贩,死狀恐怖击狮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情益老,我是刑警寧澤彪蓬,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站捺萌,受9級(jí)特大地震影響档冬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桃纯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一酷誓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧态坦,春花似錦盐数、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至壮锻,卻和暖如春琐旁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猜绣。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工灰殴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掰邢。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓牺陶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親辣之。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掰伸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容