手拉手帶你開啟Vue3世界的鬼斧神工【實踐】

手拉手帶你開啟Vue3世界的鬼斧神工【實踐】


作者:流_星

轉發鏈接:
https://juejin.im/post/5ea97600f265da7b983b9e76

前言

2020註定是不平凡的一年,無論是疫情的橫空出世,還是世界局勢的激烈動盪,抑或是股市的跌宕起伏,我相信很多國人都會有一種慶幸我是中國人的深刻感悟。作為一名技術宅,除了疫情,更多的還是雨女無瓜,隨著Vue3.0 Beta的推出,大家都爭先恐後的嚐了鮮,筆者也不例外,經過一番研究,覺得Vue3也的確存在它獨特的魅力,也應該寫一篇博客方便還沒有體驗的朋友能夠快速對其有一個大體的認知。

開始

此文默認你已熟悉Vue2.x相關知識

環境搭建

相關庫版本

  • Vue-Cli 4.x
  • Vue 3.0.0-beta.1
  • Vue-Router 4.0.0-alpha.7

具體步驟如下:

  1. 使用VueCli創建一個Vue基礎項目:vue create project
  2. 在項目中,執行升級命令:vue add vue-next

項目目錄結構如下:


手拉手帶你開啟Vue3世界的鬼斧神工【實踐】


進行完以上操作無誤之後基本環境就已經搭建完畢。

配置路由

按照一般規範,在src目錄下新建router文件夾,並在router文件夾中新建index.js文件。

index.js內容:

<code>

import

{ createRouter, createWebHashHistory }

from

'vue-router'

;

import

Home

from

'../components/home'

const

routes = [ {

path

:

'/'

,

redirect

:

'/home'

}, {

path

:

'/home'

,

component

: Home} ]

export

default

createRouter({

history

: createWebHashHistory(), routes }) 複製代碼/<code>

基本的路由配置沒有太大改變,大多數情況下你只需要關注routes中路由規則編寫。接下來,我們需要在main.js中接入router。

main.js:

<code>

import

{ createApp }

from

'vue'

;

import

App

from

'./App.vue'

import

router

from

'./router'

;

const

app = createApp(App); app.use(router); app.mount(

'#app'

); 複製代碼/<code>

不同於我們之前採用new Vue()創建實例的方式,Vue3在這裡進行了改變;不僅如此,我們不難發現,安裝路由的方式也由之前的Vue.use(Router)變成如上方式,同理對於Vuex的接入也是大同小異,筆者這裡就不過多贅述了。

App.js

<code>

<

template

>

<

div

id

=

"app"

>

<

router-view

>

router-view

>

div

>

template

>

複製代碼/<code>

基礎語法初探

setup

setup功能是新的組件選項,它充當在組件內部使用Composition API(新特性)的入口點;創建組件實例時,在初始道具解析後立即調用。在生命週期方面,它在beforeCreate掛接之前被調用。

一般來說,按照我們之前常規的寫法,我們在對需要使用變量、計算屬性的時候,我們會習慣性的寫上:

home/index.vue

<code>

<

template

>

<

div

class

=

'home'

>

<

div

>

{{count}}

div

>

<

div

>

{{foo}}

div

>

div

>

template

>

<

script

>

import

{ ref }

from

'vue'

export

default

{

name

:

'home'

, data() {

return

{

count

:

0

} },

computed

: { foo() {

return

this

.count +

1

; } } }; 複製代碼

/<code>

兩者是需要被分類到各自的對象中,在同等功能實現上來說,Vue3的實現如下:

<code>

<

template

>

<

div

class

=

'home'

>

<

div

>

{{count}}

div

>

<

div

>

{{foo}}

div

>

div

>

template

>

<

script

>

import

{ ref, computed }

from

'vue'

export

default

{

name

:

'home'

, setup(props, context) {

const

count = ref(

0

)

const

foo = computed(

()

=>

count.value +

1

)

return

{ count, foo } } };

script

>

複製代碼/<code>

看到這種語法你是不是懵了,不用慌,這部分著重介紹setup這個入口函數,具體內部語法可以先不用在意,後面都會進行對應性一一講解。

setup接收兩個重要參數:

  • props:這個自然不用多提了,等同於vue2的props,在這個地方我們需要注意的地方是,我們不能對這個參數進行解構,如果使用解構會使它失去響應性。例如下面代碼就會讓props傳過來的值失去響應性:
<code>

export

default

{

props

: {

name

:

String

}, setup({ name }) { watchEffect(

()

=>

{

console

.log(

`name is: `

+ name) }) } } 複製代碼/<code>
  • context:其實這個參數我們也是比較熟悉的,它提供了一個上下文對象,該對象公開了先前this在2.x API中公開的屬性的選擇性列表,它僅包含三個屬性(attrs、slots、emit),舉個栗子:
<code>

setup

(props, context) {

context

.attrs

context

.slots

context

.emit

} 複製代碼/<code>

