最全系列的vue3入門教程『圖文并茂』

點(diǎn)擊在線閱讀饮醇,體驗(yàn)更好 鏈接
現(xiàn)代JavaScript高級小冊 鏈接
深入淺出Dart 鏈接
現(xiàn)代TypeScript高級小冊 鏈接
linwu的算法筆記?? 鏈接

Vue 3 簡介

Vue 3 是一個(gè)流行的開源JavaScript框架茧球,用于構(gòu)建用戶界面和單頁面應(yīng)用切黔。它帶來了許多新特性和改進(jìn)摔敛,包括更好的性能翼雀、更小的打包大小欢峰、更好的TypeScript支持瓦呼、全新的組合式 API,以及一些新的內(nèi)置組件庐椒。

1. Vue 3 的新特性

Vue 3引入了許多新特性椒舵,包括:

  • 組合式API:這是Vue 3最重要的新特性之一,它允許更靈活约谈、更邏輯化地組織代碼笔宿。
  • 更好的性能:Vue 3的虛擬DOM重寫,提供了更快的掛載棱诱、修補(bǔ)和渲染速度泼橘。
  • 更小的打包大小:由于新的架構(gòu)和樹搖技術(shù)迈勋,Vue 3的打包大小比Vue 2小炬灭。
  • 更好的TypeScript支持:Vue 3在內(nèi)部使用了TypeScript,因此它為開發(fā)者提供了更好的TypeScript支持靡菇。

2. 與 Vue 2 的區(qū)別

Vue 3與Vue 2的主要區(qū)別包括:

  • 構(gòu)建:Vue 3使用monorepo架構(gòu)重归,更容易管理和維護(hù)。
  • API:Vue 3引入了新的組合式API厦凤,它提供了更靈活的代碼組織方式鼻吮。
  • 性能:Vue 3提供了更好的性能,包括更快的渲染速度和更小的打包大小较鼓。
  • TypeScript:Vue 3提供了更好的TypeScript支持狈网。

3. 全新的核心架構(gòu)

Vue 3的核心架構(gòu)進(jìn)行了全面的重寫和優(yōu)化,以提高性能和靈活性。此外拓哺,Vue 3還引入了許多新的API和組件勇垛,以滿足現(xiàn)代web開發(fā)的需求。

基礎(chǔ)

1. 創(chuàng)建 Vue 3 項(xiàng)目

首先士鸥,我們需要通過Vite創(chuàng)建一個(gè)新的Vue 3項(xiàng)目闲孤。你可以通過下面的命令安裝Vite:

pnpm create vite

然后,你可以通過下面的命令創(chuàng)建一個(gè)新的Vue 3項(xiàng)目:

pnpm create vite my-vue-app --template vue-ts

2. 應(yīng)用和組件編寫

在Vue 3中烤礁,我們可以使用新的組合式API創(chuàng)建和管理組件讼积。下面是一個(gè)簡單的Vue 3組件示例:

<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const increment = () => { count.value++ }

    return {
      count,
      increment
    }
  }
}
</script>

在這個(gè)示例中,我們首先導(dǎo)入了 ref 函數(shù)脚仔,然后在 setup 函數(shù)中使用 ref 創(chuàng)建了一個(gè)響應(yīng)式值 count勤众。我們還定義了一個(gè) increment 函數(shù),用于增加 count 的值鲤脏。最后们颜,我們將 countincrement 返回給模板,以便在模板中使用它們猎醇。

響應(yīng)式系統(tǒng)

1. 響應(yīng)式原理


Vue的響應(yīng)式系統(tǒng)是其核心特性之一窥突,它使得數(shù)據(jù)變更能夠自動(dòng)更新到UI上缝左。在Vue 3中褒链,這個(gè)系統(tǒng)基于JavaScript的 Proxy 對象重寫,提供了更好的性能和更多的功能部默。

2. ref 和 reactive

Vue 3提供了兩個(gè)主要的函數(shù)來創(chuàng)建響應(yīng)式數(shù)據(jù):refreactive沦疾。

