Vue3 中有哪些值得深究的知識點?
眾所周知,前端技術一直更新很快,這不 vue3 也問世這么久了,今天就來給大家分享下vue3中值得注意的知識點。
1、createApp
vue2 和 vue3 在創建實例時,有很大的區別,具體對比如下:
- //Vue 2
- Vue.use({
- router,
- store,
- render:h=>h(App)
- }).$mount("#app")
- //Vue 3
- createApp(App).use(router).use(store).mount("#app")
vue2 創建實例,使用的是 new Vue() 對應的 router、store 都是其中一部分參數。
而 vue3 中,使用 createApp 創建應用實例,router、store 被當作插件通過鏈式調用。
在 vue2 中,創建多個實例的話,如果有 mixin、prototype 等時,容易造成實例污染。而 createApp 方法創建的是一個全新的實例,可以有效地避免這個問題。所以在vue3中,可以任意地創建多個實例。
2、setup
vue2 中選項式開發的,而 vue3 采用組合式開發,也可以向下兼容選項式開發。
setup 函數就是 vue3 中 Composition API 的入口,是處于生命周期鉤子函數 beforeCreate 和 created 兩個函數之間,所以 setup 中的屬性和方法無法在外部使用。如果需要使用的話,必須 return 暴露出去。
對比一下 vue2 和 vue3 中 data 和 method 使用區別:
- // vue2
- export default{
- data(){
- return{
- name:"熱愛前端的小姐姐"
- },
- methods:{
- print(){
- console.log("打印")
- }
- }
- }
- }
- // vue3
- export default{
- setup(){
- const name="熱愛前端的小姐姐"
- function print(){
- console.log("打印")
- }
- return { name , print }
- }
- }
vue2 中,this 是我們的常客,隨處可見它的蹤影。我們在 setup 中加入 this 的打印,試著查看下結果,發現運行結果是 undefined。
所以在 setup 內無法使用 this 以及掛載 this 相關的東西。
所以 setup 函數提供了兩個參數:
- setup(props,context){
- //props 是響應式數據,不能直接解構賦值
- //context 非響應式對象,可以直接解構使用
- // Attribute (非響應式對象)
- console.log(context.attrs)
- // 插槽 (非響應式對象)
- console.log(context.slots)
- // 觸發事件 (方法)
- console.log(context.emit)
- }
3、script setup 語法糖
簡化上述 setup 組合式 API 的寫法,屬于 vue3 的新語法糖。
特點:
- 定義的屬性和方法無需 return,可以直接使用。
- 自動注冊組件,不再需要 components 內注冊組件。
大大簡化上述 setup() 的代碼。
4、鉤子函數
vue2 使用生命周期函數時,直接使用就好了。如:
- // vue2
- export default{
- beforeCreate(){
- },
- mounted(){
- }
- }
但是在 vue3 組合式 API 中,通過生命周期鉤子前面加 on 來訪問,使用之前必須引入。如:
- // vue3
- <script setup>
- import { onMounted } from "vue"
- onMounted(()=>{
- })
- </script>
由于 setup 是圍繞 beforeCreate 和 created 生命周期鉤子運行的,所以在 setup 內不需要這兩個鉤子函數,剩余的都是一樣的。
官方提供生命周期鉤子:

