前言
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) } }
所以: 前端總是在路上,發展真的太瘋狂了,少年加油 學起來 !