Vue3教程,搶先學習


Vue 3尚未正式發布,但是維護者已經發布了Beta版本,供我們的參與者嘗試並提供反饋。

如果你想知道Vue 3的主要功能和主要變化是什么,那么我將在這篇文章中重點介紹一下,告訴你使用Vue 3 beta 9創建一個簡單的應用程序。

我將介紹盡可能多的新內容,包括fragments,teleport,Composition API以及其他一些晦澀的更改。我將盡力解釋該功能或更改的原理。


Vue3相關文章:


我們將建立什么

我們將構建一個帶有模式窗口功能的簡單應用。我之所以選擇它,是因為它可以方便地展示Vue 3的許多變化。

這是該應用在打開和關閉狀態下的外觀,因此你可以在腦海中描繪出我們正在做什么:

 

 

 

Vue 3安裝和setup

與其直接安裝Vue 3,不如克隆一個項目 vue-next-webpack-preview,這將為我們提供一個包括Vue 3在內的最小的Webpack設置。

$ git clone https://github.com/vuejs/vue-next-webpack-preview.git vue3-experiment $ cd vue3-experiment $ npm i 復制代碼

一旦克隆好了,安裝好了NPM模塊,我們需要做的就是刪除樣板文件,然后創建一個新的 main.js 文件,這樣我們就可以從頭開始創建我們的Vue 3 app了。

$ rm -rf src/*
$ touch src/main.js
復制代碼

現在,我們將運行開發服務器:

$ npm run dev
復制代碼

創建一個新的Vue 3 app

我們啟動一個新的Vue應用程序的方式改變了,我們現在需要導入新的 createApp 方法,而不是使用新的 Vue()

我們調用這個方法,傳遞我們的Vue實例定義對象,並將返回對象分配給一個變量 app

接下來,我們將在 app 上調用 mount 方法,並傳遞一個CSS選擇器來指示我們的mount元素,就像在Vue 2中使用 $mount 實例方法一樣。

// src/main.js import { createApp } from "vue"; const app = createApp({ // 根實例定義 }); app.mount("#app"); 

變化的原因

與舊的API一樣,我們添加的任何全局配置(plugins,mixins,原型屬性等)都將永久更改全局狀態。例如:

// src/main.js // 影響兩個實例 Vue.mixin({ ... }) const app1 = new Vue({ el: '#app-1' }) const app2 = new Vue({ el: '#app-2' }) 復制代碼

在單元測試中,這確實是一個問題,因為要確保將每個測試都與上一個測試隔離是很棘手的。

在新的API下,調用 createApp 將返回一個新的app實例,該實例不會被應用於其他實例的任何全局配置污染。

了解更多:Global API change RFC

添加state屬性

我們的模態窗口可以處於兩種狀態之一——打開或關閉。讓我們用一個布爾狀態屬性 modalOpen 來管理它,我們將給它一個初始值 false

在Vue 2下,我們可以通過在我們的應用實例上創建一個 data 屬性並將一個對象分配給該對象來聲明 modalOpen 屬性,例如:

// src/main.js const app = createApp({ data: { modalOpen: false } }); 復制代碼

不再允許這樣做。相反,必須為數據分配一個返回狀態對象的工廠函數。

// src/main.js const app = createApp({ data: () => ({ modalOpen: false }) }); 復制代碼

變化的原因

使用對象而不是工廠函數來存儲數據的優點是,首先,它在語法上更簡單;其次,你可以在多個根實例之間共享頂級狀態,例如:

// src/main.js const state = { sharedVal: 0 }; const app1 = new Vue({ state }); const app2 = new Vue({ state }); // 影響兩個實例 app1._data.sharedVal = 1; 復制代碼

這種用例很少,可以使用。因為有兩種類型的聲明是不適合初學者的,所以決定刪除這個特性。

了解更多:Data object declaration removed RFC

在繼續之前,我們還添加一個方法來切換 modalOpen 值。這與Vue 2沒什么不同。

// src/main.js const app = createApp({ data: () => ({ modalOpen: true }), methods: { toggleModalState() { this.modalOpen = !this.modalOpen; } } }); 復制代碼

使用一個根組件

如果你現在進入瀏覽器並檢查控制台,則會看到警告“Component is missing render function”,因為我們尚未為根實例定義模板。

Vue 2的最佳實踐是為根實例創建一個最小的模板,並創建一個app組件,其中將聲明主app標記。

讓我們在這里也這樣做。

$ touch src/App.vue
復制代碼

現在我們可以獲取根實例來渲染該組件。區別在於,對於Vue 2,我們通常會使用render函數來執行此操作:

// src/main.js import App from "./App.vue"; const app = createApp({ ... render: h => h(App) }); app.mount("#app"); 復制代碼

我們仍然可以做到這一點,但是Vue 3有一個更簡單的方法——使 App 成為根組件。為此,我們可以刪除根實例定義,而是傳遞 App 組件。

// src/main.js import App from "./App.vue"; const app = createApp(App); app.mount("#app"); 復制代碼

這意味着 App 組件不僅由根實例渲染,而且是根實例。

在此過程中,我們通過刪除 app 變量來簡化語法:

// src/main.js createApp(App).mount("#app"); 復制代碼

現在移至根組件,讓我們向該組件重新添加狀態和方法:

// src/App.vue

<script> export default { data: () => ({ modalOpen: true }), methods: { toggleModalState() { this.modalOpen = !this.modalOpen; } } }; </script> 復制代碼

我們還為模態功能創建一個新組件:

$ touch src/Modal.vue
復制代碼

現在,我們將提供一個最小的模板,其中包括內容插槽。這確保了我們的模態是可重用的。稍后我們將向此組件添加更多內容。

// src/Modal.vue

<template> <div class="modal"> <slot></slot> </div> </template> 復制代碼

多根模板

現在讓我們為我們的根組件創建模板。我們將創建一個按鈕來打開模態,它將觸發 toggleModalState 方法。

我們還將使用我們剛剛創建的modal組件,它將根據 modalState 的值來渲染。讓我們也在槽中插入一段文字作為內容。

// src/App.vue

<template> <button @click="toggleModalState">Open modal</button> <modal v-if="modalOpen"> <p>Hello, I'm a modal window.</p> </modal> </template> <script> import Modal from "./Modal.vue"; export default { components: { Modal }, ... } </script> 復制代碼

注意這個模板有什么奇怪的地方嗎?再看一遍。

沒錯——有兩個根元素。在Vue 3中,由於有了一個叫做片段(fragments)的功能,它不再強制要求有一個單一的根元素!

使用Composition API進行重構

Vue 3的旗艦功能是Composition API。這個新的API允許你使用 setup 功能而不是使用添加到組件定義對象的屬性來定義組件功能。

現在,讓我們重構App組件以使用Composition API。

在解釋代碼之前,請清楚我們所做的只是重構——組件的功能將相同。還要注意,模板沒有更改,因為Composition API僅影響我們定義組件功能的方式,而不影響我們渲染它的方式。

src/App.vue

<template>
  <button @click="toggleModalState">Open modal</button>
  <modal v-if="modalOpen">
    <p>Hello, I'm a modal window.</p>
  </modal>
</template>
<script>
import Modal from "./Modal.vue";
import { ref } from "vue";
export default {
  setup () {
    const modalState = ref(false);
    const toggleModalState = () => {
      modalState.value = !modalState.value;
    };
    return {
      modalState,
      toggleModalState
    }
  }
};
</script>
復制代碼

setup 方法

首先,請注意,我們導入了 ref 函數,該函數允許我們定義響應式變量 modalState。此變量等效於this.modalState

toggleModalState 方法只是一個普通的JavaScript函數。但是,請注意,要更改方法主體中的 modalState 值,我們需要更改其子屬性 value。 這是因為使用 ref 創建的響應式變量被封裝在一個對象中。這對於保留它們的響應式是非常必要的,因為它們在被傳遞的過程中會被保留下來。

最后,我們從 setup 方法返回 modalState 和 toggleModalState ,因為這些是在呈現模板時傳遞給模板的值。

變化的原因

請記住,Composition API並不是更改,因為它純粹是可選的。主要動機是允許更好的代碼組織和組件之間的代碼重用(因為mixin本質上是一種反模式)。

如果你認為在這個例子中重構App組件以使用Composition API是沒有必要的,那你的想法是正確的。但是,如果這是一個更大的組件,或者我們需要與其他組件共享其功能,那么你就會發現它的用處。

Teleporting content

如果你曾經創建過模態功能,你會知道它通常被放置在關閉的 </body> 標簽之前。

<body> <div> <!--main page content here--> </div> <!--modal here--> </body> 復制代碼

這樣做是因為模式通常具有覆蓋頁面的背景,要使用CSS來實現,您不需要處理父元素定位和z-index堆棧上下文,因此最簡單的解決方案是將模式放在DOM的最底部。

但這在Vue.js中產生了一個問題,它假定UI將作為一個單一的組件樹來構建。為了允許將樹的片段移動到DOM中的其他位置,在Vue 3中添加了一個新的 teleport 組件。

要使用teleport,首先要在頁面上添加一個元素,我們要將模態內容移動到該頁面。我們將轉到 index.html,並將ID為 modal-wrapper 的 div 放在Vue的安裝元素旁邊。

index.html

<body> ... <div id="app"></div><!--Vue mounting element--> <div id="modal-wrapper"> <!--modal should get moved here--> </div> </body> 復制代碼

現在,回到 App.vue,我們將模態內容包裝在 teleport 組件中。我們還需要指定一個 to 屬性,為該屬性分配一個查詢選擇器,以標識目標元素,在本例中為 #modal-wrapper

src/App.vue

<template> <button @click="toggleModalState">Open modal</button> <teleport to="#modal-wrapper"> <modal v-if="modalOpen"> <p>Hello, I'm a modal window.</p> </modal> </teleport> </template> 復制代碼

就是這樣,teleport 中的任何內容都將渲染在目標元素中。

Emitting 和 event

現在,讓我們在modal中添加一個按鈕,讓它可以被關閉。要做到這一點,我們要在modal 模板中添加一個按鈕元素,並添加一個點擊處理程序,該處理程序會發出一個 close 事件。

src/Modal.vue

<template> <div class="modal"> <slot></slot> <button @click="$emit('close')">Dismiss</button> </div> </template> 復制代碼

然后,該事件將由父組件捕獲,並將切換 modalState 的值,從邏輯上將其設置為 false 並導致窗口關閉。

src/App.vue

<template> ... <modal v-if="modalOpen" @click="toggleModalState" > <p>Hello, I'm a modal window.</p> </modal> </teleport> </template> 復制代碼

到目前為止,此功能與Vue 2中的功能相同。但是,現在在Vue 3中,建議您使用新的 emits 組件選項顯式聲明組件的事件。就像props一樣,你可以簡單地創建一個字符串數組來命名組件將發出的每個事件。

src/Modal.vue

<template>...</template> <script> export default { emits: [ "close" ] } </script> 復制代碼

變化的原因

想象一下,打開別人寫的組件的文件,看到它的prop和event明文聲明。馬上,你就會明白這個組件的界面,也就是它要發送和接收什么。

除了提供自說明代碼外,你還可以使用事件聲明來驗證你的事件有效載荷,雖然我在這個例子中找不到理由來驗證。

了解更多:Emits Option RFC

樣式插槽內容

為了使模態可重用,我們提供了一個內容插槽。讓我們開始通過為組件添加 style 標簽來為內容設置樣式。

在我們的組件中使用 scoped CSS是一種很好的做法,以確保我們提供的規則不會對頁面中的其他內容產生意外影響。

讓我們把任何被放入插槽中的段落文字變成斜體。要做到這一點,我們將使用 p 選擇器創建一個新的CSS規則。

src/Modal.vue

<template>...</template> <script>...</script> <style scoped> p { font-style: italic; } </style> 復制代碼

如果你嘗試一下,你會發現這一點並不奏效。問題是,在編譯時,當插槽內容仍屬於父對象時,Scoped styling是在編譯時確定的。

Vue 3提供的解決方案是提供一個偽選擇器 ::v-slotted(),允許你在提供插槽的組件中使用范圍化規則來針對插槽內容。

這是我們的用法:

<style scoped> ::v-slotted(p) { font-style: italic; } </style> 復制代碼

Vue 3還包含了其他一些新的Scoped Styling選擇器:::v-deep 和 ::v-global,你可以在這里了解更多:Scoped Styles RFC

其他改變

好吧,這就是我可以在一個簡單示例中涵蓋的所有新功能。主要的我基本都有了,但這里有一些我認為很重要的,在總結文章之前,我覺得足夠重要,可以自己研究一下。

添加的:

移出的:

更改的:

關於Vue Router也有各種變化,但我將專門用一篇文章來介紹這些變化!

 本文的文字及圖片來源於網絡加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM