初體驗(yàn)Vue2和Vue3開發(fā)組件有什么區(qū)別

我們一直都有關(guān)注和閱讀很多關(guān)于Vue3的新特性和功能即將到來(lái)。但是我們沒(méi)有一個(gè)具體的概念在開發(fā)中會(huì)有如何的改變和不一樣的體驗(yàn)餐蔬。還有一些童鞋已經(jīng)開始又慌又抓狂了 -- “又要開始學(xué)新的寫法了 (ノToT )ノ ~┻┻”。

所以這里我使用Vue2和Vue3開發(fā)一個(gè)簡(jiǎn)單的表格組件來(lái)展示一下Vue2和Vue3開發(fā)組件的區(qū)別骡技〖鼐眨看完這片文章后,你將會(huì)有一個(gè)概念Vue2和Vue3開發(fā)組件時(shí)的區(qū)別匣砖,并且為Vue3的開發(fā)之路做好準(zhǔn)備科吭。?(????)ミ

廢話少說(shuō),讓我們開始吧~ (? ?????)?

創(chuàng)建一個(gè) template

組件來(lái)說(shuō)猴鲫,大多代碼在Vue2和Vue3都非常相似对人。Vue3支持碎片(Fragments),就是說(shuō)在組件可以擁有多個(gè)根節(jié)點(diǎn)拂共。

這種新特性可以減少很多組件之間的div包裹元素牺弄。在開發(fā)vue的時(shí)候,我們會(huì)發(fā)現(xiàn)每一個(gè)組件都會(huì)有個(gè)div元素包裹著宜狐。就會(huì)出現(xiàn)很多層多余的div元素势告。碎片(Fragments)解決了這個(gè)問(wèn)題。對(duì)于有完美強(qiáng)迫癥的童鞋“真的時(shí)太棒了”肌厨。我們這里的例子里就不展示了培慌,用簡(jiǎn)單的單根節(jié)點(diǎn)的組件。

Vue2 表格template

<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>
復(fù)制代碼

在Vue3的唯一真正的不同在于數(shù)據(jù)獲取柑爸。Vue3中的反應(yīng)數(shù)據(jù)(Reactive Data)是包含在一個(gè)反應(yīng)狀態(tài)(Reactive State)變量中吵护。— 所以我們需要訪問(wèn)這個(gè)反應(yīng)狀態(tài)來(lái)獲取數(shù)據(jù)值。

<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>
復(fù)制代碼

[圖片上傳失敗...(image-ded8c7-1607336905047)]

建立數(shù)據(jù) data

這里就是Vue2與Vue3 最大的區(qū)別 — Vue2使用選項(xiàng)類型API(Options API)對(duì)比Vue3合成型API(Composition API)

舊的選項(xiàng)型API在代碼里分割了不同的屬性(properties):data馅而,computed屬性祥诽,methods,等等瓮恭。新的合成型API能讓我們用方法(function)來(lái)分割雄坪,相比于舊的API使用屬性來(lái)分組,這樣代碼會(huì)更加簡(jiǎn)便和整潔屯蹦。

現(xiàn)在我們來(lái)對(duì)比一下Vue2寫法和Vue3寫法在代碼里面的區(qū)別维哈。

Vue2 - 這里把兩個(gè)數(shù)據(jù)放入data屬性中

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  }
}
復(fù)制代碼

Vue3.0,我們就需要使用一個(gè)新的setup()方法登澜,此方法在組件初始化構(gòu)造的時(shí)候觸發(fā)阔挠。

為了可以讓開發(fā)者對(duì)反應(yīng)型數(shù)據(jù)有更多的控制,我們可以直接使用到 Vue3 的反應(yīng)API(reactivity API)脑蠕。

使用以下三步來(lái)建立反應(yīng)性數(shù)據(jù):

  1. 從vue引入reactive
  2. 使用reactive()方法來(lái)聲名我們的數(shù)據(jù)為反應(yīng)性數(shù)據(jù)
  3. 使用setup()方法來(lái)返回我們的反應(yīng)性數(shù)據(jù)购撼,從而我們的template可以獲取這些反應(yīng)性數(shù)據(jù)

上一波代碼,讓大家更容易理解是怎么實(shí)現(xiàn)的谴仙。

import { reactive } from 'vue'

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

    return { state }
  }
}
復(fù)制代碼

