助你上手Vue3全家桶之Vue3教程

前言

這些內容是博主在學習過程中記錄下來的,有一些不重要的點就跳過了,需要時自行查詢文檔。其實V2V3的學習成本不高,熟悉V2的話,看完這篇文章就可以上手V3

Vue3官網

在線源碼編譯地址

1,setup


setup是所有Composition API的容器,值為一個函數。組件中所用到的數據、方法等等,均要配置在setup中,它會在beforeCreate之前執行一次,注意:V3this不再是指向Vue實例,訪問this會是undefined

1.1,返回值


  • 若返回一個對象,則對象中的屬性、方法, 在模板中均可以直接使用。
  • 若返回一個渲染函數:則可以自定義渲染內容。

1.2,注意點


盡量不要與V2配置混用

V2配置(datamethoscomputed...)中可以訪問到setup中的屬性、方法。
但在setup中不能訪問到V2配置(datamethodscomputed...)。
如果有重名, setup優先。

setup不能是一個async函數

因為返回值不再return的對象, 而是promise, 模板看不到return對象中的屬性。(后期也可以返回一個Promise實例,但需要Suspense和異步組件的配合)

1.3,語法


<script>
import { ref, reactive } from 'vue'

export default {
    name: 'Home',
    setup(props, context) {
        const title = ref('標題')
        const data = reactive({
            value: '哈哈哈'
        })
        return {
          title,
          data
        }
    }
}
</script>

1.4,setup的參數


  • props:值為對象,包含組件外部傳遞過來,且組件內部聲明接收了的屬性

  • context:上下文對象

    • attrs: 值為對象,包含組件外部傳遞過來,但沒有在props配置中聲明的屬性, 相當于this.$attrs
    • slots: 收到的插槽內容, 相當于this.$slots
    • emit: 分發自定義事件的函數, 相當于this.$emit

2,ref 創建響應式數據


使用ref可以創建一個包含響應式數據的引用對象(reference對象,簡稱ref對象),可以是基本類型、也可以是對象。

語法

// 創建
const xxx = ref(value)

// 使用
xxx.value

// 在模板中
<div>{{xxx}}</div>

3,reactive 創建響應式數據


定義一個對象類型的響應式數據,內部基于ES6Proxy實現,通過代理對象操作源對象內部數據進行操作

語法

// 創建
const xxx = reactive({
    xxx: ''
})

// 使用
xxx.xxx

4,computed 計算屬性


V2computed配置功能一致

語法

import { computed } from 'vue'

setup(){
    // 簡寫語法
    let fullName = computed(() => {
        return person.firstName + '-' + person.lastName
    })
    
    // 完整語法
    let fullName = computed({
        get(){
            return person.firstName + '-' + person.lastName
        },
        set(value){
            const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
    
    return fullName
}

5,watch 監聽


V2watch配置功能一致,語法有點改動

語法

  • 情況一:監視ref定義的響應式數據
watch(sum, (newValue, oldValue) => {
    console.log('sum變化了', newValue, oldValue)
}, {immediate:true})
  • 情況二:監視多個ref定義的響應式數據
watch([sum, msg], (newValue,oldValue) => {
    console.log('sum或msg變化了', newValue,oldValue)
}) 
  • 情況三:監視reactive定義的響應式數據
// 若watch監視的是reactive定義的響應式數據,則無法正確獲得oldValue
// 若watch監視的是reactive定義的響應式數據,則強制開啟了深度監視
watch(person, (newValue, oldValue) => {
    console.log('person變化了', newValue, oldValue)
}, { immediate:true, deep:false }) // 此處的deep配置不再奏效
  • 情況四:監視reactive定義的響應式數據中的某個屬性
watch(() => person.job, (newValue, oldValue) => {
    console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true }) 
  • 情況五:監視reactive定義的響應式數據中的某些屬性
watch([() => person.job, () => person.name], (newValue, oldValue) => {
    console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true })
  • 特殊情況:此處由于監視的是reactive素定義的對象中的某個屬性,所以deep配置有效
watch(() => person.job, (newValue, oldValue) => {
    console.log('person的job變化了', newValue, oldValue)
}, { deep:true })

6,watchEffect 監聽回調


watch的區別是,watch既要指明監視的屬性,也要指明監視的回調。而watchEffect,不用指明監視哪個屬性,監視的回調中用到哪個屬性,那就監視哪個屬性,不用寫返回值。

語法

// 回調中用到的數據只要發生變化,則直接重新執行回調
watchEffect(() => {
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回調執行了')
})

7,生命周期


生命周期全都寫在setup

7.1,改變


  • beforeDestroy 改名為 beforeUnmount
  • destroyed 改名為 unmounted
  • beforeCreate => setup
  • created => setup
  • beforeMount => onBeforeMount
  • mounted => onMounted
  • beforeUpdate => onBeforeUpdate
  • updated => onUpdated
  • beforeUnmount => onBeforeUnmount
  • unmounted => onUnmounted

7.2,語法


setup() {
    onMounted(() => {
      console.log('mounted')
    })
}

8,toRef 創建ref


創建一個ref對象,其value值指向另一個對象中的某個屬性

語法

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

// 傳遞props
export default {
  setup(props) {
    useSomeFeature(toRef(props, 'foo'))
  }
}

9,toRefs 響應式轉換


將響應式對象轉換為普通對象,其中結果對象的每個property都是指向原始對象相應propertyref

語法

const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)
// 此時state和stateAsRefs是關聯的

10,shallowReactive 響應式外層轉換


只處理對象最外層屬性的響應式(淺響應式)。適用于:一個對象數據,結構比較深, 但變化時只是外層屬性變化

語法

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})

11,shallowRef 基本數據響應式


只處理基本數據類型的響應式, 不進行對象的響應式處理。適用于:一個對象數據,后續功能不會修改該對象中的屬性,而是生新的對象來替換

語法

const shallow = shallowRef({
  greet: 'Hello, world'
})

12,readonly 響應式變只讀


讓一個響應式數據變為只讀的(深只讀),應用于不希望數據被修改時

語法

const shallow = shallowRef({
  greet: 'Hello, world', // 只讀
  nested: {
    bar: 2 // 只讀
  }
})

13,shallowReadonly 響應式變只讀


讓一個響應式數據變為只讀的(淺只讀),應用于不希望數據被修改時

語法

const shallow = shallowReadonly({
  foo: 1, // 只讀
  nested: {
    bar: 2 // 非只讀
  }
})

14,toRaw 響應式變非響應式


將一個由reactive生成的響應式對象轉為普通對象,對這個普通對象的所有操作,不會引起頁面更新。

語法

const foo = {}
const Foo = reactive(foo)
console.log(toRaw(Foo) === foo) // true

15,markRaw 標記永遠不響應式


標記一個對象,使其永遠不會再成為響應式對象,有些值不應被設置為響應式的,例如復雜的第三方類庫等,當渲染具有不可變數據源的大列表時,跳過響應式轉換可以提高性能。

語法

const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false

// 嵌套在其他響應式對象中時也可以使用
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false

16,customRef 依賴更新控制


創建一個自定義的 ref,并對其依賴項跟蹤和更新觸發進行顯式控制。它需要一個工廠函數,該函數接收tracktrigger函數作為參數,并且應該返回一個帶有getset的對象。

語法

<script>
import { customRef } from 'vue'

export default {
    name: 'Home',
    setup() {
        // 實現防抖函數
        const fn = function(value, delay = 500) {
            let timeout
            return customRef((track, trigger) => {
                return {
                    get() {
                        track()
                        return value
                    },
                    set(newValue) {
                        clearInterval(timeout)
                        timeout = setTimeout(() => {
                            console.log(newValue)
                            value = newValue
                            trigger()
                        }, delay)
                    }
                }
            })
        }
        const keyword = fn('', 500)
        return {
            keyword
        }
    }
}
</script>

17,provide & inject 通信


實現祖與后代組件間通信,父組件有一個provide選項來提供數據,后代組件有一個inject選項來開始使用這些數據

語法

// 祖組件
setup(){
    let car = reactive({ name:'奔馳', price:'40萬' })
    provide('car', car)
}

// 后代組件
setup(props, context){
    const car = inject('car')
    return { car }
}

18,響應式數據的判斷


18.1,isRef


檢查一個值是否為一個ref對象

語法

const val = ref('xxx')
isRef(val) // true

18.2,isReactive


檢查一個值是否為一個isReactive對象

語法

const val = isReactive({})
isRef(val) // true

