迎接Vue3.0 | 在Vue2與Vue3中構建相同的組件

圖片



4月16日,Vue 開發團隊終於在今天發佈了 3.0-beta.1 版本,也就是測試版。一般來講,從測試版到正式版,只會修復 bug,不會引入新功能,或者刪改老功能。因此,若是你對新版本很是感興趣,或者有新項目即將上馬,不妨嘗試一下新版本。
vue

隨着Vue3即將發佈,許多人都在想「 Vue2與Vue3有何不一樣?」react

爲了顯示這些更改,咱們將在Vue2和Vue3中構建一個簡單的表單組件。編程

在本文結尾,你將瞭解Vue2和Vue3之間的主要編程差別,並逐步成爲一名更好的開發人員。數組

建立咱們的模板

對於大多數組件,Vue2和Vue3中的代碼即便不徹底相同,也是很是類似的。可是,Vue3支持Fragments,這意味着組件能夠具備多個根節點。app

在渲染列表中的組件以刪除沒必要要的包裝div元素時,這特別有用。可是,在這種狀況下,咱們將爲兩個版本的Form組件保留一個根節點。ide

Vue2函數

<template>
 <div class='form-element'>
   <h2> {{ title }} </h2>
   <input type='text' v-model='username' placeholder='Username' />
   
   <input type='password' v-model='password' placeholder='Password' />

   <button @click='login'>
     Submit
   </button>
   <p>
     Values: {{ username + ' ' + password }}
   </p>
 </div>
</template>

惟一真正的區別是咱們訪問數據的方式。在Vue3中,咱們的響應式數據都包裝在響應式狀態變量中——所以咱們須要訪問該狀態變量以獲取咱們的值。測試

Vue3this

<template>
 <div class='form-element'>
   <h2> {{ state.title }} </h2>
   <input type='text' v-model='state.username' placeholder='Username' />
   
   <input type='password' v-model='state.password' placeholder='Password' />

   <button @click='login'>
     Submit
   </button>
   <p>
     Values: {{ state.username + ' ' + state.password }}
   </p>
 </div>
</template>

設置Data

這是主要的區別——Vue2 Options API與Vue3 Composition API。spa

Options API將咱們的代碼分爲不一樣的屬性:數據,計算屬性,方法等。同時,Composition API容許咱們按功能而不是屬性類型對代碼進行分組。

假設對於表單組件,咱們只有兩個數據屬性:username 和 password

Vue2代碼看起來是這樣的——咱們只需在 data 屬性中放入兩個值。

Vue2

export default {
 props: {
   title: String
 },
 data () {
   return {
     username: '',
     password: ''
   }
 }
}

在Vue 3.0中,咱們必須投入更多的精力來使用一個新的 setup() 方法,全部的組件初始化都應該在這個方法中進行。

另外,爲了使開發人員可以更好地控制響應式,咱們能夠直接訪問Vue的響應式API。

建立響應式數據涉及三個步驟:

  • 從Vue導入 reactive
  • 使用 reactive 方法聲明咱們的數據
  • 讓咱們的 setup() 方法返回reactive數據,以便咱們的模板能夠訪問它

在代碼方面,它將看起來像這樣。

Vue3

import { reactive } from 'vue'

export default {
 props: {
   title: String
 },
 setup () {
   const state = reactive({
     username: '',
     password: ''
   })

   return { state }
 }
}

而後,在模板中,咱們像 state.username 和 state.password 同樣訪問它們

在Vue2與Vue3中建立方法

Vue2 Options API有一個單獨的方法部分。在其中,咱們能夠定義全部方法並以所需的任何方式組織它們。

Vue2

export default {
 props: {
   title: String
 },
 data () {
   return {
     username: '',
     password: ''
   }
 },
 methods: {
   login () {
     // login method
   }
 }
}

Vue3 Composition API中的setup方法也能夠處理方法。它的工做方式與聲明數據有些相似——咱們必須先聲明咱們的方法,而後返回它,以便組件的其餘部分能夠訪問它。

Vue3

export default {
 props: {
   title: String
 },
 setup () {
   const state = reactive({
     username: '',
     password: ''
   })

   const login = () => {
     // login method
   }
   return {
     login,
     state
   }
 }
}

生命週期鉤子函數

在Vue2中,咱們能夠直接從組件選項訪問生命週期鉤子函數。對於咱們的示例,咱們將等待 mounted 事件。

Vue2

export default {
 props: {
   title: String
 },
 data () {
   return {
     username: '',
     password: ''
   }
 },
 mounted () {
   console.log('component mounted')
 },
 methods: {
   login () {
     // login method
   }
 }
}

如今有了Vue3 Composition API,幾乎全部內容都在 setup() 方法內部,這包括 mounted 的生命週期鉤子。

可是,默認狀況下不包括生命週期掛鉤,所以咱們必須導入 onMounted方法,做爲Vue3中調用的方法,這看起來與早期導入 reactive 相同。

而後,在咱們的 setup() 方法中,能夠經過將 onMounted 方法傳遞給函數來使用它。

Vue3

import { reactive, onMounted } from 'vue'

export default {
 props: {
   title: String
 },
 setup () {
   // ..

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

   // ...
 }
}

計算屬性

讓咱們添加一個計算屬性,將咱們的用戶名轉換爲小寫字母。爲了在Vue2中完成此操做,咱們將一個計算字段添加到咱們的options對象中。

Vue2

export default {
 // ..
 computed: {
   lowerCaseUsername () {
     return this.username.toLowerCase()
   }
 }
}

Vue3的設計容許開發人員導入他們使用的內容,而在項目中沒有使用的不須要導入。本質上,他們不但願開發人員必須包含他們從未使用過的東西,這在Vue2中已經成爲一個日益嚴重的問題。

所以,要在Vue3中使用計算屬性,咱們首先必須將 computed 導入到組件中。

而後,相似於咱們以前建立 reactive 數據的方式,咱們可使一條 reactive 數據成爲這樣的計算值:

Vue3

import { reactive, onMounted, computed } from 'vue'

export default {
 props: {
   title: String
 },
 setup () {
   const state = reactive({
     username: '',
     password: '',
     lowerCaseUsername: computed(() => state.username.toLowerCase())
   })

   // ...
 }
}

訪問屬性(Props)

訪問Props帶來了Vue2和Vue3之間的一個重要區別——這意味着徹底不一樣的東西

在Vue2中,這幾乎老是引用組件,而不是特定的屬性,雖然這使事情表面上很容易,但它使類型支持成爲一種痛苦。

以往,咱們均可以輕鬆訪問Props——讓咱們添加一個簡單的示例,例如在mounted的鉤子上打印出標題prop:

Vue2

mounted () {
 console.log('title: ' + this.title)
}

可是在Vue3中,咱們再也不使用它來訪問Props、發出事件和獲取屬性。

相反,setup() 方法採用兩個參數:

  • props——對組件prop的不可變訪問
  • context——Vue3公開的選定屬性(emit、slots、 attrs)

使用props參數,上面的代碼將以下所示。

Vue3

setup (props) {
 // ...

 onMounted(() => {
   console.log('title: ' + props.title)
 })

 // ...
}

發送事件(Emitting Events)

相似地,在Vue2中發出事件很是簡單,可是Vue3爲你提供了對如何訪問屬性/方法的更多控制。

例如,在咱們的例子中,咱們想在按下「Submit」按鈕時向父組件發出登陸事件。

Vue2代碼只須要調用 this.$emit並傳入咱們的有效參數對象便可。

Vue2

login () {
 this.$emit('login', {
   username: this.username,
   password: this.password
 })
}

然而,在Vue3中,咱們如今知道這再也不意味着一樣的事情,因此咱們必須作得不一樣。

幸運的是,上下文對象(context)公開了 emit,這使咱們擁有與此相同的東西。

咱們要作的就是將 context 添加爲 setup() 方法的第二個參數,咱們將解構上下文對象,以使咱們的代碼更簡潔。

而後,咱們只須要調用emit發送事件便可。而後,像之前同樣,emit方法採用兩個參數:

  • 事件名稱
  • 與事件一塊兒傳遞的有效參數對象

Vue3

setup (props, { emit }) {
 // ...

 const login = () => {
   emit('login', {
     username: state.username,
     password: state.password
   })
 }

 // ...
}

最終的Vue2與Vue3代碼!

如你所見,Vue2和Vue3中的全部概念都是相同的,可是咱們訪問屬性的某些方式已經有所變化。

總的來講,我認爲Vue3將幫助開發人員編寫更有組織的代碼——特別是在大型代碼庫中。這主要是由於Composition API容許你按特定功能將代碼分組在一塊兒,甚至能夠將功能提取到本身的文件中,而後根據須要將其導入組件中。

Vue2中用於表單組件的完整代碼:

<template>
 <div class='form-element'>
   <h2> {{ title }} </h2>
   <input type='text' v-model='username' placeholder='Username' />
   
   <input type='password' v-model='password' placeholder='Password' />

   <button @click='login'>
     Submit
   </button>
   <p>
     Values: {{ username + ' ' + password }}
   </p>
 </div>
</template>
<script>
export default {
 props: {
   title: String
 },
 data () {
   return {
     username: '',
     password: ''
   }
 },
 mounted () {
   console.log('title: ' + this.title)
 },
 computed: {
   lowerCaseUsername () {
     return this.username.toLowerCase()
   }
 },
 methods: {
   login () {
     this.$emit('login', {
       username: this.username,
       password: this.password
     })
   }
 }
}
</script>

這是在Vue3中的完整代碼:

<template>
 <div class='form-element'>
   <h2> {{ state.title }} </h2>
   <input type='text' v-model='state.username' placeholder='Username' />
   
   <input type='password' v-model='state.password' placeholder='Password' />

   <button @click='login'>
     Submit
   </button>
   <p>
     Values: {{ state.username + ' ' + state.password }}
   </p>
 </div>
</template>
<script>
import { reactive, onMounted, computed } from 'vue'

export default {
 props: {
   title: String
 },
 setup (props, { emit }) {
   const state = reactive({
     username: '',
     password: '',
     lowerCaseUsername: computed(() => state.username.toLowerCase())
   })

   onMounted(() => {
     console.log('title: ' + props.title)
   })

   const login = () => {
     emit('login', {
       username: state.username,
       password: state.password
     })
   }

   return {
     login,
     state
   }
 }
}
</script>

我但願本教程有助於重點介紹Vue代碼在Vue3中看起來不同凡響的某些方式。若有其餘疑問,請留下你的意見!

相關文章
相關標籤/搜索