- Vue3 中文文檔 https://vue3js.cn/docs/zh/
- Vue3 設(shè)計理念 https://vue3js.cn/vue-composition/
- vue3優(yōu)點
- 性能提升(首次渲染更快, diff算法更快,內(nèi)存占用更少,打包體積更小)
- 更好的Typescript支持
- Composition API 組合式api(重點)
- vue3和vue2對比
- 實例方法$on移除 (eventBus現(xiàn)有實現(xiàn)模式不再支持 可以使用三方插件替代)
- 過濾器filter移除 (插值表達(dá)式里不能再使用過濾器 可以使用methods替代)
- .sync語法移除 (和v-model語法合并)
- vue3.0的單文件組件中不再強制要求必須有唯一根元素
更多閱讀:https://v3.cn.vuejs.org/guide/migration/introduction.html
vue3組件庫
- ant-design-vue
ant-design-vue 是 Ant Design 的 Vue 實現(xiàn)鞠抑,組件的風(fēng)格與 Ant Design 保持同步
網(wǎng)址:https://antdv.com/docs/vue/introduce-cn/
- element-plus(elementUi3.0適配)
Element Plus朽褪,一套為開發(fā)者法梯、設(shè)計師和產(chǎn)品經(jīng)理準(zhǔn)備的基于 Vue 3.0 的桌面端組件庫
網(wǎng)址:| https://element-plus.gitee.io/#/zh-CN |
- vant
有贊前端團(tuán)隊開源的移動端組件庫吃既,于 2016 年開源,已持續(xù)維護(hù) 4 年時間
網(wǎng)址:https://vant-contrib.gitee.io/vant/v3/#/zh-CN
- Naive UI
一個 Vue 3 組件庫比較完整脾歇,主題可調(diào)序六,使用 TypeScript跃须,不算太慢,有點意思
網(wǎng)址:https://www.naiveui.com/zh-CN/
- VueUse
基于composition組合api的常用集合球榆,小兔仙項目會部分使用
網(wǎng)址:https://vueuse.org/
組合式API
- 特定功能相關(guān)的所有東西都放到一起維護(hù)朽肥,比如功能A相關(guān)的響應(yīng)式數(shù)據(jù),操作數(shù)據(jù)的方法等放到一起持钉,這樣不管應(yīng)用多大衡招,都可以快讀定位到某個功能的所有相關(guān)代碼
-
維護(hù)方便,設(shè)置如果功能復(fù)雜每强,代碼量大始腾,我們還可以進(jìn)行邏輯拆分處理
特別注意:
- 選項式api和組合式api倆種風(fēng)格是并存的關(guān)系 并不是非此即彼
- 需要大量的邏輯組合的場景,可以使用compition API進(jìn)行增強
setup入口函數(shù)
- setup 函數(shù)是一個新的組件選項空执,作為組件中組合式API 的入口函數(shù)
- setup 中不能使用 this浪箭, this 指向 undefined
- setup函數(shù)只會在組件初始化的時候執(zhí)行一次
- setup函數(shù)在beforeCreate生命周期鉤子執(zhí)行之前執(zhí)行
export default {
setup () {
console.log('setup執(zhí)行了')
console.log(this)
},
beforeCreate() {
console.log('beforeCreate執(zhí)行了')
console.log(this)
}
}
響應(yīng)式API - reactive
- 作用:reactive是一個函數(shù),接收一個普通的對象傳入辨绊,把對象數(shù)據(jù)轉(zhuǎn)化為響應(yīng)式對象并返回
- 使用步驟
- 從vue框架中導(dǎo)入reactive函數(shù)
- 在setup函數(shù)中調(diào)用reactive函數(shù)并將對象數(shù)據(jù)傳入
- 在setup函數(shù)中把reactive函數(shù)調(diào)用完畢之后的返回值以對象的形式返回出去
<template>
<div>{{ state.name }}</div>
<div>{{ state.age }}</div>
<button @click="state.name = 'pink'">改值</button>
</template>
<script>
import { reactive } from 'vue' //引入reactive函數(shù)
export default {
setup () {
const state = reactive({ //在reactive函數(shù)中傳入對象
name: 'cp',
age: 18
})
return {
state
}
}
}
</script>
響應(yīng)式API - ref
- 作用:ref是一個函數(shù)奶栖,接受一個簡單類型或者復(fù)雜類型的傳入并返回一個響應(yīng)式且可變的 ref 對象
- 使用步驟
- 從vue框架中導(dǎo)出ref函數(shù)
- 在setup函數(shù)中調(diào)用ref函數(shù)并傳入數(shù)據(jù)(簡單類型或者復(fù)雜類型)
- 在setup函數(shù)中把ref函數(shù)調(diào)用完畢的返回值以對象的形式返回出去
- 注意:在setup函數(shù)中使用ref結(jié)果,需要通過.value 訪問邢羔,模板中使用不需要加.value
<template>
<div>{{ money }}</div>
<button @click="changeMondy">改值</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
let money = ref(100)
console.log(money.value)
return {
money
}
}
}
</script>
ref和reactive函數(shù)對比結(jié)論:
- ref 函數(shù)可以接收一個簡單類型的值驼抹,返回一個可改變的 ref 響應(yīng)式對象,從而彌補reactive函數(shù)不支持簡單類型的問題
- 只有我們明確知道要轉(zhuǎn)換的對象內(nèi)部的字段名稱我們才使用reactive拜鹤,否則就一律使用ref框冀,從而降低在語法選擇上的心智負(fù)擔(dān)
響應(yīng)式API - computed
- 作用:根據(jù)現(xiàn)有響應(yīng)式數(shù)據(jù)經(jīng)過一定的計算得到全新的數(shù)據(jù)
- 使用步驟
- 從vue框架中導(dǎo)入computed 函數(shù)
- 在setup函數(shù)中執(zhí)行computed函數(shù),并傳入一個函數(shù)敏簿,在函數(shù)中定義計算公式
- 把computed函數(shù)調(diào)用完的執(zhí)行結(jié)果放到setup的return值對象中
<template>
{{ list }}
{{ filterList }}
<button @click="changeList">change list</button>
</template>
<script>
import { computed, ref } from 'vue'
export default {
setup() {
const list = ref([1, 2, 3, 4, 5])
// 輸入大于3的數(shù)字
const filterList = computed(() => {
return list.value.filter(item => item > 3)
})
// 修改list的函數(shù)
function changeList() {
list.value.push(6, 7, 8)
}
return {
list,
filterList,
changeList
}
}
}
</script>
響應(yīng)式API - watch
- 作用:基于響應(yīng)式數(shù)據(jù)的變化執(zhí)行回調(diào)邏輯明也,和vue2中的watch的功能完全一致
- 普通監(jiān)聽
- 立即執(zhí)行
- 深度監(jiān)聽
- 使用步驟
- 從vue框架中導(dǎo)入watch函數(shù)
- 在setup函數(shù)中執(zhí)行watch函數(shù)開啟對響應(yīng)式數(shù)據(jù)的監(jiān)聽
- watch函數(shù)接收三個常規(guī)參數(shù)
- 第一個參數(shù)為函數(shù)宣虾,返回你要監(jiān)聽變化的響應(yīng)式數(shù)據(jù)
- 第二個參數(shù)為響應(yīng)式數(shù)據(jù)變化之后要執(zhí)行的回調(diào)函數(shù)
- 第三個參數(shù)為一個對象,在里面配置是否開啟立刻執(zhí)行或者深度監(jiān)聽
1)普通監(jiān)聽
<template>
{{ age }}
<button @click="age++">change age</button>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const age = ref(18)
watch(() => {
// 返回你想要監(jiān)聽的響應(yīng)式屬性(ref產(chǎn)生的對象必須加.value)
return age.value
}, () => {
// 數(shù)據(jù)變化之后的回調(diào)函數(shù)
console.log('age發(fā)生了變化')
})
return {
age
}
}
}
</script>
2)開啟立刻執(zhí)行
- watch的效果默認(rèn)狀態(tài)下温数,只有監(jiān)聽的數(shù)據(jù)發(fā)生變化才會執(zhí)行回調(diào)绣硝,如果你需要在一上來的時候就立刻執(zhí)行一次,需要配置一下immediate屬性
<template>
{{ age }}
<button @click="age++">change age</button>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const age = ref(18)
watch(() => {
// 返回你想要監(jiān)聽的響應(yīng)式屬性(ref產(chǎn)生的對象必須加.value)
return age.value
}, () => {
// 數(shù)據(jù)變化之后的回調(diào)函數(shù)
console.log('age發(fā)生了變化')
},{ immediate: true})
return {
age
}
}
}
</script>
3)開啟深度監(jiān)聽
- 當(dāng)我們監(jiān)聽的數(shù)據(jù)是一個對象的時候撑刺,默認(rèn)狀態(tài)下鹉胖,對象內(nèi)部的屬性發(fā)生變化是不會引起回調(diào)函數(shù)執(zhí)行的,如果想讓對象下面所有屬性都能得到監(jiān)聽够傍,需要開啟deep配置
- 注意: 使用watch的時候甫菠,盡量詳細(xì)的表明你到底要監(jiān)聽哪個屬性,避免使用deep引起的性能問題冕屯,
<template>
{{ name }}
{{ info.age }}
<button @click="name = 'pink'">change name</button>
<button @click="info.age++">change age</button>
</template>
<script>
import { reactive, toRefs, watch } from 'vue'
export default {
setup() {
const state = reactive({
name: 'cp',
info: {
age: 18
}
})
watch(() => {
return state
}, () => {
// 數(shù)據(jù)變化之后的回調(diào)函數(shù)
console.log('age發(fā)生了變化')
}, {
deep: true
})
return {
...toRefs(state)
}
}
}
</script>
生命周期函數(shù)
- 使用步驟
- 先從vue中導(dǎo)入以on打頭的生命周期鉤子函數(shù)
- 在setup函數(shù)中調(diào)用生命周期函數(shù)并傳入回調(diào)函數(shù)
- 生命周期鉤子函數(shù)可以調(diào)用多次
<template>
<div>生命周期函數(shù)</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
setup() {
// 時機成熟 回調(diào)函數(shù)自動執(zhí)行
onMounted(() => {
console.log('mouted生命周期執(zhí)行了')
})
onMounted(() => {
console.log('mouted生命周期函數(shù)又執(zhí)行了')
})
}
}
</script>
父子通信
- 實現(xiàn)步驟
- setup函數(shù)提供倆個參數(shù)寂诱,第一個參數(shù)為props,第二個參數(shù)為一個對象context
- props為一個對象安聘,內(nèi)部包含了父組件傳遞過來的所有prop數(shù)據(jù)痰洒,context對象包含了attrs,slots浴韭, emit屬性丘喻,其中的emit可以觸發(fā)自定義事件的執(zhí)行從而完成子傳父
app.vue
<template>
<son :name="name" @get-msg="getMsg"></son>
</template>
<script>
import { ref } from 'vue'
import Son from './components/son'
export default {
components: {
Son
},
setup() {
const name = ref('cp')
function getMsg(msg) {
console.log(msg)
}
return {
name,
getMsg
}
}
}
</script>
components/son.vue
<template>
<div>
{{name}}
<button @click="setMsgToSon">set</button>
</div>
</template>
<script>
export default {
props: {
name: {
type: String
}
},
emits: ['get-msg'], // 聲明當(dāng)前組件觸發(fā)的自定義事件
setup(props,{emit}) {
console.log(props.name)
function setMsgToSon(){
emit('get-msg','這是一條來自子組件的msg信息')
}
return {
setMsgToSon
}
}
}
</script>
provide 和 inject (組件傳值)
- provide 和 inject,它們配合起來可以完成從頂層組件向任意底層組件傳遞數(shù)據(jù)的效果,也可以傳遞響應(yīng)式數(shù)據(jù)
- 實現(xiàn)步驟
- 頂層組件在setup方法中使用provide函數(shù)提供數(shù)據(jù)
provide('key'囱桨,數(shù)據(jù)) - 任何底層組件在setup方法中使用inject函數(shù)獲取數(shù)據(jù)
const data = inject('key')
爺爺組件 - app.vue
<template>
<father></father>
</template>
<script>
import Father from '@/components/Father'
import { provide } from 'vue'
export default {
components: {
Father
},
setup() {
let name = '柴柴老師'
// 使用provide配置項注入數(shù)據(jù) key - value
provide('name', name)
}
}
</script>
孫組件 - components/Son.vue
<template>
我是子組件
{{ name }}
</template>
<script>
import { inject } from 'vue'
export default {
setup() {
const name = inject('name')
return {
name
}
}
}
</script>
TemplateRef(獲取組件實例)
- 實現(xiàn)步驟
- 使用ref函數(shù)傳入null創(chuàng)建 ref對象,并return接收的變量
const hRef = ref(null)
- 模板中通過定義ref屬性等于1中創(chuàng)建的ref對象名稱建立關(guān)聯(lián)
<h1 ref="hRef"></h1>
- 使用
hRef.value
components/RefComponent.vue
<template>
我是一個普通的組件
</template>
app.vue
<template>
<h1 ref="h1Ref">我是普通dom標(biāo)簽</h1>
<ref-comoonent ref="comRef"></ref-comoonent>
</template>
<script>
import { onMounted, ref } from 'vue'
import RefComoonent from '@/components/RefComponent'
export default {
components: {
RefComoonent
},
setup() {
const h1Ref = ref(null)
const comRef = ref(null)
onMounted(() => {
console.log(h1Ref.value)
console.log(comRef.value)
})
// 必須return
return {
h1Ref,
comRef
}
}
}
</script>