ref 函數(shù)創(chuàng)建一個(gè)響應(yīng)式引用称近。在模板中,你可以直接使用響應(yīng)式引用的值哮塞,而在JavaScript代碼中煌茬,你需要通過 .value 屬性來訪問或修改它的值。

import { ref } from 'vue'

const count = ref(0)
console.log(count.value) // 0
count.value++ // 1

reactive 函數(shù)創(chuàng)建一個(gè)響應(yīng)式對象彻桃。你可以直接訪問和修改它的屬性。

import { reactive } from 'vue'

const state = reactive({ count: 0 })
console.log(state.count) // 0
state.count++ // 1

3. 實(shí)現(xiàn)機(jī)制區(qū)別

refreactive 的主要區(qū)別在于晾蜘,ref 是為了讓基本類型(如數(shù)字和字符串)可以變?yōu)轫憫?yīng)式邻眷,而 reactive 是為了讓對象變?yōu)轫憫?yīng)式。

ref 創(chuàng)建的響應(yīng)式數(shù)據(jù)需要通過 .value 屬性進(jìn)行訪問和修改剔交,而 reactive 創(chuàng)建的響應(yīng)式對象可以直接訪問和修改其屬性肆饶。因此,ref 更適合于處理基本類型岖常,而 reactive 更適合于處理對象驯镊。

組合式 API


組合式API是Vue 3的重要新特性,它提供了一種更靈活、更邏輯化的方式來組織和復(fù)用代碼板惑。

1. setup 函數(shù)

在Vue 3中橄镜,你可以使用 setup 函數(shù)來使用組合式API。setup 函數(shù)是組件的入口點(diǎn)冯乘,在組件實(shí)例被創(chuàng)建和初始化之后洽胶,但在渲染發(fā)生之前被調(diào)用。

export default {
  setup() {
    // 在這里使用組合式 API
  }
}

2. 響應(yīng)式編程

你可以在 setup 函數(shù)中使用 refreactive 來創(chuàng)建響應(yīng)式數(shù)據(jù)裆馒。

import

 { ref, reactive } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const state = reactive({ name: 'Vue' })

    return {
      count,
      state
    }
  }
}

3. 計(jì)算屬性與監(jiān)視

你可以使用 computedwatch 來創(chuàng)建計(jì)算屬性和監(jiān)視響應(yīng)式數(shù)據(jù)的變化姊氓。

import { ref, computed, watch } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const doubled = computed(() => count.value * 2)

    watch(count, (newValue, oldValue) => {
      console.log(`count changed from ${oldValue} to ${newValue}`)
    })

    return {
      count,
      doubled
    }
  }
}

4. 生命周期鉤子


你可以在 setup 函數(shù)中使用生命周期鉤子,比如 onMounted喷好、onUpdatedonUnmounted翔横。

import { onMounted, onUpdated, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('component mounted')
    })

    onUpdated(() => {
      console.log('component updated')
    })

    onUnmounted(() => {
      console.log('component unmounted')
    })
  }
}

5. 自定義 hooks

你可以創(chuàng)建自定義的hooks來復(fù)用代碼。一個(gè)自定義hook就是一個(gè)函數(shù)梗搅,它可以使用其他的響應(yīng)式數(shù)據(jù)和組合式API禾唁。

import { ref, onMounted } from 'vue'

function useCounter() {
  const count = ref(0)

  const increment = () => {
    count.value++
  }

  onMounted(() => {
    console.log('counter mounted')
  })

  return {
    count,
    increment
  }
}

export default {
  setup() {
    const counter = useCounter()

    return {
      counter
    }
  }
}

高級功能

1. 淺層響應(yīng)式

在某些情況下,你可能想要?jiǎng)?chuàng)建一個(gè)淺層的響應(yīng)式對象些膨,這樣其內(nèi)部的屬性不會被轉(zhuǎn)化為響應(yīng)式的蟀俊。這可以通過 shallowReactive 函數(shù)來實(shí)現(xiàn)。

import { shallowReactive } from 'vue'