看完代碼,我們基本可以理解為setup函數就是我們整個組件各項邏輯關係以及操作的入口了,在Vue3中,我們使用不同api的方式都是採用導入的形式,這就相當於我們有了更大的操作空間,有了更大的自由性。

雖然說Vue3向下兼容Vue2,但是這裡其實我們需要注意的是,我們應該儘量避免2.x和setup函數的混用,這將會導致一些問題。

reactive

取得一個對象並返回原始對象的反應式代理。這等效於2.x的Vue.observable()。

對這個api用法,筆者用代碼講解會比較好理解:

<code>

<

template

>

<

div

class

=

'home'

>

<

div

>

{{name}}

div

>

div

>

template

>

<

script

>

import

{ reactive }

from

'vue'

export

default

{

name

:

'home'

, setup() {

const

obj = reactive({

name

:

'流星啊'

}) obj.name =

'bilibili'

;

return

obj; } };

script

>

複製代碼/<code>

相信大家已經看出來端倪,沒錯,這個api就是單純的把一個對象變得可響應。

ref

接受一個內部值並返回一個反應性且可變的ref對象。ref對象具有.value指向內部值的單個屬性。

在這裡我估計有小夥伴就要問了,這不就是2.x裡的ref嗎,不不不,在3.x它跟那個種在標籤上的ref沒有半點關係,也和$refs沒有任何關係,對於新的類似於2.x的獲取dom的方式請看模板引用部分。

同樣,舉個栗子:

<code>

<

template

>

<

div

class

=

'home'

>

<

div

>

{{count}}

div

>

div

>

template

>

<

script

>

import

{ ref }

from

'vue'

export

default

{

name

:

'home'

, setup() {

const

count = ref(

0

); count.value++;

console

.log(count.value);

return

{ count }; } };

script

>

複製代碼/<code>

這裡也有一個注意點,你如果想要修改使用ref構造出來的變量,只能對xxx.value進行修改,同理你想要在js中訪問它的值必須使用xxx.value,直接對count進行賦值如count++,這種寫法會報錯。

在這裡估計又有小夥伴要問了,那為啥在template模板中使用{{count}}訪問的時候不用加.value,這裡其實你在使用插值表達式的時候,它內部會自動展開,所以我們直接用就行了。

如果說我們把reactive和ref結合起來用會有怎樣的奇淫巧計呢,繼續舉個栗子:

<code>const 

count

= ref(

0

) const state = reactive({

count

}) console.log(state.

count

) state.

count

=

1

console.log(

count

.value) 複製代碼/<code>

當ref被訪問或作為反應對象的屬性進行更改時,它會自動展開為內部值,因此其行為類似於普通屬性。

computed

這個api也類似2.x,可以使用getter、setter,話不多說,上代碼:

<code>

const

count =

ref

(

1

)

const

plusOne = computed(() => count.

value

+

1

) console.log(plusOne.

value

) plusOne.

value

++ 複製代碼/<code>

在這裡我們不難發現,它的訪問方式也等同於ref,也是需要採用xxx.value,與此同時呢,如果你想要修改一個計算屬性的值,你必須為他設置setter,並對相應的依賴進行修改。廢話少說,看碼:

<code> 

const

count =

ref

(

1

)

const

plusOne = computed({

get

: () => count.

value

+

1

,

set

: val => { count.

value

= val -

1

} }) plusOne.

value

=

1

console.log(count.

value

) 複製代碼/<code>

readonly

意如其名,顧名思義,就是構造一個只能訪問的屬性,這個玩意它針對的很強,也就是無論你這個對象嵌套有多深,被他包裝後的對象一定是隻能讀,其實就是相當於一個代理:

<code>

const

re = reactive({count:

0

})

const

readonlyRe =

readonly

(re); readonlyRe.count++; 複製代碼/<code>

watchEffect

對於這個屬性呢,你可以拿它跟2.x的watch對象相比較了,沒錯他就是來監聽的。

<code>

const

count = ref(

0

) watchEffect(

()

=>

console

.log(count.value)) setTimeout(

()

=>

{ count.value++ },

100

) 複製代碼/<code>

總而言之,他會收集傳入函數的依賴,一旦依賴發生發生改變,他就會重新調用你傳進來的函數,用過react hooks的童靴可能會說,這玩意怎麼這麼像useEffect,其實Vue3也的確借鑑了react一些不錯的設計,所以,大家也不要覺得抄襲不抄襲的,框架終究是為用戶服務,好的設計自然應該值得借鑑,就像react也有借鑑Vue的一些優點對自身進行優化。

接下來我們繼續刨析這個api。調用這個api的同時,它會返回一個用於暫停句柄的函數,我們可以顯式調用它用於的停止當前監聽,並且對於傳入給watchEffect的回調函數,這個api在觸發調用的時候會傳入一個用於註冊無效回調的函數onInvalidate。具體例子如下:

<code>

const

stop = watchEffect(

onInvalidate

=>

{

const

token = performAsyncOperation(id.value); onInvalidate(

()

=>

{ token.cancel(); }) }) stop(); 複製代碼/<code>

