帶你體驗Vue2和Vue3開發組件有什麼區別

帶你體驗Vue2和Vue3開發組件有什麼區別

咱們一直都有關注和閱讀不少關於Vue3的新特性和功能即將到來。可是咱們沒有一個具體的概念在開發中會有如何的改變和不同的體驗。還有一些童鞋已經開始又慌又抓狂了 -- 「又要開始學新的寫法了 (ノToT )ノ ~┻┻」。javascript

因此這裏我使用Vue2和Vue3開發一個簡單的表格組件來展現一下Vue2和Vue3開發組件的區別。看完這片文章後,你將會有一個概念Vue2和Vue3開發組件時的區別,而且爲Vue3的開發之路作好準備。ღ(◔ڼ◔ღ)ミhtml

廢話少說,讓咱們開始吧~ (๑ •̀ㅂ•́)و前端

三鑽分割線

建立一個 template

組件來講,大多代碼在Vue2和Vue3都很是類似。Vue3支持碎片(Fragments),就是說在組件能夠擁有多個根節點。vue

這種新特性能夠減小不少組件之間的div包裹元素。在開發vue的時候,咱們會發現每個組件都會有個div元素包裹着。就會出現不少層多餘的div元素。碎片(Fragments)解決了這個問題。對於有完美強迫症的童鞋「真的時太棒了」。咱們這裏的例子裏就不展現了,用簡單的單根節點的組件。java

Vue2 表格templatereact

<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的惟一真正的不一樣在於數據獲取。Vue3中的反應數據(Reactive Data)是包含在一個反應狀態(Reactive State)變量中。— 因此咱們須要訪問這個反應狀態來獲取數據值。設計模式

<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與Vue3 最大的區別 — Vue2使用選項類型API(Options API)對比Vue3合成型API(Composition API)性能

舊的選項型API在代碼裏分割了不一樣的屬性(properties):data,computed屬性,methods,等等。新的合成型API能讓咱們用方法(function)來分割,相比於舊的API使用屬性來分組,這樣代碼會更加簡便和整潔。ui

如今咱們來對比一下Vue2寫法和Vue3寫法在代碼裏面的區別。this

Vue2 - 這裏把兩個數據放入data屬性中

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

Vue3.0,咱們就須要使用一個新的setup()方法,此方法在組件初始化構造的時候觸發。

爲了可讓開發者對反應型數據有更多的控制,咱們能夠直接使用到 Vue3 的反應API(reactivity API)

使用如下三步來創建反應性數據:

  1. 從vue引入reactive
  2. 使用reactive()方法來聲名咱們的數據爲反應性數據
  3. 使用setup()方法來返回咱們的反應性數據,從而咱們的template能夠獲取這些反應性數據

上一波代碼,讓你們更容易理解是怎麼實現的。

import { reactive } from 'vue'

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

    return { state }
  }
}
複製代碼

這裏構造的反應性數據就能夠被template使用,能夠經過state.usernamestate.password得到數據的值。

三鑽分割線

Vue2 對比 Vue3的 methods 編寫

Vue2 的選項型API是把methods分割到獨立的屬性區域的。咱們能夠直接在這個屬性裏面添加方法來處理各類前端邏輯。

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    login () {
      // 登錄方法
    }
  }
}
複製代碼

Vue3 的合成型API裏面的setup()方法也是能夠用來操控methods的。建立聲名方法其實和聲名數據狀態是同樣的。— 咱們須要先聲名一個方法而後在setup()方法中返回(return), 這樣咱們的組件內就能夠調用這個方法了。

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

    const login = () => {
      // 登錄方法
    }
    return { 
      login,
      state
    }
  }
}
複製代碼

三鑽分割線

生命週期鉤子 — Lifecyle Hooks

Vue2,咱們能夠直接在組件屬性中調用Vue的生命週期的鉤子。如下使用一個組件已掛載(mounted)生命週期觸發鉤子。

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  mounted () {
    console.log('組件已掛載')
  },
  methods: {
    login () {
      // login method
    }
  }
}
複製代碼

如今 Vue3 的合成型API裏面的setup()方法能夠包含了基本全部東西。生命週期的鉤子就是其中之一!