5、teleport 傳送門
teleport 傳送門可以把內部的元素綁定到任意父元素上,使用方式簡單靈活。
使用方式:
- <teleport to="body"></teleport>
to 屬性是指定 teleport 中內容加入的 DOM 元素,可以是標簽名、類名或 id 。
- //標簽名 。上述實例就是加入body元素內,使用的是標簽名。
- <teleport to="body"></teleport>
- //類名。如:to=".className"
- <teleport to=".className"></teleport>
- //id名
- <teleport to="#idName"></teleport>
優點:多個組件嵌套層次過多時,樣式層級處理麻煩,使用 teleport 可以把元素剝離出來,設置樣式方便,同時 vue 控制狀態也方便。
6、mixin 混入
mixin 對象會把多個組件公用的選項提取出來,需要的組件內引入,管理方便。在 vue3 中 mixin 使用較少。
使用方式:
- <script>
- const myMixin = {
- data(){
- return {name:'熱愛前端的小姐姐'}
- }
- }
- export default {
- mixins:[myMixin],
- data(){
- return {
- qdr:"前端人"
- }
- }
- }
- </script>
使用時,可以引入多個 mixin 對象。使用注意事項:
- mixin 對象與組件包含相同選項時,會自動合并。
- mixin 對象與組件相同選項內擁有相同屬性時,就近原則,優先繼承實例內的值。
- mixin 和組件包含相同的鉤子函數時,會合并執行,優先執行 mixin 中的鉤子函數。
- mixin 自定義屬性與實例中沖突時,可以通過 optionMergeStrategies 定義優先級。
7、自定義指令
全局自定義指令:
vue2 的 directive 掛載到 Vue 對象上。
vue3 的 directive 掛載到 app 上,如:
- //Vue 2
- Vue.directive('name',opt)
- //Vue 3
- const app = createApp(App)
- app.directive("name",options)
- app.mount("#app")
局部自定義指令:與 vue2 寫法相同。
在 vue3 中自定義指令生命周期鉤子函數有一部分改變,鉤子函數分別為:
- created
- beforeMounted
- mounted
- beforeUpdate
- updated
- beforeUnmounted
- unmounted
8、ref、reactive
ref 作用是讓基礎類型數據具備響應式。
reactive 讓引用數據類型具備響應式能力。
ref 和 reactive 包裹數據,使數據具備響應式,在使用之前需要先引入。
使用方法如:
- <script setup>
- import { ref , reactive } from "vue"
- let mood = ref("value")
- let me = reactive({
- str:value,
- })
- </script>
setup + ref + reactive 就可以實現 vue2 中 data 的響應式功能,所以 setup 能夠替換掉 data 。
9、toRefs、toRef
toRefs 解構 props 傳遞的數據,由于父向子組件通過 props 傳值是響應式的,使用 ES6 解構會消除響應特性,所以使用 toRefs 。
- <script setup>
- const props = defineProps({
- selectNum:Number,
- allNum:Number,
- })
- const { selectNum, allNum } = toRefs(props)
- </script>
toRef 也是解構數據,主要是對可選參數處理,運行時先檢查 解構的數據中是否存在該屬性,如果存在就繼承,不存在則會創建一個屬性,這樣就不會報錯了。
- const str = toRef( props, 'str' )
10、watch、watchEffect 新用法
watch 、watchEffect 都是偵聽器。
watch 會監聽某個基礎類型數據或引用數據類型的某個具體屬性。
vue3 使用 watch 之前,必須引入。
- //vue2
- watch:{
- mood(curVal,preVal){
- console.log('cur',curVal);//最新值
- console.log('pre',preVal);//修改之前的值
- }
- }
- //vue3
- import { watch } from "vue"
- watch(
- name ,
- ( curVal , preVal )=>{ //業務處理 },
- options
- )
watchEffect 監聽的是引用數據類型的所有屬性,不需要指定是哪個具體的屬性,一旦運行,就會立刻執行。
watchEffect 使用之前也必須引入。
- import { watchEffect } from "vue"
- let obj = reactive({ name:'qq',sex:'女'})
- watchEffect(() => {
- console.log('name',obj.name);
- console.log('sex' , obj.sex);
- })
watch 與 watchEffect 對比:
- watch 運行的時候不會立刻執行, watchEffect 立即執行。
- watch 更加具體,需要指定監聽的誰,watchEffect 不要執行具體監聽誰,回調函數內直接使用就可以,比較抽象。
- watch 回調內可以訪問到修改之前的值,watchEffect 只能訪問最新的值。
- watch 可通過配置實現 watchEffect 的前兩個特性。
11、computed 新用法
computed 計算屬性
選項式 API 中 vue2 和 vue3 使用相同。
組合式 API 中,使用之前需要引入。
- // 選項式
- computed:{
- sum(){
- return this.num1+ this.num2
- }
- }
- //組合式
- import { ref, computed } from "vue"
- export default{
- setup(){
- const num1 = ref(1)
- const num2 = ref(1)
- let sum = computed(()=>{
- return num1.value + num2.value
- })
- }
- }
或者,它可以使用一個帶有 get 和 set 函數的對象來創建一個可寫的對象。
- let mul = computed({
- get:()=>{
- return num1.value *10
- },
- set:(value)=>{
- return num1.value = value/10
- }
- })
在vue3.2+內,computed 可接受一個帶有 onTrack 和 onTrigger 選項的對象作為第二個參數:
- onTrack 會在某個響應式 property 或 ref 作為依賴被追蹤時調用。
- onTrigger 會在偵聽回調被某個依賴的修改觸發時調用。
12、provide / inject
provide/inject 類似于消息的訂閱和發布,provide 提供或發送數據或方法, inject 接收數據或方法。
優點:組件嵌套層級較多,父組件向子組件、多個孫組件傳值時,傳遞數據需要一級一級向下傳遞,比較麻煩,使用 project 和 inject 很方便地解決了這個問題。
- //vue2
- export default{
- provide:{
- info:"提供數據"
- }
- }
- //接收數據
- export default{
- inject:['info'],
- mounted(){
- console.log("接收數據:", this.info) // 接收數據:提供數據
- }
- }
- //vue3
- <script setup>
- import { provide } from "vue"
- provide( 'info', "值" )
- </script>
- //接收數據
- <script setup>
- import { inject } from "vue"
- const info = inject( 'info', "設置默認值" )
- </script>
13、readonly
readonly 只讀函數,使用之后該數據只能使用,不能修改,修改時會有警告。
父子組件之間傳值時,如果傳遞的是響應式數據,子組件修改的時候,父組件的也會更新,這樣就容易造成狀態混亂,不符合 vue 的單項數據流。
如果使用 readonly ,保證數據在其他組件內只能使用,并不能修改,規避混亂。
14、獲取真實DOM
vue2 使用 $ref 獲取真實DOM。
vue3 使用 ref 獲取真實DOM。與上述的 ref 不同。
- <div ref="box" class="test" id="boxtest">獲取真實DOM</div>
- //vue2
- <script>
- export default{
- mounted(){
- console.log('box', this.$refs.box);
- }
- }
- </script>
- //vue3
- <script setup>
- const box = ref(null)
- onMounted(()=>{
- console.log('box',box.value);
- })
- </script>
15、vue3 中的 vuex4
createStore 函數創建新的 store 實例。使用之前需要先引入。
- import { createApp } from 'vue'
- import App from './App.vue'
- import { createStore } from "vuex"
- const store = createStore({
- state(){
- return{
- num:1,
- }
- }
- })
- const app = createApp(App)
- app.use(store)
- app.mount('#app')
組件內使用 store 時,通過 useStore 引入,使用之前也需要引入。
- import { useStore } from "vuex"
- const store = useStore()
使用的時候,與低版本都是一樣的。使用 state 內數據時,可以通過 toRefs 解構。
16、v-slot
v-slot 指令只能用在 template 或組件上,否則就會報錯。
簡化 slot、slot-scope 作用域插槽的功能,相比更加強大,代碼效率更高。
使用:
- <child-com>
- <template v-slot:header>
- 頭部
- </template>
- <template v-slot:body>
- 內容
- </template>
- </child-com>
簡寫:
- <child-com>
- <template #header>
- 頭部
- </template>
- <template #body>
- 內容
- </template>
- </child-com>
17、vue3 中的 vue-router4
createRouter 創建 router 實例,之前的 mode 改為 history 。
- import { createRouter,createWebHashHistory } from "vue-router";
- const routes = []
- const router = createRouter({
- history:createWebHashHistory('/'),
- routes
- })
- export default router
在 main.js 內引入的時候,通過 use 引用。
- import { createApp } from 'vue'
- import App from './App.vue'
- import router from "./router/index"
- const app = createApp(App)
- app.use(router)
- app.mount('#app')
關于 vue-router4 更新挺多的,更多知識請閱讀《 vue-router 4 你真的熟練嗎?》文章。
18、render
在 vue3 中,render 函數的參數發生了改變,之前的 h 去掉,變成全局引入,虛擬節點具備扁平的屬性結構。
vue3中 render 應用
- import { h } from "vue"
- export default {
- render(){
- return h("div", {}, content)
- }
- }
【編輯推薦】