vue2.x與vue3.x的對(duì)比

異步組件(vue3.x新增)

vue3.x

  • 由于函數(shù)式組件被定義為純函數(shù)界斜,因此異步組件的定義需要通過(guò)將其包裝在新的 defineAsyncComponent助手方法中來(lái)顯式地定義
import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'

// 不帶選項(xiàng)的異步組件
const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))

// 帶選項(xiàng)的異步組件
const asyncPageWithOptions = defineAsyncComponent({
  loader: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  errorComponent: ErrorComponent,
  loadingComponent: LoadingComponent
})
  • component選項(xiàng)現(xiàn)在被重命名為loader,loader函數(shù)不再接收resolvereject參數(shù),且必須返回promise
const asyncComponent = defineAsyncComponent(
  ()=>new Promise((resolve,reject)=>{
    /*...*/
  })
)

片段(vue3.x新增)

vue3.x
組件可以有多個(gè)根節(jié)點(diǎn)

// vue2.x
<template>
  <div>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </div>
</template>

// vue3.x
<template>
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>

v-for

vue2.x
v-for指令可以綁定數(shù)組的數(shù)據(jù)來(lái)渲染列表

<div v-for="item in items" :key="item.message">
    {{ item.message }}
  </div>

vue3.x
從單個(gè)綁定獲取多個(gè)ref,ref會(huì)通過(guò)迭代的key被設(shè)置(新特性)

<div v-for="item in list" :ref="setItemRef"></div>

自定義元素交互

vue2.x
通過(guò)Vue.config.ignoredElements配置自定義元素白名單

Vue.config.ignoredElements = ['plastic-button']

vue3.x
在模板編譯期間執(zhí)行指示編譯器將<plastic-button>視為自定義元素

  • 如果使用生成步驟:將isCustomElement傳遞給 Vue模板編譯器挎春,如果使用vue-loader涯雅,則應(yīng)通過(guò) vue-loader 的compilerOptions選項(xiàng)傳遞
rules: [
  {
    test: /\.vue$/,
    use: 'vue-loader',
    options: {
      compilerOptions: {
        isCustomElement: tag => tag === 'plastic-button'
      }
    }
  }
]
  • 如果使用動(dòng)態(tài)模板編譯揣钦,通過(guò) app.config.isCustomElement傳遞
const app = Vue.createApp({})
app.config.isCustomElement = tag => tag === 'plastic-button'

自定義內(nèi)置元素的方法是向內(nèi)置元素添加is屬性
v-is要使用注冊(cè)名稱來(lái)渲染組件计贰,其值應(yīng)為 JavaScript字符串文本

<tr v-is="'blog-post-row'"></tr>

Data選項(xiàng)

vue2.x
可以自定義data選項(xiàng)是objectfunction

// object 聲明
<script>
  const app = new Vue({
    data: {
      num: '123'
    }
  })
</script>

// function 聲明 
<script>
  const app = new Vue({
    data() {
      return {
        num: '123'
      }
    }
  })
</script>

vue3.x
data選項(xiàng)只接受返回objectfunction

<script>
  import { createApp } from 'vue'

  createApp({
    data() {
      return {
         num: '123'
      }
    }
  }).mount('#app')
</script>

全局API

vue2.x
有許多全局API和配置,會(huì)全局改變vue的行為

vue3.x
調(diào)用createApp返回一個(gè)應(yīng)用實(shí)例

import {createApp} from 'vue'
const app = createApp({})

config.productionTip移除
config.ignoredElements替換為 config.isCustomElement

下表為2.x與3.x的對(duì)比

2.x 全局 API 3.x 實(shí)例 API (app)
Vue.config app.config
Vue.config.productionTip 已移除
Vue.config.ignoredElements app.config.isCustomElement
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use

全局 API Treeshaking

vue2.x
Vue.nextTick()是一個(gè)全局的 API 直接暴露在單個(gè) Vue 對(duì)象上,回調(diào)的this上下文自動(dòng)綁定到當(dāng)前實(shí)例
webpack支持tree-shaking,但Vue 2.x 的全局 API 比如 nextTick 無(wú)法被 TreeShake,所以就算沒(méi)有用到這些 API孔厉,它們還是會(huì)被打包到你的生產(chǎn)版本的代碼包里