const state = shallowReactive({ count: 0 })

2. 只讀數(shù)據(jù)

你可以使用 readonly 函數(shù)來創(chuàng)建一個(gè)只讀的響應(yīng)式對象订雾。任何試圖修改只讀對象的操作都將在開發(fā)環(huán)境下引發(fā)一個(gè)錯(cuò)誤肢预。

import { readonly } from 'vue'

const state = readonly({ count: 0 })

3. 自定義 Ref

你可以使用 customRef 函數(shù)來創(chuàng)建一個(gè)自定義的響應(yīng)式引用。這允許你控制和觀察當(dāng)引用的值發(fā)生變化時(shí)的行為洼哎。

import { customRef } from 'vue'

const count = customRef((track, trigger) => {
  let value = 0

  return {
    get() {
      track()
      return value
    },
    set(newValue) {
      value = newValue
      trigger()
    }
  }
})

4. toRefs 和 toRef

當(dāng)我們從 setup 函數(shù)返回一個(gè)響應(yīng)式對象時(shí)烫映,對象的屬性將失去響應(yīng)式。為了防止這種情況噩峦,我們可以使用 toRefstoRef 函數(shù)锭沟。

import { reactive, toRefs } from 'vue'

export default {
  setup() {
    const state = reactive({ count: 0 })

    return {
      ...toRefs(state)
    }
  }
}

新組件

1. Fragment

在Vue 3中,你可以在一個(gè)組件的模板中有多個(gè)根節(jié)點(diǎn)识补,這被稱為 Fragment族淮。

<template>
  <div>Hello</div>
  <div>World</div>
</template>

2. Teleport

Teleport 組件允許你將子組件渲染到DOM的任何位置,而不僅僅是它的父組件中凭涂。

<teleport to="#modal">
  <div>This will be rendered wherever the #modal element is.</div>
</teleport>

3. Suspense

Suspense 組件允許你等待一個(gè)或多個(gè)異步組件祝辣,然后顯示一些備用內(nèi)容,直到所有的異步組件都被解析切油。

<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

深入編譯優(yōu)化

Vue 3在編譯優(yōu)化上做出了很大的提升蝙斜。在編譯過程中,Vue 3對模板進(jìn)行靜態(tài)分析澎胡,提取出不會改變的部分孕荠,預(yù)編譯為純JavaScript娩鹉,這大大提高了運(yùn)行時(shí)的渲染效率。下面詳細(xì)介紹一下這些優(yōu)化稚伍。

靜態(tài)節(jié)點(diǎn)提升

在 Vue 3 中弯予,如果你的模板中有不會改變的部分,例如:

<template>
  <div>
    <h1>Hello, world!</h1>
    <p>Welcome to Vue 3</p>
  </div>
</template>

在編譯時(shí)槐瑞,"Hello, world!" 和 "Welcome to Vue 3" 這些靜態(tài)節(jié)點(diǎn)將會被提升熙涤,避免了每次渲染時(shí)都需要重新創(chuàng)建。

片段困檩、模板并用

在 Vue 3 中祠挫,你可以在一個(gè)組件模板中有多個(gè)根節(jié)點(diǎn),這就是片段:

<template>
  <header>Header</header>
  <main>Main content</main>
  <footer>Footer</footer>
</template>

在這個(gè)示例中悼沿,我們有三個(gè)根節(jié)點(diǎn)等舔,這在 Vue 2 中是不允許的。但在 Vue 3 中糟趾,這是完全正常的慌植。

動(dòng)態(tài)編譯

Vue 3 的動(dòng)態(tài)編譯可以讓我們在運(yùn)行時(shí)編譯模板字符串,例如义郑,我們可以動(dòng)態(tài)創(chuàng)建一個(gè)Hello組件

import { compile, h } from 'vue'

const template = `<h1>{{ greeting }} World!</h1>`

const render = compile(template)

export default {
  data() {
    return {
      greeting: 'Hello',
    }
  },
  render
}

在這個(gè)例子中蝶柿,我們在運(yùn)行時(shí)編譯了模板字符串,并將結(jié)果設(shè)置為組件的渲染函數(shù)非驮。這種技術(shù)在需要?jiǎng)討B(tài)生成模板的場景中非常有用交汤,比如在一個(gè) CMS 中渲染用戶提供的模板。

深入組件化

Vue 3在組件化方面也有很多進(jìn)步劫笙,下面詳細(xì)介紹一下芙扎。

動(dòng)態(tài)組件

Vue 3支持使用component標(biāo)簽來動(dòng)態(tài)加載組件,組件可以是一個(gè)組件選項(xiàng)對象填大,也可以是一個(gè)組件的名字戒洼。這個(gè)特性在根據(jù)不同的狀態(tài)顯示不同組件時(shí)非常有用。

<component :is="currentComponent"></component>

異步組件

Vue 3 支持異步組件允华,你可以使用defineAsyncComponent方法來定義一個(gè)異步組件圈浇,該方法接收一個(gè)返回 Promise 的工廠函數(shù),Promise 需要解析為一個(gè)組件靴寂。

import { defineAsyncComponent } from 'vue'

const AsyncComponent = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

高階組件

高階組件(Higher-Order Component磷蜀,簡稱 HOC)是一種設(shè)計(jì)模式,它是接收一個(gè)組件并返回一個(gè)新組件的函數(shù)榨汤。在 Vue 3 中,你可以使用組合式 API 來更容易地創(chuàng)建高階組件怎茫。

import { ref } from 'vue'

export default function withHover(Component) {
  return {
    setup(props, { slots }) {
      const isHovered = ref(false)

      return () => (
        <div
          onMouseenter={() => (isHovered.value = true)}
          onMouseleave={() => (isHovered.value = false)}
        >
          <Component {...props} isHovered={isHovered.value} v-slots={slots} />
        </div>
      )
    }
  }
}

在這個(gè)例子中收壕,withHover 函數(shù)接收一個(gè)組件妓灌,并返回一個(gè)新的組件,新的組件有一個(gè) isHovered 屬性蜜宪,表示鼠標(biāo)是否懸停在組件上虫埂。這種模式可以幫助我們在不同的組件間復(fù)用邏輯。

其它組合API

computed

computed 函數(shù)用于創(chuàng)建一個(gè)響應(yīng)式的計(jì)算屬性圃验。這個(gè)屬性的值是由提供的 getter 函數(shù)計(jì)算得出掉伏,并且只有當(dāng)它的依賴項(xiàng)改變時(shí)才會重新計(jì)算。

import { ref, computed } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const doubleCount = computed(() => count.value * 2)

    return {
      count,
      doubleCount
    }
  }
}

在這個(gè)示例中澳窑,我們創(chuàng)建了一個(gè) doubleCount 計(jì)算屬性斧散,它的值始終是 count 的兩倍。

watch 和 watchEffect

watchwatchEffect 函數(shù)用于觀察一個(gè)或多個(gè)響應(yīng)式引用或函數(shù)摊聋,并在其值改變時(shí)執(zhí)行副作用鸡捐。

import { ref, watch, watchEffect } from 'vue'

export default {
  setup() {
    const count = ref(0)

    watch(count, (newCount, oldCount) => {
      console.log(`Count changed from ${oldCount} to ${newCount}`)
    })

    watchEffect(() => {
      console.log(`Count is ${count.value}`)
    })

    return {
      count
    }
  }
}

在這個(gè)示例中,我們使用 watch 函數(shù)觀察 count麻裁,并在其值改變時(shí)打印消息箍镜。我們還使用 watchEffect 函數(shù)創(chuàng)建了一個(gè)副作用,它會在 count 改變時(shí)立即執(zhí)行煎源。

lifecycle hooks

在 Vue 3 中色迂,你可以在 setup 函數(shù)中直接使用生命周期鉤子函數(shù),例如 onMounted手销,onUpdatedonUnmounted歇僧。

import { onMounted, onUpdated, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('Component is mounted')
    })

    onUpdated(() => {
      console.log('Component is updated')
    })

    onUnmounted(() => {
      console.log('Component is unmounted')
    })
  }
}