如果我們註冊了無效回調方法,那麼在這個依賴已經變化但是異步請求還未完成的時候,它內部就會幫我們調用我們註冊的無效回調。

生命週期函數

這裡給一個與2.x的對比:

  • beforeCreate (vue3棄用) -> 使用 setup()
  • created (vue3棄用) -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

使用示例:

<code>

import

{ onMounted, onUpdated, onUnmounted }

from

'vue'

const MyComponent = { setup() { onMounted(

()

=>

{

console

.log(

'mounted!'

) }) onUpdated(

()

=>

{

console

.log(

'updated!'

) }) onUnmounted(

()

=>

{

console

.log(

'unmounted!'

) }) } } 複製代碼/<code>

模板引用

在看完前面ref這個api的介紹之後,很多小夥伴肯定也會疑惑,那我要獲取dom怎麼辦,這個Vue3也有的,放寬心,聽筆者繼續娓娓道來。

<code>

<

template

>

<

div

class

=

'home'

>

<

div

ref

=

"dom"

>

div

>

div

>

template

>

<

script

>

import

{ ref, onMounted }

from

'vue'

export

default

{

name

:

'home'

, setup() {

const

dom = ref(

null

) onMounted(

()

=>

{

console

.log(dom.value); })

return

{ dom } } };

script

>

複製代碼/<code>

從代碼中我們可以發現,現在這種訪問dom的方式和之前區別在於,我們需要顯示設定一個響應性變量,然後再在模板中使用之前我們耳熟能詳的方式ref='xxx'來進行設定。

結尾

聽完筆者的敘述,你有沒有對Vue3有一種躍躍欲試的想法呢。

如有發現筆者表述不當的地方,請在評論區戳筆者哦,感激不盡。

推薦Vue學習資料文章:

深入淺出通過vue-cli3構建一個SSR應用程序【實踐】

怎樣為你的 Vue.js 單頁應用提速

聊聊昨晚尤雨溪現場針對Vue3.0 Beta版本新特性知識點彙總

【新消息】Vue 3.0 Beta 版本發佈,你還學的動麼?

Vue真是太好了 壹萬多字的Vue知識點 超詳細!

Vue + Koa從零打造一個H5頁面可視化編輯器——Quark-h5

深入淺出Vue3 跟著尤雨溪學 TypeScript 之 Ref 【實踐】

手把手教你深入淺出vue-cli3升級vue-cli4的方法

Vue 3.0 Beta 和React 開發者分別槓上了

手把手教你用vue drag chart 實現一個可以拖動 / 縮放的圖表組件

Vue3 嚐鮮

總結Vue組件的通信

手把手讓你成為更好的Vue.js開發人員的12個技巧和竅門【實踐】

Vue 開源項目 TOP45

2020 年,Vue 受歡迎程度是否會超過 React?

尤雨溪:Vue 3.0的設計原則

使用vue實現HTML頁面生成圖片

實現全棧收銀系統(Node+Vue)(上)

實現全棧收銀系統(Node+Vue)(下)

vue引入原生高德地圖

Vue合理配置WebSocket並實現群聊

多年vue項目實戰經驗彙總

vue之將echart封裝為組件

基於 Vue 的兩層吸頂踩坑總結

Vue插件總結【前端開發必備】

Vue 開發必須知道的 36 個技巧【近1W字】

構建大型 Vue.js 項目的10條建議

深入理解vue中的slot與slot-scope

手把手教你Vue解析pdf(base64)轉圖片【實踐】

使用vue+node搭建前端異常監控系統

推薦 8 個漂亮的 vue.js 進度條組件

基於Vue實現拖拽升級(九宮格拖拽)

手摸手,帶你用vue擼後臺 系列二(登錄權限篇)

手摸手,帶你用vue擼後臺 系列三(實戰篇)

前端框架用vue還是react?清晰對比兩者差異

Vue組件間通信幾種方式,你用哪種?【實踐】

淺析 React / Vue 跨端渲染原理與實現

10個Vue開發技巧助力成為更好的工程師

手把手教你Vue之父子組件間通信實踐講解【props、$ref 、$emit】

1W字長文+多圖,帶你瞭解vue的雙向數據綁定源碼實現

深入淺出Vue3 的響應式和以前的區別到底在哪裡?【實踐】

乾貨滿滿!如何優雅簡潔地實現時鐘翻牌器(支持JS/Vue/React)

基於Vue/VueRouter/Vuex/Axios登錄路由和接口級攔截原理與實現

手把手教你D3.js 實現數據可視化極速上手到Vue應用

吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【上】

吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【中】

吃透 Vue 項目開發實踐|16個方面深入前端工程化開發技巧【下】

Vue3.0權限管理實現流程【實踐】

後臺管理系統,前端Vue根據角色動態設置菜單欄和路由


作者:流_星
轉發鏈接:
https://juejin.im/post/5ea97600f265da7b983b9e76


分享到:


相關文章: