9個(gè)關(guān)于 Vue3.0 api 方法的總結(jié)

ref與toRef、toRefs
ref函數(shù)包裝了一個(gè)響應(yīng)式的數(shù)據(jù)對象。toRef 是將某個(gè)對象中的某個(gè)值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù),其接收兩個(gè)參數(shù),第一個(gè)參數(shù)為 obj 對象;第二個(gè)參數(shù)為對象中的屬性名。toRefs其作用就是將傳入的對象里所有的屬性的值都轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)對象,該函數(shù)支持一個(gè)參數(shù),即 obj 對象ref 是對傳入數(shù)據(jù)的拷貝;toRef 是對傳入數(shù)據(jù)的引用ref 的值改變會(huì)更新視圖;toRef 的值改變不會(huì)更新視圖
reactive與shallowReactive
reactive 方法是用來創(chuàng)建一個(gè)響應(yīng)式的數(shù)據(jù)對象,可以是嵌套的對象,會(huì)給內(nèi)部的每一個(gè)對像都加入一個(gè)Proxy包裹著shallowReactive代表一個(gè)淺層的 reactive,意思就是監(jiān)聽了第一層屬性的值,一旦發(fā)生改變,則更新視圖。代表著當(dāng)使用時(shí)只給第一層加入了Proxy
<template><div>{{state.count}}</div></template><script>import { reactive,shallowReactive }from 'vue'export default {name: 'HelloWorld',props: {msg: String},setup() {const state= reactive({count:3})return {state}}}</script>復(fù)制代碼
現(xiàn)在對比reactive和shallowReactive
使用reactive
<template><div>{{state.count}}</div></template><script>import { reactive,shallowReactive }from 'vue'export default {name: 'HelloWorld',props: {msg: String},setup() {const obj={one:{name:'小明',two:{name:'小王',three:{name:'小李',}}}}const state= reactive(obj)console.log(state.one)console.log(state.one.two)console.log(state.one.two.three)return {state}}}</script>
使用shallowReactive
<template><div>{{state.count}}</div></template><script>import { reactive,shallowReactive }from 'vue'export default {name: 'HelloWorld',props: {msg: String},setup() {const obj={one:{name:'小明',two:{name:'小王',three:{name:'小李',}}}}const state= shallowReactive(obj)console.log(state)console.log(state.one)console.log(state.one.two)console.log(state.one.two.three)return {state}}}</script>
運(yùn)行結(jié)果如下: 
3.toRaw和markRaw
toRaw 方法是用于獲取 ref 或 reactive 對象的原始數(shù)據(jù)的;
示例如下:
<script>import {reactive, toRaw} from 'vue'export default {setup() {const obj = {name: '哈哈哈哈哈哈哈',age: 35}const state = reactive(obj)const raw = toRaw(state)console.log(state)console.log(raw)console.log(obj === raw) // true}}</script>
結(jié)果如下:
markRaw 方法可以將原始數(shù)據(jù)標(biāo)記為非響應(yīng)式的,即使用 ref 或 reactive 將其包裝,仍無法實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式,其接收一個(gè)參數(shù),即原始數(shù)據(jù),并返回被標(biāo)記后的數(shù)據(jù)。示例如下:
<script>import {reactive, toRaw,markRaw} from 'vue'export default {setup() {const obj = {name: '哈哈哈哈哈哈哈',age: 35}markRaw(obj)const state = reactive(obj)console.log(obj)console.log(state)}}</script>
結(jié)果:

4.useRoute和useRouter
<template><div><router-link to="/home">Home</router-link><router-link to='/test'>Test</router-link></div><router-view></router-view></template><script>import { onMounted } from "vue";import { useRoute, useRouter } from "vue-router";export default {setup(props, context) {onMounted(() => {console.log(route);console.log(router);});const route = useRoute();const router = useRouter();return {};},};</script>

5.watch和watchEffect
watch和watchEffect都是用來監(jiān)視某項(xiàng)數(shù)據(jù)變化從而執(zhí)行指定的操作的,但是他們之間在用法上還是有區(qū)別的:
watch( source, cb, [options] )
source:可以是表達(dá)式或函數(shù),用于指定監(jiān)聽的依賴對象
cb:依賴對象變化后執(zhí)行的回調(diào)函數(shù)
options:可參數(shù),可以配置的屬性有 immediate(立即觸發(fā)回調(diào)函數(shù))、deep(深度監(jiān)聽)
當(dāng)ref時(shí)
<template><div><router-link to="/home">Home</router-link><router-link to='/test'>Test</router-link></div><router-view></router-view></template><script>import { ref,watch} from "vue";export default {setup() {const state = ref(0)watch(state, (newValue, oldValue) => {console.log(`原值為${oldValue}`)console.log(`新值為${newValue}`)/* 1秒后打印結(jié)果:原值為0新值為1*/})// 1秒后將state值+1setTimeout(() => {state.value ++}, 1000)},};</script>
當(dāng)reactive時(shí)
<script>import {reactive, watch} from 'vue'export default {setup() {const state = reactive({count: 0})watch(() => state.count, (newValue, oldValue) => {console.log(`原值為${oldValue}`)console.log(`新值為${newValue}`)/* 1秒后打印結(jié)果:原值為0新值為1*/})// 1秒后將state.count的值+1setTimeout(() => {state.count ++}, 1000)}}</script>
結(jié)果如下:
監(jiān)聽多個(gè)值:
<script>import {reactive, watch} from 'vue'export default {setup() {const state = reactive({ count: 0, name: 'zs' })watch([() => state.count, () => state.name],([newCount, newName], [oldvCount, oldName]) => {console.log(oldvCount) // 舊的 count 值console.log(newCount) // 新的 count 值console.log(oldName) // 舊的 name 值console.log(newName) // 新的 name 值})setTimeout(() => {state.count ++state.name = 'ls'}, 1000)}}</script>
結(jié)果如下:

watchEffect,它與 watch 的區(qū)別主要有以下幾點(diǎn):
不需要手動(dòng)傳入依賴
每次初始化時(shí)會(huì)執(zhí)行一次回調(diào)函數(shù)來自動(dòng)獲取依賴
無法獲取到原值,只能得到變化后的值
<template><div><router-link to="/home">Home</router-link><router-link to='/test'>Test</router-link></div><router-view></router-view></template><script>import {reactive, watchEffect} from 'vue'export default {setup() {const state = reactive({ count: 0, name: 'zs' })watchEffect(() => {console.log(state.count)console.log(state.name)/* 初始化時(shí)打印:0zs1秒后打印:1ls*/})setTimeout(() => {state.count ++state.name = 'ls'}, 1000)}}</script>
6.computed 返回一個(gè) ref 對象。
<script>import {computed,ref} from 'vue'export default {setup() {const x=computed(()=>{return 'jjjjj'})console.log(x.value)const count = ref(1)const plusOne = computed({get: () => {console.log('---------Get',count.value)return count.value + 1},set: val => {console.log('---------Set',val)count.value = val - 1}})plusOne.value = 1console.log(count.value)}}</script>
結(jié)果如下:

7.provide和inject
provide :向子組件以及子孫組件傳遞數(shù)據(jù)。接收兩個(gè)參數(shù),第一個(gè)參數(shù)是
key,即數(shù)據(jù)的名稱;第二個(gè)參數(shù)為value,即數(shù)據(jù)的值inject :接收父組件或祖先組件傳遞過來的數(shù)據(jù)。接收一個(gè)參數(shù)
key,即父組件或祖先組件傳遞的數(shù)據(jù)名稱
//a.vue<script>import {provide} from 'vue'export default {setup() {const obj= {name: '哈哈哈哈哈哈',age: 22}// 向子組件以及子孫組件傳遞名為info的數(shù)據(jù)provide('info', obj)}}</script>//b.vue<script>import {inject} from 'vue'export default {setup() {// 接收a.vue傳遞過來的數(shù)據(jù)inject('info') // {name: '哈哈哈哈哈哈', age: 22}}}</script>//c.vue<script>import {inject} from 'vue'export default {setup() {// 接收a.vue傳遞過來的數(shù)據(jù)inject('info') // {name: '哈哈哈哈哈哈', age: 22}}}</script>
8.vue2與vue3生命周期對比

<template><div id="app"></div></template><script>// 1. 從 vue 中引入 多個(gè)生命周期函數(shù)import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, unMounted} from 'vue'export default {name: 'App',setup() {onBeforeMount(() => {// 在掛載前執(zhí)行某些代碼})onMounted(() => { // 在掛載后執(zhí)行某些代碼})onBeforeUpdate(() => {// 在更新前前執(zhí)行某些代碼})onUpdated(() => {// 在更新后執(zhí)行某些代碼})onBeforeUnmount(() => {// 在組件銷毀前執(zhí)行某些代碼})unMounted(() => {// 在組件銷毀后執(zhí)行某些代碼})return {}}}</script>
9.setup(props,context)
(1)props:組件傳遞的參數(shù),是響應(yīng)式的,可以通過使用watchEffect或watch進(jìn)行觀測和響應(yīng)不要直接使用解構(gòu)賦值,會(huì)使得參數(shù)失去響應(yīng)性若要解構(gòu):const { title } = toRefs(props)(2)context:上下文對象 對應(yīng)之前vue2的context.attrs this.$attrs 組件標(biāo)簽上的屬性(非響應(yīng)式對象)context.slots this.$slots 插槽(非響應(yīng)式對象)context.emit this.$emit 標(biāo)簽上自定義的觸發(fā)事件(方法)context.emit('自定義事件名',參數(shù))無法訪問:因?yàn)槭窃诮M件創(chuàng)建實(shí)例之前指向datacomputedmethods解構(gòu):context是一個(gè)普通的JavaScript對象,也就是說,它不是響應(yīng)式的,可以直接解構(gòu)attrs和slots是內(nèi)部組件實(shí)例上相應(yīng)值的代理。這樣可以確保它們即使在更新后也始終會(huì)顯示最新值,以便我們可以對它們進(jìn)行結(jié)構(gòu)分解,而不必?fù)?dān)心訪問老的引用:但避免對內(nèi)部的屬性進(jìn)行解構(gòu),并始終以attrs.x或slots.x的方式使用(3)this指向問題:因?yàn)閟etup()是在解析其它組件選項(xiàng)之前被調(diào)用的,所以setup()內(nèi)部的this的行為與其它選項(xiàng)中的this完全不同(4)更好的模塊化問題:可以從其他文件引入函數(shù)等,然后在setup中執(zhí)行,其他文件中可以使用v3的組合式api(需先導(dǎo)入),但必須在setup中調(diào)用(5)return返回值方式:返回的內(nèi)容可以在命令式api中this.x訪問到方式一:return{返回的屬性和方法,在setup外部能夠使用,返回的普通屬性不是響應(yīng)式的,即改變不會(huì)更新視圖}方式二:return () => h('div', ["哇咔咔"]) 還可以直接返回一個(gè)渲染函數(shù),將替換模板中的內(nèi)容方式三:注意此時(shí)組件已經(jīng)變成了一個(gè)異步組件,可使用Suspense懸掛展示可以返回一個(gè)成功狀態(tài)的Promise對象,會(huì)將成功態(tài)的[[PromiseResult]]結(jié)果作為返回值return new Promise((resolve,reject)=>{ 也可返回一個(gè)Promise對象,使得組件為異步的...resolve({數(shù)據(jù)})})return await ...
轉(zhuǎn)自:https://juejin.cn/post/6989217956483825695