在這個(gè)示例中,我們在組件掛載原献、更新和卸載時(shí)打印消息馏慨。

這些是 Vue 3 中提供的更為高級的響應(yīng)式 API,讓我們逐一了解它們姑隅。

shallowReactive 與 shallowRef

shallowReactiveshallowRef 允許我們創(chuàng)建一個(gè)淺層的響應(yīng)式對象写隶。對于 shallowReactive,只有對象的第一層屬性會變?yōu)轫憫?yīng)式的讲仰,對象的更深層次的屬性不會被轉(zhuǎn)換慕趴。shallowRefref 的淺層版本,它不會自動(dòng)解包內(nèi)部的值鄙陡。

import { shallowReactive, shallowRef } from 'vue'

const obj = shallowReactive({ a: { b: 1 } })
obj.a.b // 這不是一個(gè)響應(yīng)式的值

const num = shallowRef(1)
num.value // 你需要使用 .value 才能訪問到值

readonly 與 shallowReadonly

readonlyshallowReadonly 允許我們創(chuàng)建一個(gè)只讀的響應(yīng)式對象冕房。對于 readonly,對象的所有屬性(包括嵌套屬性)都會變?yōu)橹蛔x趁矾。shallowReadonlyreadonly 的淺層版本耙册,只有對象的第一層屬性會變?yōu)橹蛔x。

import { readonly, shallowReadonly } from 'vue'

const obj = readonly({ a: { b: 1 } })
obj.a = 2 // 這會拋出一個(gè)錯(cuò)誤

const shallowObj = shallowReadonly({ a: { b: 1 } })
shallowObj.a.b = 2 // 這不會拋出錯(cuò)誤

toRaw 與 markRaw

toRawmarkRaw 允許我們逃避 Vue 的響應(yīng)式系統(tǒng)毫捣。toRaw 可以返回一個(gè)對象的原始版本详拙,而 markRaw 可以防止一個(gè)對象被轉(zhuǎn)換為響應(yīng)式的帝际。

import { reactive, toRaw, markRaw } from 'vue'

const obj = reactive({ a: 1 })
const rawObj = toRaw(obj) // rawObj 是 obj 的原始版本

const nonReactiveObj = markRaw({ a: 1 }) // nonReactiveObj 不會被轉(zhuǎn)換為響應(yīng)式的

customRef

customRef 允許我們創(chuàng)建一個(gè)自定義的 ref,我們可以控制它何時(shí)觸發(fā)依賴追蹤和更新饶辙。

import { customRef } from 'vue'

const myRef = customRef((track, trigger) => ({
  get() {
    track()
    return someValue
  },
  set(newValue) {
    someValue = newValue
    trigger()
  }
}))

provide 與 inject


provideinject 是 Vue 3 的依賴注入 API蹲诀,可以用于在組件樹中傳遞值,而不必一層一層地通過 props 傳遞弃揽。

import { provide, inject } from 'vue'

// 在父組件中
provide('myValue', 123)

// 在子組件中
const myValue = inject('myValue') // myValue 現(xiàn)在是 123

響應(yīng)式判斷

Vue 3 提供了 isReactiveisRef 函數(shù)脯爪,用于檢查一個(gè)值是否是響應(yīng)式的或者一個(gè) ref。

import { reactive, ref, isReactive, isRef } from 'vue'

const obj = reactive({ a: 1 })
isReactive(obj) // true

const num = ref(1)
isRef(num) // true

這些 API 提供了更多的控制和靈活性矿微,使我們能夠根據(jù)需要來選擇如何使用 Vue 的響應(yīng)式系統(tǒng)痕慢。

深入響應(yīng)式系統(tǒng)

Vue 3 的響應(yīng)式系統(tǒng)構(gòu)建在一個(gè)名為 effect 的函數(shù)基礎(chǔ)之上,它被用來收集依賴項(xiàng)(依賴追蹤)和觸發(fā)副作用冷冗。當(dāng)一個(gè)響應(yīng)式對象的屬性被訪問時(shí)守屉,effect 將其收集為依賴項(xiàng);當(dāng)一個(gè)響應(yīng)式對象的屬性被修改時(shí)蒿辙,它將觸發(fā)關(guān)聯(lián)的副作用拇泛。

effect、reactive思灌、ref

reactiveref 是 Vue 3 的兩種基本響應(yīng)式 API俺叭。它們都使用 effect 來跟蹤依賴項(xiàng)和觸發(fā)更新。

import { effect, reactive, ref } from 'vue'

// 使用 reactive
const state = reactive({ a: 1 })

effect(() => {
  console.log(state.a)
})

state.a = 2 // 打印 "2"

// 使用 ref
const count = ref(0)

effect(() => {
  console.log(count.value)
})

count.value++ // 打印 "1"

在這個(gè)示例中泰偿,我們創(chuàng)建了一個(gè)響應(yīng)式對象和一個(gè) ref熄守,然后使用 effect 創(chuàng)建了兩個(gè)副作用,它們分別打印出對象和 ref 的值耗跛。當(dāng)這些值被改變時(shí)裕照,副作用就會被觸發(fā)。

track调塌、trigger

tracktrigger 是 Vue 3 的底層 API晋南,它們分別被用來收集依賴項(xiàng)和觸發(fā)更新。

import { reactive, effect, track, trigger } from 'vue'

const state = reactive({ a: 1 })

effect(() => {
  // 手動(dòng)進(jìn)行依賴追蹤
  track(state, 'a')
  console.log(state.a)
})

state.a = 2 // 打印 "2"

// 手動(dòng)觸發(fā)更新
trigger(state, 'a')

在這個(gè)示例中羔砾,我們使用 track 手動(dòng)收集了 state.a 作為依賴項(xiàng)负间,然后使用 trigger 手動(dòng)觸發(fā)了更新。

嵌套結(jié)構(gòu)處理

Vue 3 的響應(yīng)式系統(tǒng)可以處理嵌套的響應(yīng)式對象姜凄。

import { reactive, effect } from 'vue'

const state = reactive({
  user: {
    name: 'Alice'
  }
})

effect(() => {
  console.log(state.user.name)
})

state.user.name = 'Bob' // 打印 "Bob"

在這個(gè)示例中政溃,我們創(chuàng)建了一個(gè)嵌套的響應(yīng)式對象,并使用 effect 創(chuàng)建了一個(gè)副作用态秧,它打印出用戶的名字董虱。當(dāng)用戶的名字被改變時(shí),副作用就會被觸發(fā)申鱼。

Render 函數(shù)


在 Vue 3 中愤诱,Render 函數(shù)是一種提供了更大靈活性的高級功能藏鹊。雖然 Vue 的模板系統(tǒng)已經(jīng)足夠強(qiáng)大,但在某些情況下转锈,直接使用 JavaScript 編寫渲染邏輯會更加方便。

Render 函數(shù)的工作原理是通過返回一個(gè)虛擬節(jié)點(diǎn)(VNode)來告訴 Vue 如何渲染界面楚殿。Vue 3 提供了 h 函數(shù)用于創(chuàng)建 VNode撮慨。

import { h } from 'vue'

export default {
  render() {
    return h('div', {}, 'Hello, world!')
  }
}

在這個(gè)例子中,我們使用 h 函數(shù)創(chuàng)建了一個(gè) div 元素脆粥,然后在 Render 函數(shù)中返回它砌溺。

編譯優(yōu)化

參考上一章節(jié)

Vue 3 的編譯器在編譯時(shí)做了許多優(yōu)化,例如靜態(tài)節(jié)點(diǎn)提升和動(dòng)態(tài)節(jié)點(diǎn)綁定变隔,從而在運(yùn)行時(shí)減少了不必要的工作规伐。靜態(tài)節(jié)點(diǎn)提升可以將不會改變的節(jié)點(diǎn)從渲染函數(shù)中提取出來,從而避免在每次渲染時(shí)都重新創(chuàng)建它們匣缘。動(dòng)態(tài)節(jié)點(diǎn)綁定則是對那些可能改變的節(jié)點(diǎn)進(jìn)行優(yōu)化猖闪,只有當(dāng)這些節(jié)點(diǎn)的綁定值發(fā)生變化時(shí),才會重新渲染節(jié)點(diǎn)肌厨。