18.3,isReadonly


檢查一個對象是否是由readonly創建的只讀代理

語法

const state = reactive({
  name: 'John'
})
console.log(isReactive(state)) // true

18.4,isProxy


檢查對象是否是由reactivereadonly創建的proxy

語法

const state = reactive({
  name: 'John'
})
console.log(isProxy(state)) // true

19,teleport 移動dom組件


Teleport提供了一種干凈的方法,允許我們控制在DOM中哪個父節點下渲染了HTML,而不必求助于全局狀態或將其拆分為兩個組件。

語法

<teleport to="移動位置">
    <div v-if="isShow" class="mask">
        <div class="dialog">
            <h3>我是一個彈窗</h3>
            <button @click="isShow = false">關閉彈窗</button>
        </div>
    </div>
</teleport>


// to的格式
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />

// disabled的格式
<teleport to="#popup" :disabled="displayVideoInline">
  <video src="./my-movie.mp4">
</teleport>

20,Suspense 異步渲染組件


等待異步組件時先渲染一些額外內容,讓應用有更好的用戶體驗

語法

<template>
    <div class="app">
        <h3>我是App組件</h3>
        <Suspense>
            <template #default>
                <Child/>
            </template>
            <template #fallback>
                <h3>加載中.....</h3>
            </template>
        </Suspense>
    </div>
</template>


import { defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(() => import('./components/Child.vue'))

components: {
    Child
}

21,全局API調整


將全局的API,即:Vue.xxx調整到應用實例(app)上

V2的api V3的api
Vue.config.xxxx app.config.xxxx
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties

22,移除api


名稱 現狀
Vue.config.productionTip 已移除
config.keyCodes 已移除
$children 已移除
$listeners 已移除
$on 已移除
$off 已移除
$once 已移除
filters 已移除
.native 已移除

23,Ref 獲取DOM


由于V3中不在存在this,所以ref的獲取調整了

23.1,單個ref


語法

<div ref="Qrcode" class="qr_codeode_url" />

import { ref } from 'vue'

export default {
  setup() {
    const Qrcode = ref(null)
    // 掛載后
    onMounted(() => {
        console.log(Qrcode.value)
    })
    return {
      Qrcode
    }
  }
}

23.2,循環中的ref


V3中在for循環元素上綁定ref將不再自動創建$ref數組。要從單個綁定獲取多個ref,請將ref綁定到一個更靈活的函數上

語法

<div v-for="item in list" :ref="setItemRef"></div>

import { onBeforeUpdate, onUpdated } from 'vue'

export default {
  setup() {
    let itemRefs = []
    const setItemRef = el => {
      if (el) {
        itemRefs.push(el)
      }
    }
    onBeforeUpdate(() => {
      itemRefs = []
    })
    onUpdated(() => {
      console.log(itemRefs)
    })
    return {
      setItemRef
    }
  }
}
  • itemRefs不必是數組:它也可以是一個對象,其ref可以通過迭代的key被設置
  • 如有需要,itemRef也可以是響應式的,且可以被偵聽

24,emits 自定義事件


定義一個組件可以向其父組件觸發的事件

// 在子組件中
<h1 @click="father">{{ msg }}</h1>

export default {
    name: 'HelloWorld',
    props: {
        msg: {
            type: String,
            default: ''
        }
    },
    emits: ['close'],
    setup(props, { emit }) {
        const father = function() {
            emit('close', 'child')
        }
        return {
            father
        }
    }
}

// 在父組件中
<HelloWorld :msg="msg" @click="fn" @close="fn2" />

25,$nextTick 異步更新


使用方式修改

import { nextTick } from 'vue'

nextTick(() => {
  // ...
})

26,hook 生命周期事件


通過事件來監聽組件生命周期中的關鍵階段

語法

// V2的語法
<template>
  <child-component @hook:updated="onUpdated">
</template>

// V3的語法
<template>
  <child-component @vnode-updated="onUpdated">
</template>

// 駝峰寫法
<template>
  <child-component @vnodeUpdated="onUpdated">
</template

如果看了覺得有幫助的,我是@鵬多多11997110103,歡迎 點贊 關注 評論;
END

PS:在本頁按F12,在console中輸入document.querySelectorAll('._2VdqdF')[0].click(),有驚喜哦

往期文章

個人主頁

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容