vue3.x
全局和內(nèi)部API進(jìn)行了重構(gòu),支持使用tree-shaking
需要注意的是:
當(dāng)使用全局 API 時(shí)聂抢,需要主動(dòng)將其導(dǎo)入到目標(biāo)文件中

import { nextTick } from 'vue';
 
nextTick(() => {
  // 和 DOM 有關(guān)的一些操作
});

如果直接調(diào)用Vue.nextTick()钧嘶,會(huì)導(dǎo)致報(bào)錯(cuò):undefined is not a function

key attribute

vue2.x
建議在v-if/v-else/v-else-if的分支中使用key

// vue2.x
<div v-if="hhhh" key = "yes">YES</div>
<div v-else key = "no">NO</div>

vue3.x
vue會(huì)自動(dòng)生成唯一的key

<div v-if="hhhh">YES</div>
<div v-else>NO</div>

按鍵修飾符

vue2.x

  • 支持keyCodes作為修改v-on的方法
  • 可以通過(guò)全局config.keyCodes
<!-- 鍵碼版本 -->
<input v-on:keyup.13="submit" />

<!-- 別名版本 -->
<input v-on:keyup.enter="submit" />

vue3.x

  • 不再支持使用數(shù)字 (即鍵碼) 作為v-on 修飾符,建議使用kebab-cased大小寫(xiě)名稱
  • 不再支持 config.keyCodes
<input v-on:keyup.delete="confirmDelete" />

在 prop 的默認(rèn)函數(shù)中訪問(wèn)this

vue3.x
生成 prop 默認(rèn)值的工廠函數(shù)不再能訪問(wèn) this

渲染函數(shù)API

vue2.x

  • render函數(shù)參數(shù)
    render函數(shù)自動(dòng)接收h函數(shù)作為參數(shù)
// vue2.x
export default
  render(h){
    return h('div')
  }
}
  • render函數(shù)簽名更改
    render函數(shù)自動(dòng)接收諸如 h 之類的參數(shù)
// vue2.x
export default{
  render(h){
    return h('div')
  }
}

vue3.x

  • render函數(shù)參數(shù)
    h是全局引入的,而不是作為參數(shù)自動(dòng)傳遞
// vue 3.x
import {h} from 'vue'
export default{
  render(){
    return h('div')
  }
}
  • render函數(shù)簽名更改
    render函數(shù)不再接收任何參數(shù),將主要用于setup()內(nèi)部,可以訪問(wèn)作用域中聲明的響應(yīng)式狀態(tài)和函數(shù)以及傳遞給setup()的參數(shù)
import { h, reactive } from 'vue'

export default {
  setup(props, { slots, attrs, emit }) {
    const state = reactive({
      count: 0
    })

    function increment() {
      state.count++
    }

    // 返回render函數(shù)
    return () =>
      h(
        'div',
        {
          onClick: increment
        },
        state.count
      )
  }
}

slot統(tǒng)一

vue2.x
在內(nèi)容節(jié)點(diǎn)上定義slot data property

h(LayoutComponent,[
  h('div',{slot:'header'},this.header),
  h('div',{slot:'content'},this.content)
])

// 引用時(shí)
this.$scopedSlots.header

vue3.x

  • 插槽被定義為當(dāng)前節(jié)點(diǎn)的子對(duì)象
h(LayoutComponent,{},{
  header:()=>h('div',this.header),
  content:()=>h('div',this.content)
})
  • 當(dāng)需要以編程方式引用作用域slot時(shí),被統(tǒng)一到$slot選項(xiàng)中
this.$slots.header

過(guò)渡類名更改

vue3.x
過(guò)渡類名 v-enter修改為 v-enter-from、過(guò)渡類名v-leave修改為v-leave-from

<transition>組件相關(guān)屬性名也發(fā)生了變化:
leave-class已經(jīng)被重命名為leave-from-class(在渲染函數(shù)或 JSX 中可以寫(xiě)為:leaveFromClass)
enter-class已經(jīng)被重命名為enter-from-class (在渲染函數(shù)或 JSX 中可以寫(xiě)為:enterFromClass)

v-model

vue2.x

  • 使用v-model指令必須使用valueprop;
<ChildComponent v-model="pageTitle" />
  • 如果出于不同的目的使用其他的prop,需要使用v-bind.sync
<ChildComponent :title.sync="pageTitle" />

vue3.x

  • 如果要改變綁定的屬性名琳疏,而不是更改組件內(nèi)綁定的選項(xiàng),只需要給 v-model 傳遞一個(gè)參數(shù)就可以了;