手動(dòng)編寫渲染邏輯

有時(shí)培慌,我們可能需要手動(dòng)編寫渲染邏輯。比如柑爸,當(dāng)我們需要根據(jù)一組數(shù)據(jù)動(dòng)態(tài)生成一個(gè)列表時(shí)吵护,我們可以在 Render 函數(shù)中使用 JavaScript 的數(shù)組方法。

import { h } from 'vue'

export default {
  data() {
    return {
      items: ['Apple', 'Banana', 'Cherry']
    }
  },
  render() {
    return h('div', {}, this.items.map(item => h('div', {}, item)))
  }
}

在這個(gè)例子中表鳍,我們使用 map 方法動(dòng)態(tài)生成了一個(gè)列表的元素馅而,然后在 Render 函數(shù)中返回它。

Render 函數(shù)提供了一種強(qiáng)大的方式來控制 Vue 應(yīng)用的渲染過程譬圣,使得我們能夠更好地控制和優(yōu)化應(yīng)用的性能瓮恭。

vue生態(tài)配套

狀態(tài)管理

Pinia 是 Vue 3 提供的一種新型狀態(tài)管理庫,它提供了 Vuex 的核心功能胁镐,但在 API 設(shè)計(jì)上更加簡潔且易用偎血。

Pinia 的主要優(yōu)點(diǎn)包括:

  1. 它有更簡潔的 API,減少了模板代碼的數(shù)量盯漂。
  2. 它通過 TypeScript 提供了更好的類型支持颇玷。
  3. 它提供了基于組件的狀態(tài)存儲,只在需要時(shí)加載狀態(tài)就缆。

下面是一個(gè) Pinia 使用示例:

首先帖渠,安裝 Pinia:

npm install pinia

然后,創(chuàng)建一個(gè) Pinia store:

// src/stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore({
  id: 'counter',
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++
    }
  }
})

然后竭宰,在你的 main.js 或 main.ts 文件中創(chuàng)建 Pinia 插件空郊,并將其添加到你的 Vue 應(yīng)用中:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)

app.use(createPinia())
app.mount('#app')

然后份招,你可以在組件中使用該 store:

<template>
  <button @click="increment">{{ count }}</button>
</template>

<script>
import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()

    return {
      count: counter.count,
      increment: counter.increment
    }
  }
}
</script>

以上就是 Pinia 的基本用法,它提供了一種更簡潔狞甚、更靈活的方式來管理 Vue 應(yīng)用的狀態(tài)锁摔。

路由管理 - Vue Router

Vue Router 是 Vue.js 的路由庫,你可以使用它構(gòu)建單頁面應(yīng)用程序哼审,如下面的例子所示:

首先谐腰,創(chuàng)建一個(gè) router:

import { createRouter, createWebHistory } from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

然后,在 Vue 應(yīng)用中使用這個(gè) router:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

最后涩盾,在組件中使用 <router-link><router-view> 來導(dǎo)航和渲染路由:

<template>
  <router-link to="/">Home</router-link>
  <router-link to="/about">About</router-link>
  <router-view></router-view>
</template>

UI 框架 - Element UI

Element UI 是一個(gè)為 Vue.js 開發(fā)的 UI 框架十气,它提供了一套豐富多樣的組件,可以幫助我們更容易地構(gòu)建出漂亮的界面:

<template>
  <el-button type="primary">主要按鈕</el-button>
  <el-button type="success">成功按鈕</el-button>
  <el-button type="warning">警告按鈕</el-button>
</template>

測試方案 - Vitest

Vitest 是一個(gè)由 Vite 提供支持的極速單元測試框架春霍。

import { assert, describe, it } from 'vitest'

