Vue3——Hook函數(shù) & 生命周期 & toRef和toRefs & 其他的組合式API

一毁渗、Hook函數(shù)

Vue3 的hook函數(shù)相當(dāng)于 vue2 的 mixin祝蝠,不同點(diǎn)在于hooks是函數(shù)。Vue3的hook函數(shù)可以幫助我們提高代碼的復(fù)用性细溅,能在不同的組件中都使用hook函數(shù)喇聊。

在src目錄下建立一個(gè) hooks 文件夾誓篱,文件夾中新建一個(gè)我們要用的方法的名字.js文件(一般情況下use開(kāi)頭)窜骄。
useCar.js

import { ref, computed } from 'vue'
export default function () {
    let carName = ref("奔馳")
    let carPrice = ref(50000)
    // 修改汽車名稱
    let updateCarName = (name) => {
        carName.value = name
    }
    // 修改汽車價(jià)格
    let updateCarPrice = (price) => {
        carPrice.value = price
    }
    let usaCarPrice = computed(() => {
        return '$' + (carPrice.value / (Math.random() + 6)).toFixed(2)
    })
    return {
        carName,
        carPrice,
        updateCarName,
        updateCarPrice,
        usaCarPrice
    }
}

usePlane.js

// 導(dǎo)入ref,computed
import { ref, computed } from "vue";
export default function () {
  // 飛機(jī)名稱
  let planeName = ref("波音747");
  // 飛機(jī)價(jià)格
  let planePrice = ref(20000);
  // 修改飛機(jī)名稱的方法
  let updatePlaneName = (name) => {
    planeName.value = name;
  };
  // 修改飛機(jī)價(jià)格的方法
  let updatePlanePrice = (price) => {
    planePrice.value = price;
  };
  // 飛機(jī)在美國(guó)的價(jià)格
  let usaPlanePrice = computed(() => {
    return "$" + (planePrice.value / (Math.random() + 6)).toFixed(2);
  });
  return {
    planeName,
    planePrice,
    updatePlaneName,
    updatePlanePrice,
    usaPlanePrice,
  };
}

組件
將文件引入到要使用的組件中邻遏。

<div class="child">
    <div class="car">
        <p>汽車名稱:{{carName}}<button @click="updateCarName('寶馬')">修改汽車名稱</button></p>
        <p>汽車價(jià)格:{{'¥'+carPrice}}<button @click="updateCarPrice(10000)">修改汽車價(jià)格</button></p>
        <p>美國(guó)價(jià)格:{{usaCarPrice}}</p>
    </div>
    <hr>
    <div class="plane">
        <p>汽車名稱:{{planeName}}<button @click="updatePlaneName('B2轟炸機(jī)')">修改飛機(jī)名稱</button></p>
        <p>汽車價(jià)格:{{'¥'+planePrice}}<button @click="updatePlanePrice(50000)">修改飛機(jī)價(jià)格</button></p>
        <p>美國(guó)價(jià)格:{{usaPlanePrice}}</p>
    </div>
</div>
import {computed, ref} from 'vue'
// 導(dǎo)入hook函數(shù)useCar
import useCar from '../hooks/useCar'
// 導(dǎo)入hook函數(shù)usePlane
import usePlane from '../hooks/usePlane'
export default {
  name: "Child",
  setup() {
      return {
          ...useCar(),
          ...usePlane()
      }
  }
};

二、生命周期

Vue3 中廷没,可以在 setup() 函數(shù)中使用生命周期颠黎,定義組合式API生命周期函數(shù)。組合式API生命周期函數(shù)砰蠢,會(huì)先與傳統(tǒng)的生命周期函數(shù)執(zhí)行台舱。
與vue2相比潭流,在vue3中對(duì)beforeDestroy和destroyed這兩個(gè)生命周期函數(shù)灰嫉,進(jìn)行了重命名,beforeUnmount 替換了 beforeDestroy浑厚;unmounted 替換了 destroyed钳幅。
setup()函數(shù)敢艰,可以替代beforeCreate 和 created 這兩個(gè)生命周期函數(shù)册赛,因?yàn)関ue2中的beforeCreate和created生命周期的執(zhí)行幾乎與VUE3中的setup在同一時(shí)間執(zhí)行。

<div class="child3">
  {{ count }}
  <button @click="updateCount">count++</button>