這里構(gòu)造的反應(yīng)性數(shù)據(jù)就可以被template使用迂求,可以通過(guò)state.usernamestate.password獲得數(shù)據(jù)的值。

[圖片上傳失敗...(image-db3f3c-1607336905046)]

Vue2 對(duì)比 Vue3的 methods 編寫

Vue2 的選項(xiàng)型API是把methods分割到獨(dú)立的屬性區(qū)域的晃跺。我們可以直接在這個(gè)屬性里面添加方法來(lái)處理各種前端邏輯揩局。

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    login () {
      // 登陸方法
    }
  }
}
復(fù)制代碼

Vue3 的合成型API里面的setup()方法也是可以用來(lái)操控methods的。創(chuàng)建聲名方法其實(shí)和聲名數(shù)據(jù)狀態(tài)是一樣的掀虎⌒逞— 我們需要先聲名一個(gè)方法然后在setup()方法中返回(return), 這樣我們的組件內(nèi)就可以調(diào)用這個(gè)方法了涩盾。

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

    const login = () => {
      // 登陸方法
    }
    return { 
      login,
      state
    }
  }
}
復(fù)制代碼

[圖片上傳失敗...(image-fbaafd-1607336905046)]

生命周期鉤子 — Lifecyle Hooks

Vue2,我們可以直接在組件屬性中調(diào)用Vue的生命周期的鉤子励背。以下使用一個(gè)組件已掛載(mounted)生命周期觸發(fā)鉤子春霍。

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

現(xiàn)在 Vue3 的合成型API里面的setup()方法可以包含了基本所有東西。生命周期的鉤子就是其中之一叶眉!

但是在 Vue3 生周期鉤子不是全局可調(diào)用的了址儒,需要另外從vue中引入。和剛剛引入reactive一樣衅疙,生命周期的掛載鉤子叫onMounted莲趣。

引入后我們就可以在setup()方法里面使用onMounted掛載的鉤子了。

import { reactive, onMounted } from 'vue'

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

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

    // ...
  }
}
復(fù)制代碼

計(jì)算屬性 - Computed Properties

我們一起試試添加一個(gè)計(jì)算屬性來(lái)轉(zhuǎn)換username成小寫字母饱溢。

Vue2 中實(shí)現(xiàn)喧伞,我們只需要在組件內(nèi)的選項(xiàng)屬性中添加即可

export default {
  // .. 
  computed: {
    lowerCaseUsername () {
      return this.username.toLowerCase()
    }
  }
}
復(fù)制代碼

Vue3 的設(shè)計(jì)模式給予開發(fā)者們按需引入需要使用的依賴包。這樣一來(lái)就不需要多余的引用導(dǎo)致性能或者打包后太大的問(wèn)題。Vue2就是有這個(gè)一直存在的問(wèn)題潘鲫。

所以在 Vue3 使用計(jì)算屬性翁逞,我們先需要在組件內(nèi)引入computed

使用方式就和反應(yīng)性數(shù)據(jù)(reactive data)一樣溉仑,在state中加入一個(gè)計(jì)算屬性:

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

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

    // ...
  }
復(fù)制代碼

接收 Props

接收組件props參數(shù)傳遞這一塊為我們帶來(lái)了Vue2和Vue3之間最大的區(qū)別挖函。this在vue3中與vue2代表著完全不一樣的東西。

Vue2浊竟,this代表的是當(dāng)前組件怨喘,不是某一個(gè)特定的屬性。所以我們可以直接使用this訪問(wèn)prop屬性值振定。就比如下面的例子在掛載完成后打印處當(dāng)前傳入組件的參數(shù)title必怜。

mounted () {
    console.log('title: ' + this.title)
}
復(fù)制代碼

但是在 Vue3 中,this無(wú)法直接拿到props屬性吩案,emit events(觸發(fā)事件)和組件內(nèi)的其他屬性棚赔。不過(guò)全新的setup()方法可以接收兩個(gè)參數(shù):

  1. props - 不可變的組件參數(shù)
  2. content - Vue3 暴露出來(lái)的屬性(emit,slots徘郭,attrs)

所以在 Vue3 接收與使用props就會(huì)變成這樣:

setup (props) {
    // ...

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

    // ...
}
復(fù)制代碼

事件 - Emitting Events

Vue2 中自定義事件是非常直接的靠益,但是在 Vue3 的話,我們會(huì)有更多的控制的自由度残揉。