可是在 Vue3 生週期鉤子不是全局可調用的了,須要另外從vue中引入。和剛剛引入reactive同樣,生命週期的掛載鉤子叫onMounted

引入後咱們就能夠在setup()方法裏面使用onMounted掛載的鉤子了。

import { reactive, onMounted } from 'vue'

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

    onMounted(() => {
      console.log('組件已掛載')
    })

    // ...
  }
}
複製代碼

三鑽分割線

計算屬性 - Computed Properties

咱們一塊兒試試添加一個計算屬性來轉換username成小寫字母。

Vue2 中實現,咱們只須要在組件內的選項屬性中添加便可

export default {
  // .. 
  computed: {
    lowerCaseUsername () {
      return this.username.toLowerCase()
    }
  }
}
複製代碼

Vue3 的設計模式給予開發者們按需引入須要使用的依賴包。這樣一來就不須要多餘的引用致使性能或者打包後太大的問題。Vue2就是有這個一直存在的問題。

因此在 Vue3 使用計算屬性,咱們先須要在組件內引入computed

使用方式就和反應性數據(reactive data)同樣,在state中加入一個計算屬性:

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之間最大的區別。this在vue3中與vue2表明着徹底不同的東西。

Vue2this表明的是當前組件,不是某一個特定的屬性。因此咱們能夠直接使用this訪問prop屬性值。就好比下面的例子在掛載完成後打印處當前傳入組件的參數title

mounted () {
    console.log('title: ' + this.title)
}
複製代碼

可是在 Vue3 中,this沒法直接拿到props屬性,emit events(觸發事件)和組件內的其餘屬性。不過全新的setup()方法能夠接收兩個參數:

  1. props - 不可變的組件參數
  2. context - Vue3 暴露出來的屬性(emit,slots,attrs)

因此在 Vue3 接收與使用props就會變成這樣:

setup (props) {
    // ...

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

    // ...
}
複製代碼

三鑽分割線

事件 - Emitting Events

Vue2 中自定義事件是很是直接的,可是在 Vue3 的話,咱們會有更多的控制的自由度。

舉例,如今咱們想在點擊提交按鈕時觸發一個login的事件。

Vue2 中咱們會調用到this.$emit而後傳入事件名和參數對象。

login () {
      this.$emit('login', {
        username: this.username,
        password: this.password
      })
 }
複製代碼

可是在 Vue3中,咱們剛剛說過this已經不是和vue2表明着這個組件了,因此咱們須要不同的自定義事件的方式。

那怎麼辦呀?! ლಠ益ಠ)ლ

不用慌,在setup()中的第二個參數content對象中就有emit,這個是和this.$emit是同樣的。那麼咱們只要在setup()接收第二個參數中使用分解對象法取出emit就能夠在setup方法中隨意使用了。

而後咱們在login方法中編寫登錄事件:

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

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

    // ...
}
複製代碼

三鑽分割線

最終的vue2對比vue3代碼

最終的vue2對比vue3代碼
真的是太棒了,能看到這裏的童鞋們,大家如今基本都看到vue2與vue3其實概念與理念都是同樣的。只是有一些屬性獲取方式和聲名和定義方式稍微變了。一直在鬼哭狼嚎的小小前端開發猿人們,大家能夠鬆一口氣了吧。

總結一下,我以爲 Vue3 給咱們前端開發者帶來了全新的開發體驗,更好的使用彈性,可控度也獲得了大大的提高。若是你是一個學過或者接觸過 React 而後如今想使用Vue的話,應該特別興奮,由於不少使用方式都和React很是相近了 🎉!

全新的合成式API(Composition API)能夠提高代碼的解耦程度 —— 特別是大型的前端應用,效果會更加明顯。還有就是按需引用的有了更細微的可控性,讓項目的性能和打包大小有更好的控制。

最後我把完成的 Vue2Vue3 的組件代碼發出來給你們:

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> 複製代碼

但願這篇文章能讓你們體驗到一個比較全面的Vue2與Vue3的開發區別。若是你們還有什麼問題,能夠在評論中提問哦!

開發愉快!~

三鑽分割線
相關文章
相關標籤/搜索