前言
vue3.0 發布了,啊啊啊啊 刺激啊 (學哦)
博客平台、公眾號、朋友圈基本都被傳聞了,
可見 Vue3.0 的被期待程度,因為 React 16 發布的時候,也米有那么瘋狂,讓我有點震驚的是 Vue 有 130 萬的使用者。
其實在4月的時候就已經出來,只不過在9月的時候正式發布了,前面也學習了下3.0的語法糖,現在在看看
Vue3.0 更新了什么
一個是 Composition API,另一個是對 TypeScript 的全面支持。
團隊還會出一個 Vue 2.7 的版本,給予 2.x 用戶一些在 3.0 版本中被刪除方法的警告,這有助於用戶的平穩升級。
Nuxt3 好像還在路上,但是目前看來,市面上的各大組件庫還沒來得及針對 Vue3.0 進行改版升級。
周邊的插件如 Vue-Router、Vuex、VSCode 插件 Vetur 等都在有序的進行
vue3.0快速創建項目
1. 全局安裝create-vite-app
npm i -g create-vite-app
2.創建項目目錄
create-vite-app 項目名
3.運行
cd 項目名
npm install
npm run dev
4.查看
http://localhost:3000/
Vue3.0 變化在哪?
setup 函數
- 執行機制
setup是在創建組件實例並完成props初始化之后執行的,也是在beforeCreate鈎子之前執行,無法訪問option(data、comupted、methods等)選項,而option可使用setup中返回的變量。
-
沒有
this:在解析其他組件選項之前就已經調用了setup() -
接受兩個參數:
- props:組件傳參
- context:執行上下文,包含三個屬性方法:
attrs、slots、emit
export default { props: { user: { type: String, defalut: 'Libai' } }, setup(props, context) { console.log(props.user) console.log(context) } }
- 生命周期
其內部使用生命周期鈎子需要在前面加上on
因為 setup 是圍繞 beforeCreate 和 created 生命周期鈎子運行的,所以不需要顯式地定義它們。換句話說,在這些鈎子中編寫的任何代碼都應該直接在 setup 函數中編寫。
import { onMounted } from 'vue'
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
| 鈎子函數 | stup使用 |
|---|---|
| beforeCreate | 不支持 |
| created | 不支持 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
| errorCaptured | onErrorCaptured |
| renderTracked | onRenderTracked |
| renderTriggered | onRenderTriggered |
- 渲染函數
setup 還可以返回一個渲染函數,該函數可以直接使用在同一作用域中聲明的響應式狀態:
// MyBook.vue import { h, ref, reactive } from 'vue' export default { setup() { const readersNumber = ref(0) const book = reactive({ title: 'Vue 3 Guide' }) // Please note that we need to explicitly expose ref value here return () => h('div', [readersNumber.value, book.title]) } }
provide & inject
類似於vue2中provide與inject, vue3提供了對應的provide與inject API,實現組件傳參。
provide 函數允許你通過兩個參數定義 property:
- property 的 name (
<String>類型) - property 的 value
<!-- src/components/MyMap.vue --> <template> <MyMarker /> </template> <script> import { provide } from 'vue' import MyMarker from './MyMarker.vue' export default { components: { MyMarker }, setup() { provide('location', 'North Pole') provide('geolocation', { longitude: 90, latitude: 135 }) } } </script>
inject 函數有兩個參數:
- 要注入的
property的名詞 - 一個默認的值 (可選)
<!-- src/components/MyMarker.vue --> <script> import { inject } from 'vue' export default { setup() { const userLocation = inject('location', 'The Universe') const userGeolocation = inject('geolocation') return { userLocation, userGeolocation } } } </script>
應用的配置項
config 是一個包含 Vue 應用程序全局配置的對象。可以在掛載應用程序之前修改下面列出的屬性。
- devtools 類型: boolean 默認值: true 如何使用:
app.config.devtools = true
是否開啟 vue-devtools 工具的檢測,默認情況下開發環境是 true,生產環境下則為 false。
- errorHandler 類型: Function 默認值: undefined 如何使用:
app.config.errorHandler = (err, vm, info) => { // info 為 Vue 在某個生命周期發生錯誤的信息 }
為組件渲染功能和觀察程序期間的未捕獲錯誤分配處理程序。
- globalProperties 🌟 類型: [key: string]: any 默認值: undefined 如何使用:
app.config.globalProperties.name = '十三' app.component('c-component', { mounted() { console.log(this.name) // '十三' } })
若是組件內也有 name 屬性,則組建內的屬性權限比較高。
還有一個知識點很重要,在 Vue2.x 中,我們定義一個全局屬性或者方法都是如下所示:
Vue.prototype.$md5 = () => {}
在 Vue3.0 中,我們便可這樣定義:
const app = Vue.createApp({})
app.config.globalProperties.$md5 = () => {}
- performance 類型: boolean 默認值: false 如何使用:
app.config.performance = true
將其設置為 true 可在瀏覽器 devtool 性能/時間線面板中啟用組件初始化,編譯,渲染和補丁性能跟蹤。 僅在開發模式和支持 Performance.mark API的瀏覽器中工作。
Application API
全局改變的動作,都在 createApp 所創建的應用實例中,如下所示:
import { createApp } from 'vue'
const app = createApp({})
那么 app 下這些屬性:
- component 參數: 第一個參數 string 類型表示組件名,第二個參數 Function 或 Object 返回值: 只傳第一個參數,返回組建。帶上第二個參數則返回應用程序實例 如何使用:
import { createApp } from 'vue'
const app = createApp({})
// 注冊一個 options 對象
app.component('shisan-component', {
/* ... */
})
// 檢索注冊的組件
const ShiSanComponent = app.component('shisan-component')
- config(上面第一段講過了)
- directive 自定義指令變化不大,還是之前那些東西,如下:
app.directive('my-directive', {
// 掛載前
beforeMount() {},
// 掛載后
mounted() {},
// 更新前
beforeUpdate() {},
// 更新后
updated() {},
// 卸載前
beforeUnmount() {},
// 卸載后
unmounted() {}
})
多數全局API都沒變化,還是老的 2.x 的寫法居多
Composition API
Composition API解決了什么問題? 使用傳統的 Vue2.x 配置方法寫組件的時候問題,隨着業務復雜度越來越高,代碼量會不斷的加大。
- reactive
- watchEffect
- computed
- ref
- toRefs
- hooks
reactive
import { reactive, computed } from 'vue'
export default {
setup() {
const state = reactive({
a: 0
})
function increment() {
state.a++
}
return {
state,
increment
}
}
}
reactive 相當於 Vue2.x 的 Vue.observable () API,經過 reactive 處理后的函數能變成響應式的數據,類似之前寫模板頁面時定義的 data 屬性的值。
watchEffect
import { reactive, computed, watchEffect } from 'vue'
export default {
setup() {
const state = reactive({ a: 0 })
const double = computed(() => state.a * 3)
function increment() {
state.count++
}
const wa = watchEffect(() => {
// 使用到了哪個 ref/reactive 對象.value, 就監聽哪個
console.log(double.value)
})
// 可以通過 wa.stop 停止監聽
return {
state,
increment
}
}
}
watchEffect 被稱之為副作用,立即執行傳入的一個函數,並響應式追蹤其依賴,並在其依賴變更時重新運行該函數。
computed
import { reactive, computed } from 'vue'
export default {
setup() {
const state = reactive({
a: 0
})
const double = computed(() => state.a * 3)
function increment() {
state.a++
}
return {
double,
state,
increment
}
}
}
這就比較直觀了,computed 在 Vue2.x 就存在了,只不過現在使用的形式變了一下,需要被計算的屬性,通過上述形式返回。
與vue2中computed功能一致,它接收一個函數並返回一個value為getter返回值的不可改變的響應式ref對象。
const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // 錯誤,computed不可改變 // 同樣支持set和get屬性 onst count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: val => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0
ref 和 toRefs
toRefs 提供了一個方法可以把 reactive 的值處理為 ref,也就是將響應式的對象處理為普通對象。
hooks
與 2.x 版本相對應的生命周期鈎子
| Vue2.x 的生命周期 | Vue3.x 的生命周期 |
|---|---|
| beforeCreate | setup() |
| created | setup() |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
| errorCaptured | onErrorCaptured |
Vue3.0 在 Composition API 中另外加了兩個鈎子,分別是 onRenderTracked 和 onRenderTriggered,兩個鈎子函數都接收一個 DebuggerEvent :
export default { onRenderTriggered(e) { debugger // 檢查哪個依賴性導致組件重新渲染 }, }
代碼封裝、復用
Composition API 最核心的,就是可以把代碼提取出來,把整個功能封裝成一個單獨的函數(模塊),隨處可用,也不用擔心變量和方法的命名沖突。
只需在組件中導入模塊,並調用它即可(模塊返回的是函數),函數將返回我們定義的變量,隨后我們可以從 setup 函數中使用它們。
// useCount.js import { ref, computed } from 'vue' function useCount() { let count = ref(0) let double = computed(() => count.value * 2) function increment() { count.value++ } return { count, double, increment } } export default useCount // app.vue import useCount from './useCount.js' export default { setup() { let { count, double, increment } = useCount() return { count, double, increment } } }
兩者並存
option和Composition API是可以共用的,互不影響。
vue2中data、computed等選項仍然支持,但使用setup時不建議再使用vue2中的data等選項。
import { ref, computed } from 'vue'
export default {
setup() {
let count = ref(0)
let double = computed(() => count.value * 2)
function increment() {
count.value++
}
return {
count,
double,
increment
}
},
data() {
return {
a: 2
}
},
mounted() {
// 可使用setup的返回值
console.log(this)
}
}
所以: 前端總是在路上,發展真的太瘋狂了,少年加油 學起來 !