</div>
// 導(dǎo)入生命周期組合式api牡属,除了beforeCreate和created這兩個(gè)生命周期函數(shù)沒(méi)有組合式api
// 其他的生命周期函數(shù)逮栅,都有對(duì)應(yīng)的組合式api痰驱,命名方式只是在原有方法名的前面加上on
// setup()函數(shù)在這里充當(dāng)了beforeCreate和created這兩個(gè)生命周期函數(shù)的功能担映。
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount,onUnmounted } from "vue";
export default {
  name: "Child3",
  data() {
    return {
      show:true
    }
  },
  setup() {
    //注意:setup是在beforeCreate和created之前運(yùn)行的蝇完。
    //所以矗蕊,在setup里面傻咖,無(wú)法調(diào)用data和methods里面的數(shù)據(jù)
    console.log('setup');
    let count = ref(1);
    let updateCount = () => {
      count.value++;
    };
    //掛載前
    onBeforeMount(() => {
        console.log('onBeforeMount');
    }),
    //掛載完成
    onMounted(()=>{
        console.log('onMounted');
    })
    //修改后卿操,頁(yè)面重新掛載前
    onBeforeUpdate(()=>{
        console.log('onBeforeUpdate');
    })
    //修改后害淤,頁(yè)面重新掛載完成
    onUpdated(()=>{
        console.log('onUpdated');
    })
    //卸載前
    onBeforeUnmount(()=>{
        console.log('onBeforeUnmount');
    })
    //卸載完成
    onUnmounted(() => {
        console.log('onUnmounted');
    })

    return {
      count,
      updateCount,
    };
  },
  /* data() {
    return {
      count: 1,
    };
  },
  methods: {
    updateCount() {
      this.count++;
    },
  }, */
  // 數(shù)據(jù)初始化前
  /*beforeCreate() {
    console.log("--beforeCreate--");
  },
  // 數(shù)據(jù)初始化完成
  created() {
    console.log("--created--");
  },
  // 頁(yè)面掛載前
  beforeMount() {
    console.log("--beforeMount--");
  },
  // 頁(yè)面掛載完成
  mounted() {
    console.log("--mounted--");
  },
  // 數(shù)據(jù)修改后窥摄,頁(yè)面重新掛載前
  beforeUpdate() {
    console.log(this.count);
    console.log("--beforeUpdate--");
  },
  // 數(shù)據(jù)修改后崭放,頁(yè)面重新掛載完成
  updated() {
    console.log(this.count);
    console.log("--updated--");
  },
  // 卸載組件之前前
  beforeUnmount() {
    console.log("--beforeUnmount--");
  },
  // 卸載組件完成
  unmounted() {
    console.log("--unmounted--");
  }, */
};

三币砂、toRef和toRefs

toRef()函數(shù):可以用來(lái)為一個(gè) reactive 對(duì)象里面的指定屬性創(chuàng)建一個(gè) ref道伟,這個(gè) ref 可以被傳遞并且能夠保持響應(yīng)性蜜徽。這樣做的好處是簡(jiǎn)化了模板中的表達(dá)式拘鞋。toRef()函數(shù)矢门,需要傳兩個(gè)參數(shù):reactive 對(duì)象祟剔、具體的屬性名。
toRefs()函數(shù):把一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)換成普通對(duì)象物延,該普通對(duì)象的每個(gè)屬性都是一個(gè) ref叛薯。

<div class="child1">
  <ul>
    <li>姓名:{{ name }}</li>
    <li>年齡:{{ age }}</li>
    <li>性別:{{ sex }}</li>
    <li>地址:{{ address }}</li>
    <li>汽車名稱:{{ car.name }}</li>
    <li>汽車價(jià)格:{{ car.price }}</li>
    <li><button @click="updateStudent">修改學(xué)生信息</button></li>
  </ul>
</div>
import { reactive, toRefs } from "vue";
export default {
  name: "Child1",
  setup() {
    // 學(xué)生對(duì)象
    let student = reactive({
      name: "張三",
      age: 20,
      sex: "男",
      address: "南京",
      car: {
        name: "寶馬",
        price: 1000,
      },
    });
    // 修改學(xué)生的方法
    let updateStudent = () => {
      student.name = "李四";
      student.age = 22;
      student.sex = "女";
      student.address = "成都";
      student.car.name = "奔馳";
      student.car.price = 2000;
    };
    return {
      // toRef()方法,用于將一個(gè)reactive對(duì)象里面的指定屬性以ref形式的對(duì)象返回
      // name:toRef(student,'name'),
      // age:toRef(student,'age'),
      // sex:toRef(student,'sex'),
      // address:toRef(student,'address'),

      // 假如 reactive 對(duì)象中组力,有100個(gè)屬性燎字,上面的操作要寫100次轩触,所以脱柱,一般都直接用toRefs函數(shù)
      // 注意:如果student里面的屬性是一個(gè)對(duì)象拉馋,這個(gè)屬性對(duì)象里面的內(nèi)容是不能直接轉(zhuǎn)為ref的
      // toRefs只能保證一級(jí)屬性
      ...toRefs(student),
      updateStudent,
    };
  },
};