describe.skip('skipped suite', () => {
  it('test', () => {
    // 已跳過此測試套件砸西,無錯(cuò)誤
    assert.equal(Math.sqrt(4), 3)
  })
})

describe('suite', () => {
  it.skip('skipped test', () => {
    // 已跳過此測試,無錯(cuò)誤
    assert.equal(Math.sqrt(4), 3)
  })
})

其他改變

在 Vue 3 中址儒,開發(fā)者會注意到一些重要的變化芹枷,主要體現(xiàn)在全局 API 的轉(zhuǎn)移等,以及對 TypeScript 的更好支持上莲趣。

全局 API 轉(zhuǎn)移

在 Vue 3 中杖狼,一些全局 API 已經(jīng)被轉(zhuǎn)移到了 globalProperties 上,例如 Vue.prototype 在 Vue 3 中變成了 app.config.globalProperties妖爷。這樣做是為了更好地隔離全局 API蝶涩,并為未來可能的更改提供更大的靈活性。

例如絮识,原本在 Vue 2 中我們可能會這樣添加一個(gè)全局的方法:

Vue.prototype.$myGlobalMethod = function () {
  return 'Hello World!'
}

在 Vue 3 中绿聘,我們需要這樣做:

const app = createApp(App)
app.config.globalProperties.$myGlobalMethod = function () {
  return 'Hello World!'
}

然后我們就可以在任何組件中使用這個(gè)方法:

this.$myGlobalMethod()

刪除的 API

Vue 3 為了簡化框架并避免未來的維護(hù)負(fù)擔(dān),刪除了一些在 Vue 2 中已經(jīng)被廢棄的 API次舌,例如 Vue.set熄攘、Vue.deleteVue.observable

TypeScript 支持

Vue 3 從一開始就在內(nèi)部使用了 TypeScript 重寫彼念,因此在 TypeScript 的支持上有了顯著的提升挪圾。這包括更好的類型推斷、自動(dòng)補(bǔ)全逐沙,以及更強(qiáng)大的類型安全性哲思。

例如,在 Vue 2 中吩案,我們可能需要使用 Vue.extend() 或者 @Component 裝飾器來確保 TypeScript 類型正確棚赔,但在 Vue 3 中,我們可以直接使用 defineComponent 方法,它能正確地推斷出組件的類型:

import { defineComponent } from 'vue'

export default defineComponent({
  // type inference enabled
})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末靠益,一起剝皮案震驚了整個(gè)濱河市丧肴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胧后,老刑警劉巖芋浮,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異壳快,居然都是意外死亡途样,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門濒憋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陶夜,你說我怎么就攤上這事凛驮。” “怎么了条辟?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵黔夭,是天一觀的道長。 經(jīng)常有香客問我羽嫡,道長本姥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任杭棵,我火速辦了婚禮婚惫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魂爪。我一直安慰自己先舷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布滓侍。 她就那樣靜靜地躺著蒋川,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撩笆。 梳的紋絲不亂的頭發(fā)上捺球,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機(jī)與錄音夕冲,去河邊找鬼氮兵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛歹鱼,可吹牛的內(nèi)容都是我干的胆剧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秩霍!你這毒婦竟也來了篙悯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤铃绒,失蹤者是張志新(化名)和其女友劉穎鸽照,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颠悬,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矮燎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赔癌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诞外。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖灾票,靈堂內(nèi)的尸體忽然破棺而出峡谊,到底是詐尸還是另有隱情,我是刑警寧澤刊苍,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布既们,位于F島的核電站,受9級特大地震影響正什,放射性物質(zhì)發(fā)生泄漏啥纸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一婴氮、第九天 我趴在偏房一處隱蔽的房頂上張望斯棒。 院中可真熱鬧,春花似錦主经、人聲如沸名船。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渠驼。三九已至,卻和暖如春鉴腻,著一層夾襖步出監(jiān)牢的瞬間迷扇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工爽哎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜓席,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓课锌,卻偏偏與公主長得像厨内,于是被迫代替她去往敵國和親祈秕。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容