舉例胧后,現(xiàn)在我們想在點(diǎn)擊提交按鈕時(shí)觸發(fā)一個(gè)login的事件。

Vue2 中我們會(huì)調(diào)用到this.$emit然后傳入事件名和參數(shù)對(duì)象抱环。

login () {
      this.$emit('login', {
        username: this.username,
        password: this.password
      })
 }
復(fù)制代碼

但是在 Vue3中壳快,我們剛剛說(shuō)過(guò)this已經(jīng)不是和vue2代表著這個(gè)組件了,所以我們需要不一樣的自定義事件的方式镇草。

那怎么辦呀眶痰?! ??益?)?

不用慌,在setup()中的第二個(gè)參數(shù)content對(duì)象中就有emit梯啤,這個(gè)是和this.$emit是一樣的竖伯。那么我們只要在setup()接收第二個(gè)參數(shù)中使用分解對(duì)象法取出emit就可以在setup方法中隨意使用了。

然后我們?cè)?code>login方法中編寫登陸事件:

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

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

    // ...
}
復(fù)制代碼

最終的vue2對(duì)比vue3代碼

真的是太棒了因宇,能看到這里的童鞋們七婴,你們現(xiàn)在基本都看到vue2與vue3其實(shí)概念與理念都是一樣的。只是有一些屬性獲取方式和聲名和定義方式稍微變了察滑。一直在鬼哭狼嚎的小小前端開發(fā)猿人們打厘,你們可以松一口氣了吧。

總結(jié)一下贺辰,我覺(jué)得 Vue3 給我們前端開發(fā)者帶來(lái)了全新的開發(fā)體驗(yàn)户盯,更好的使用彈性嵌施,可控度也得到了大大的提升。如果你是一個(gè)學(xué)過(guò)或者接觸過(guò) React 然后現(xiàn)在想使用Vue的話先舷,應(yīng)該特別興奮艰管,因?yàn)楹芏嗍褂梅绞蕉己蚏eact非常相近了 ??!

全新的合成式API(Composition API)可以提升代碼的解耦程度 —— 特別是大型的前端應(yīng)用蒋川,效果會(huì)更加明顯牲芋。還有就是按需引用的有了更細(xì)微的可控性,讓項(xiàng)目的性能和打包大小有更好的控制捺球。

最后我把完成的 Vue2Vue3 的組件代碼發(fā)出來(lái)給大家:

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>
復(fù)制代碼

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>
復(fù)制代碼

希望這篇文章能讓大家體驗(yàn)到一個(gè)比較全面的Vue2與Vue3的開發(fā)區(qū)別缸浦。如果大家還有什么問(wèn)題,可以在評(píng)論中提問(wèn)哦氮兵!

開發(fā)愉快裂逐!~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市泣栈,隨后出現(xiàn)的幾起案子卜高,更是在濱河造成了極大的恐慌,老刑警劉巖南片,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掺涛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡疼进,警方通過(guò)查閱死者的電腦和手機(jī)薪缆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伞广,“玉大人拣帽,你說(shuō)我怎么就攤上這事〗莱” “怎么了减拭?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)区丑。 經(jīng)常有香客問(wèn)我峡谊,道長(zhǎng),這世上最難降的妖魔是什么刊苍? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮濒析,結(jié)果婚禮上正什,老公的妹妹穿的比我還像新娘。我一直安慰自己号杏,他們只是感情好婴氮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布斯棒。 她就那樣靜靜地躺著,像睡著了一般主经。 火紅的嫁衣襯著肌膚如雪荣暮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天罩驻,我揣著相機(jī)與錄音穗酥,去河邊找鬼。 笑死惠遏,一個(gè)胖子當(dāng)著我的面吹牛砾跃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播节吮,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抽高,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了透绩?” 一聲冷哼從身側(cè)響起翘骂,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帚豪,沒(méi)想到半個(gè)月后碳竟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡志鞍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年瞭亮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片固棚。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡统翩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出此洲,到底是詐尸還是另有隱情厂汗,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布呜师,位于F島的核電站娶桦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏汁汗。R本人自食惡果不足惜衷畦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望知牌。 院中可真熱鬧祈争,春花似錦、人聲如沸角寸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沮峡,卻和暖如春疚脐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邢疙。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工棍弄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秘症。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓照卦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親乡摹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子役耕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355