四煌茴、其他的組合式API

1、readonly

readonly()方法:用于返回一份只讀數(shù)據(jù)矩乐。傳入一個(gè)對(duì)象(響應(yīng)式或普通)或 ref散罕,返回一個(gè)原始對(duì)象的只讀代理欧漱。一個(gè)只讀的代理是“深層的”误甚,對(duì)象內(nèi)部任何嵌套的屬性也都是只讀的谱净。
注意:該方法壕探,不能將一個(gè)普通值類型數(shù)據(jù)轉(zhuǎn)為只讀數(shù)據(jù)。

<div>{{ student }} <button @click="updateStudent">修改學(xué)生信息</button></div>
import { reactive, readonly } from "vue";
export default {
  name: "Child2",
  setup() {
    let data = reactive({
      name: "張三",
      age: 20,
    });
    let student = readonly(data);
    // student是一個(gè)只讀對(duì)象派继,無(wú)法修改數(shù)據(jù)
    let updateStudent = () => {
      student.name = "李四";
      student.age = 22;
    };
    return {
      student,
      updateStudent,
    };
  },
};

2、isReadonly

檢查一個(gè)對(duì)象是否是由 readonly 創(chuàng)建的只讀代理庆猫。

import { reactive, readonly, isReadonly } from "vue";
let data = reactive({
  name: "張三",
  age: 20,
});
let student = readonly(data);
console.log('student is readonly',isReadonly(student));   //true

3月培、isRef

isRef():檢查一個(gè)值是否為一個(gè) ref 對(duì)象杉畜。

import { ref, isRef } from "vue";
let name = ref('你好')
console.log('name is ref',isRef(name));   //true

4衷恭、isProxy

isProxy():檢查一個(gè)對(duì)象是否是由 reactive 或者 readonly 方法創(chuàng)建的代理随珠。