<ChildComponent v-model:title = 'pageitle' />
  • 可以自定義多個(gè)v-model;
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
  • 支持自定義修飾符
<ChildComponent v-model.capitalize="pageTitle" />

v-if與v-for的優(yōu)先級(jí)比較

vue2.x
在同一個(gè)元素上同時(shí)使用v-ifv-for,v-for會(huì)優(yōu)先使用;

vue3.x
v-if總是優(yōu)先于v-for生效

v-bind合并行為

vue2.x
如果一個(gè)元素同時(shí)定義了v-bind="object"和一個(gè)相同的單獨(dú)的property有决,那么這個(gè)單獨(dú)的 property總是會(huì)覆蓋object中的綁定

<div id="red" v-bind="{ id: 'blue' }"></div>
// 結(jié)果
<div id="red"></div>

vue3.x
如果一個(gè)元素同時(shí)定義了v-bind="object"和一個(gè)相同的單獨(dú)的property,那么聲明綁定的順序決定了它們?nèi)绾魏喜?/p>

<div id="red" v-bind="{ id: 'blue' }"></div>
// 結(jié)果
<div id="blue"></div>
<div v-bind="{ id: 'blue' }" id="red"></div>
// 結(jié)果
<div id="red"></div>

函數(shù)式組件

vue2.x

  • 作為性能優(yōu)化
  • 返回多個(gè)根節(jié)點(diǎn)
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}

vue3.x

  • 通過(guò)函數(shù)創(chuàng)建組件
    所有的函數(shù)式組件都是用普通函數(shù)創(chuàng)建的,不需要定義{function:true}組件選項(xiàng)
import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading
  • 單文件組件
<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>

function attribute 在<template>中移除
listeners現(xiàn)在作為$attrs的一部分傳遞,可以刪除

下表為vue3.x已移除的api:

已移除的api vue2.x vue3.x
$children 可以使用this.$children直接訪問(wèn)當(dāng)前實(shí)例的子組件 $children已移除,如需訪問(wèn)子組件,建議使用$refs
事件API vue實(shí)例可用于觸發(fā)通過(guò)事件觸發(fā)API強(qiáng)制附加發(fā)處理程序已創(chuàng)建全局事件監(jiān)聽(tīng)器 移除了$on,$off,$once方法,但仍可用$emit觸發(fā)由父組件以聲明方式附加的事件處理程序
過(guò)濾器 可以使用過(guò)濾器來(lái)處理通用文本格式 過(guò)濾器已刪除,可以用方法調(diào)用或計(jì)算屬性替換過(guò)濾器
內(nèi)聯(lián)模塊Attribute Vue 為子組件提供了inline-template attribute空盼,以便將其內(nèi)部?jī)?nèi)容用作模板书幕,而不是將其作為分發(fā)內(nèi)容 不再支持此功能,所有模板寫(xiě)在HTML頁(yè)面中
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揽趾,隨后出現(xiàn)的幾起案子台汇,更是在濱河造成了極大的恐慌,老刑警劉巖篱瞎,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苟呐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡俐筋,警方通過(guò)查閱死者的電腦和手機(jī)牵素,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)澄者,“玉大人两波,你說(shuō)我怎么就攤上這事∶贫撸” “怎么了腰奋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)抱怔。 經(jīng)常有香客問(wèn)我劣坊,道長(zhǎng),這世上最難降的妖魔是什么屈留? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任局冰,我火速辦了婚禮,結(jié)果婚禮上灌危,老公的妹妹穿的比我還像新娘康二。我一直安慰自己,他們只是感情好勇蝙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布沫勿。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪产雹。 梳的紋絲不亂的頭發(fā)上诫惭,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音蔓挖,去河邊找鬼夕土。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瘟判,可吹牛的內(nèi)容都是我干的怨绣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拷获,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梨熙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起刀诬,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邪财,沒(méi)想到半個(gè)月后陕壹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(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,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡又碌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绊袋,到底是詐尸還是另有隱情毕匀,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布癌别,位于F島的核電站皂岔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏展姐。R本人自食惡果不足惜躁垛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望圾笨。 院中可真熱鬧教馆,春花似錦、人聲如沸擂达。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至舒憾,卻和暖如春镀钓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镀迂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工丁溅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人探遵。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓窟赏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親箱季。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涯穷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容