前言
這些內(nèi)容是博主在學(xué)習(xí)過程中記錄下來的,有一些不重要的點(diǎn)就跳過了,需要時(shí)自行查詢文檔培他。其實(shí)V2
到V3
的學(xué)習(xí)成本不高鹃两,熟悉V2
的話,看完這篇文章就可以上手V3
舀凛。
1俊扳,setup
setup
是所有Composition API
的容器,值為一個(gè)函數(shù)猛遍。組件中所用到的數(shù)據(jù)馋记、方法等等,均要配置在setup
中螃壤,它會(huì)在beforeCreate
之前執(zhí)行一次抗果,注意:V3
里this
不再是指向Vue
實(shí)例,訪問this
會(huì)是undefined
1.1奸晴,返回值
- 若返回一個(gè)對(duì)象冤馏,則對(duì)象中的屬性、方法, 在模板中均可以直接使用寄啼。
- 若返回一個(gè)渲染函數(shù):則可以自定義渲染內(nèi)容逮光。
1.2,注意點(diǎn)
盡量不要與V2配置混用
V2
配置(data
墩划、methos
涕刚、computed
...)中可以訪問到setup
中的屬性、方法乙帮。
但在setup
中不能訪問到V2
配置(data
杜漠、methods
、computed
...)察净。
如果有重名, setup
優(yōu)先驾茴。
setup不能是一個(gè)async函數(shù)
因?yàn)榉祷刂挡辉?code>return的對(duì)象, 而是promise
, 模板看不到return
對(duì)象中的屬性。(后期也可以返回一個(gè)Promise
實(shí)例氢卡,但需要Suspense
和異步組件的配合)
1.3锈至,語法
<script>
import { ref, reactive } from 'vue'
export default {
name: 'Home',
setup(props, context) {
const title = ref('標(biāo)題')
const data = reactive({
value: '哈哈哈'
})
return {
title,
data
}
}
}
</script>
1.4,setup的參數(shù)
props:值為對(duì)象译秦,包含組件外部傳遞過來峡捡,且組件內(nèi)部聲明接收了的屬性
-
context:上下文對(duì)象
- attrs: 值為對(duì)象,包含組件外部傳遞過來筑悴,但沒有在
props
配置中聲明的屬性, 相當(dāng)于this.$attrs
- slots: 收到的插槽內(nèi)容, 相當(dāng)于
this.$slots
- emit: 分發(fā)自定義事件的函數(shù), 相當(dāng)于
this.$emit
- attrs: 值為對(duì)象,包含組件外部傳遞過來筑悴,但沒有在
2们拙,ref 創(chuàng)建響應(yīng)式數(shù)據(jù)
使用ref
可以創(chuàng)建一個(gè)包含響應(yīng)式數(shù)據(jù)的引用對(duì)象(reference對(duì)象,簡(jiǎn)稱ref對(duì)象)阁吝,可以是基本類型睛竣、也可以是對(duì)象。
語法
// 創(chuàng)建
const xxx = ref(value)
// 使用
xxx.value
// 在模板中
<div>{{xxx}}</div>
3求摇,reactive 創(chuàng)建響應(yīng)式數(shù)據(jù)
定義一個(gè)對(duì)象類型的響應(yīng)式數(shù)據(jù)射沟,內(nèi)部基于ES6
的Proxy
實(shí)現(xiàn)殊者,通過代理對(duì)象操作源對(duì)象內(nèi)部數(shù)據(jù)進(jìn)行操作
語法
// 創(chuàng)建
const xxx = reactive({
xxx: ''
})
// 使用
xxx.xxx
4,computed 計(jì)算屬性
與V2
中computed
配置功能一致
語法
import { computed } from 'vue'
setup(){
// 簡(jiǎn)寫語法
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 監(jiān)聽
與V2
中watch
配置功能一致猖吴,語法有點(diǎn)改動(dòng)
語法
- 情況一:監(jiān)視
ref
定義的響應(yīng)式數(shù)據(jù)
watch(sum, (newValue, oldValue) => {
console.log('sum變化了', newValue, oldValue)
}, {immediate:true})
- 情況二:監(jiān)視多個(gè)
ref
定義的響應(yīng)式數(shù)據(jù)
watch([sum, msg], (newValue,oldValue) => {
console.log('sum或msg變化了', newValue,oldValue)
})
- 情況三:監(jiān)視
reactive
定義的響應(yīng)式數(shù)據(jù)
// 若watch監(jiān)視的是reactive定義的響應(yīng)式數(shù)據(jù),則無法正確獲得oldValue
// 若watch監(jiān)視的是reactive定義的響應(yīng)式數(shù)據(jù)挥转,則強(qiáng)制開啟了深度監(jiān)視
watch(person, (newValue, oldValue) => {
console.log('person變化了', newValue, oldValue)
}, { immediate:true, deep:false }) // 此處的deep配置不再奏效
- 情況四:監(jiān)視
reactive
定義的響應(yīng)式數(shù)據(jù)中的某個(gè)屬性
watch(() => person.job, (newValue, oldValue) => {
console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true })
- 情況五:監(jiān)視
reactive
定義的響應(yīng)式數(shù)據(jù)中的某些屬性
watch([() => person.job, () => person.name], (newValue, oldValue) => {
console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true })
- 特殊情況:此處由于監(jiān)視的是
reactive
素定義的對(duì)象中的某個(gè)屬性海蔽,所以deep配置有效
watch(() => person.job, (newValue, oldValue) => {
console.log('person的job變化了', newValue, oldValue)
}, { deep:true })
6,watchEffect 監(jiān)聽回調(diào)
和watch
的區(qū)別是绑谣,watch
既要指明監(jiān)視的屬性党窜,也要指明監(jiān)視的回調(diào)。而watchEffect
借宵,不用指明監(jiān)視哪個(gè)屬性幌衣,監(jiān)視的回調(diào)中用到哪個(gè)屬性,那就監(jiān)視哪個(gè)屬性壤玫,不用寫返回值豁护。
語法
// 回調(diào)中用到的數(shù)據(jù)只要發(fā)生變化,則直接重新執(zhí)行回調(diào)
watchEffect(() => {
const x1 = sum.value
const x2 = person.age
console.log('watchEffect配置的回調(diào)執(zhí)行了')
})
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 創(chuàng)建ref
創(chuàng)建一個(gè)ref
對(duì)象班缎,其value
值指向另一個(gè)對(duì)象中的某個(gè)屬性
語法
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
// 傳遞props
export default {
setup(props) {
useSomeFeature(toRef(props, 'foo'))
}
}
9,toRefs 響應(yīng)式轉(zhuǎn)換
將響應(yīng)式對(duì)象轉(zhuǎn)換為普通對(duì)象她渴,其中結(jié)果對(duì)象的每個(gè)property
都是指向原始對(duì)象相應(yīng)property
的ref
語法
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
// 此時(shí)state和stateAsRefs是關(guān)聯(lián)的
10达址,shallowReactive 響應(yīng)式外層轉(zhuǎn)換
只處理對(duì)象最外層屬性的響應(yīng)式(淺響應(yīng)式)。適用于:一個(gè)對(duì)象數(shù)據(jù)惹骂,結(jié)構(gòu)比較深, 但變化時(shí)只是外層屬性變化
語法
const state = shallowReactive({
foo: 1,
nested: {
bar: 2
}
})
11苏携,shallowRef 基本數(shù)據(jù)響應(yīng)式
只處理基本數(shù)據(jù)類型的響應(yīng)式, 不進(jìn)行對(duì)象的響應(yīng)式處理做瞪。適用于:一個(gè)對(duì)象數(shù)據(jù)对粪,后續(xù)功能不會(huì)修改該對(duì)象中的屬性,而是生新的對(duì)象來替換
語法
const shallow = shallowRef({
greet: 'Hello, world'
})
12装蓬,readonly 響應(yīng)式變只讀
讓一個(gè)響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(深只讀)著拭,應(yīng)用于不希望數(shù)據(jù)被修改時(shí)
語法
const shallow = shallowRef({
greet: 'Hello, world', // 只讀
nested: {
bar: 2 // 只讀
}
})
13,shallowReadonly 響應(yīng)式變只讀
讓一個(gè)響應(yīng)式數(shù)據(jù)變?yōu)橹蛔x的(淺只讀)牍帚,應(yīng)用于不希望數(shù)據(jù)被修改時(shí)
語法
const shallow = shallowReadonly({
foo: 1, // 只讀
nested: {
bar: 2 // 非只讀
}
})
14儡遮,toRaw 響應(yīng)式變非響應(yīng)式
將一個(gè)由reactive生成的響應(yīng)式對(duì)象轉(zhuǎn)為普通對(duì)象,對(duì)這個(gè)普通對(duì)象的所有操作暗赶,不會(huì)引起頁面更新鄙币。
語法
const foo = {}
const Foo = reactive(foo)
console.log(toRaw(Foo) === foo) // true
15肃叶,markRaw 標(biāo)記永遠(yuǎn)不響應(yīng)式
標(biāo)記一個(gè)對(duì)象,使其永遠(yuǎn)不會(huì)再成為響應(yīng)式對(duì)象十嘿,有些值不應(yīng)被設(shè)置為響應(yīng)式的因惭,例如復(fù)雜的第三方類庫等,當(dāng)渲染具有不可變數(shù)據(jù)源的大列表時(shí)绩衷,跳過響應(yīng)式轉(zhuǎn)換可以提高性能蹦魔。
語法
const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false
// 嵌套在其他響應(yīng)式對(duì)象中時(shí)也可以使用
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
16,customRef 依賴更新控制
創(chuàng)建一個(gè)自定義的 ref咳燕,并對(duì)其依賴項(xiàng)跟蹤和更新觸發(fā)進(jìn)行顯式控制勿决。它需要一個(gè)工廠函數(shù),該函數(shù)接收track
和trigger
函數(shù)作為參數(shù)招盲,并且應(yīng)該返回一個(gè)帶有get
和set
的對(duì)象低缩。
語法
<script>
import { customRef } from 'vue'
export default {
name: 'Home',
setup() {
// 實(shí)現(xiàn)防抖函數(shù)
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 通信
實(shí)現(xiàn)祖與后代組件間通信宪肖,父組件有一個(gè)provide
選項(xiàng)來提供數(shù)據(jù)表制,后代組件有一個(gè)inject
選項(xiàng)來開始使用這些數(shù)據(jù)
語法
// 祖組件
setup(){
let car = reactive({ name:'奔馳', price:'40萬' })
provide('car', car)
}
// 后代組件
setup(props, context){
const car = inject('car')
return { car }
}
18,響應(yīng)式數(shù)據(jù)的判斷
18.1控乾,isRef
檢查一個(gè)值是否為一個(gè)ref
對(duì)象
語法
const val = ref('xxx')
isRef(val) // true
18.2么介,isReactive
檢查一個(gè)值是否為一個(gè)isReactive
對(duì)象
語法
const val = isReactive({})
isRef(val) // true
18.3,isReadonly
檢查一個(gè)對(duì)象是否是由readonly
創(chuàng)建的只讀代理
語法
const state = reactive({
name: 'John'
})
console.log(isReactive(state)) // true
18.4蜕衡,isProxy
檢查對(duì)象是否是由reactive
或readonly
創(chuàng)建的proxy
語法
const state = reactive({
name: 'John'
})
console.log(isProxy(state)) // true
19壤短,teleport 移動(dòng)dom組件
Teleport
提供了一種干凈的方法,允許我們控制在DOM
中哪個(gè)父節(jié)點(diǎn)下渲染了HTML
慨仿,而不必求助于全局狀態(tài)或?qū)⑵洳鸱譃閮蓚€(gè)組件久脯。
語法
<teleport to="移動(dòng)位置">
<div v-if="isShow" class="mask">
<div class="dialog">
<h3>我是一個(gè)彈窗</h3>
<button @click="isShow = false">關(guān)閉彈窗</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 異步渲染組件
等待異步組件時(shí)先渲染一些額外內(nèi)容镰吆,讓應(yīng)用有更好的用戶體驗(yàn)
語法
<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調(diào)整
將全局的API,即:Vue.xxx調(diào)整到應(yīng)用實(shí)例(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
名稱 | 現(xiàn)狀 |
---|---|
Vue.config.productionTip | 已移除 |
config.keyCodes | 已移除 |
$children | 已移除 |
$listeners | 已移除 |
$on | 已移除 |
$off | 已移除 |
$once | 已移除 |
filters | 已移除 |
.native | 已移除 |
23摧找,Ref 獲取DOM
由于V3
中不在存在this
,所以ref
的獲取調(diào)整了
23.1牢硅,單個(gè)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蹬耘,循環(huán)中的ref
V3
中在for
循環(huán)元素上綁定ref
將不再自動(dòng)創(chuàng)建$ref
數(shù)組。要從單個(gè)綁定獲取多個(gè)ref
减余,請(qǐng)將ref
綁定到一個(gè)更靈活的函數(shù)上
語法
<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
不必是數(shù)組:它也可以是一個(gè)對(duì)象综苔,其ref
可以通過迭代的key
被設(shè)置 - 如有需要,
itemRef
也可以是響應(yīng)式的,且可以被偵聽
24如筛,emits 自定義事件
定義一個(gè)組件可以向其父組件觸發(fā)的事件
// 在子組件中
<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 生命周期事件
通過事件來監(jiān)聽組件生命周期中的關(guān)鍵階段
語法
// V2的語法
<template>
<child-component @hook:updated="onUpdated">
</template>
// V3的語法
<template>
<child-component @vnode-updated="onUpdated">
</template>
// 駝峰寫法
<template>
<child-component @vnodeUpdated="onUpdated">
</template
如果看了覺得有幫助的杨刨,我是@鵬多多11997110103悴侵,歡迎 點(diǎn)贊 關(guān)注 評(píng)論;
END
PS:在本頁按F12拭嫁,在console中輸入document.querySelectorAll('._2VdqdF')[0].click()可免,有驚喜哦
往期文章
- 助你上手Vue3全家桶之Vue-Router4教程
- 助你上手Vue3全家桶之VueX4教程
- 超詳細(xì)!Vuex手把手教程
- 使用nvm管理node.js版本以及更換npm淘寶鏡像源
- 超詳細(xì)做粤!Vue-Router手把手教程
- vue中利用.env文件存儲(chǔ)全局環(huán)境變量浇借,以及配置vue啟動(dòng)和打包命令
- 微信小程序?qū)崿F(xiàn)搜索關(guān)鍵詞高亮
個(gè)人主頁