import { reactive, readonly, isProxy } from "vue";
setup() {
let data = reactive({
  name: "張三",
  age: 20,
});
let student = readonly(data);
console.log('data is proxy',isProxy(data));   //true
console.log('student is proxy',isProxy(student));   //true

5窗看、isReactive

isReactive():檢查一個(gè)對(duì)象是否是由 reactive 創(chuàng)建的響應(yīng)式代理显沈。如果這個(gè)代理是由 readonly 創(chuàng)建的拉讯,但是又被 reactive 創(chuàng)建的另一個(gè)代理包裹了一層遂唧,那么同樣也會(huì)返回 true盖彭。

import { reactive, isReactive } from "vue";
setup() {
  let data = reactive({
    name: "張三",
    age: 20,
  });
  console.log('data is reactive',isReactive(data));   //true
}

6铺呵、unref

unref()函數(shù):如果參數(shù)是一個(gè) ref 則返回它的 value片挂,否則返回參數(shù)本身音念。等同于 val = isRef(val) ? val.value : val 闷愤。

import { ref, unref } from "vue";
setup() {
  let name = ref('你好')
  let age = 20
  console.log(unref(name));   // '你好'
  console.log(unref(age));   // 20
}

7讥脐、markRaw

markRaw():使用markRaw()方法返回出來(lái)的對(duì)象旬渠,再也不能成為響應(yīng)式對(duì)象告丢,函數(shù)返回這個(gè)對(duì)象本身芋齿。如果被 markRaw 標(biāo)記了觅捆,即使在響應(yīng)式對(duì)象中作屬性栅炒,也依然不是響應(yīng)式的赢赊。

import { reactive, markRaw } from "vue";
setup() {
  // 使用markRaw()方法释移,返回出來(lái)的對(duì)象玩讳,再也不能成為響應(yīng)式對(duì)象熏纯。
  let car = markRaw({
      name:'奔馳',
      price:20
  })
  let car2 = reactive(car)
  // car2只是一個(gè)普通對(duì)象樟澜,不是響應(yīng)式對(duì)象
  console.log(car2);
}

8秩贰、shallowRef

shallowRef():返回的對(duì)象 value 屬性值是 object對(duì)象(普通對(duì)象)吭服,不再具備任何響應(yīng)式了艇棕。

<div>
  汽車信息:{{ car3 }}
  <button @click="updateCar">修改汽車</button>
</div>
import { shallowRef } from "vue";
setup() {
  let car3 = shallowRef({
    name: "大眾",
    type: {
      typeName: "SUV",
    },
  });
  let updateCar = () => {
    // 由于value返回的是object對(duì)象沼琉,所以打瘪,這里不再具有響應(yīng)式
    car3.value.name = "奔馳";
    car3.value.type.typeName = "跑車";
  };
  return {
    car3,
    updateCar
  };
}

9闺骚、shallowReactive

shallowReactive():用于定義淺響應(yīng)式對(duì)象僻爽,只對(duì)第一層屬性設(shè)置響應(yīng)式胸梆。

import { shallowReactive,isReactive } from "vue";
setup() {
  let luhan = shallowReactive({
      name:'鹿晗',
      age:30,
      friend:{
          name:'關(guān)曉彤',
          age:20,
      }
  })
  let updateLuhan = ()=>{
      // luhan.name = '張藝興',
      // luhan.age = 25

      // 如果只是修改對(duì)象的深層屬性,不會(huì)觸發(fā)頁(yè)面更新
      luhan.friend.name = '小美'
      luhan.friend.age = 22
  }
}

10绪颖、shallowReadonly

shallowReadonly:淺只讀柠横,只有第一層屬性是只讀的滓鸠。

import { shallowReadonly } from "vue";
setup() {
  let luhan = shallowReactive({
      name:'鹿晗',
      age:30,
      friend:{
          name:'關(guān)曉彤',
          age:20,
      }
  })
  let luhan3 = shallowReadonly(luhan);
  // luhan3.name = '小明'      // 屬性只讀
  luhan3.friend.name = "小美";      // 屬性可修改
}

11糜俗、toRaw

toRaw()方法:用于將一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)為普通對(duì)象珠月。

import { toRaw } from "vue";
setup() {
  let luhan = shallowReactive({
      name:'鹿晗',
      age:30,
      friend:{
          name:'關(guān)曉彤',
          age:20,
      }
  })
  let luhan2 = toRaw(luhan);
  console.log("luhan2", luhan2);   // 普通對(duì)象
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啤挎,一起剝皮案震驚了整個(gè)濱河市庆聘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌黑忱,老刑警劉巖菇曲,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件常潮,死亡現(xiàn)場(chǎng)離奇詭異蕊玷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)剪勿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)械念,“玉大人项钮,你說(shuō)我怎么就攤上這事烁巫⊙窍叮” “怎么了阿弃?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵脾还,是天一觀的道長(zhǎng)荠呐。 經(jīng)常有香客問(wèn)我泥张,道長(zhǎng)媚创,這世上最難降的妖魔是什么钞钙? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮本刽,結(jié)果婚禮上子寓,老公的妹妹穿的比我還像新娘斜友。我一直安慰自己鲜屏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著靠胜,像睡著了一般浪漠。 火紅的嫁衣襯著肌膚如雪霎褐。 梳的紋絲不亂的頭發(fā)上冻璃,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天响谓,我揣著相機(jī)與錄音娘纷,去河邊找鬼赖晶。 笑死遏插,一個(gè)胖子當(dāng)著我的面吹牛纠修,可吹牛的內(nèi)容都是我干的扣草。 我是一名探鬼主播铆惑,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碌廓!你這毒婦竟也來(lái)了呆瞻?” 一聲冷哼從身側(cè)響起颤介,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤滚朵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后移宅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體漏峰,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了顾复。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芯砸。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖包帚,靈堂內(nèi)的尸體忽然破棺而出渴邦,到底是詐尸還是另有隱情,我是刑警寧澤信峻,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布盹舞,位于F島的核電站矾策,受9級(jí)特大地震影響贾虽,放射性物質(zhì)發(fā)生泄漏蓬豁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一蟆技、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧眶蕉,春花似錦造挽、人聲如沸饭入。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寞肖,卻和暖如春新蟆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饶囚。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工嘀掸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睬塌,地道東北人揩晴。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瞄崇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摹蘑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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