vue2遷移vue3記錄


1. vue2遷移vue3記錄

開始用Vue3寫項目時,查看V3 遷移指南發現由於全局 Vue API 已更改為使用應用程序實例,相應的很多操作諸如掛載App實例,使用vue-routervuex等都發生了一定的變化,為了以后更快的搭建Vue3項目,把主要的差別簡單記錄如下:

1.1. 掛載方式差別

vue2:

// index.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  render:h=>h(App)
}).$mount('#app')

vue3:

// index.js
import { createApp } from "vue";
import App from './App.vue'

createApp(App).mount("#app");

1.2. 使用vue-router

vue2:

// index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from '@/router'

Vue.use(VueRouter)
const router = new VueRouter({
  routes,
  mode'history',
})
new Vue({
  router,
  renderh => h(App),
}).$mount('#app')
// src/router/index.js
const home = () => import('../pages/home/Home')

const routes = [
  {
    path'',
    redirect'/home'
  },
  {
    path'/home',
    name'home',
    component: home
  }
]

export default routes

vue3:

// index.js
import { createApp } from "vue";
import App from './App.vue'
import router from "./router";

createApp(App).use(router).mount("#app");

// src/router/index.js
import { createRouter, createWebHistory } from "vue-router";

const home = () => import("../views/home/Home");

const routes = [
  {
    path"",
    redirect"/home",
  },
  {
    path"/home",
    name"home",
    component: home,
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes: routes,
});
export default router;

1.3. 使用vuex

vue2:

// index.js
import Vue from 'vue'
import store from '@/store/';

new Vue({
  store,
  render:h=>h(App)
}).$mount('#app')

// src/store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
import actions from './actions'
import getters from './getters';
import mutations from './mutations';

Vue.use(Vuex)

const state = {}

export default new Vuex.Store({
  state,
  actions,
  mutations,
  getters,
})

vue3:

// index.js
import { store } from "./store";

createApp(App).use(store).mount("#app");

// src/store/index.js
import { createStore } from "vuex";
import actions from "./actions";
import getters from "./getters";
import mutations from "./mutations";

const state = () => {};

export const store = createStore({
  state,
  actions,
  getters,
  mutations,
});

1.4. router-view使用keep-alive

vue2:

// App.vue
<transition name="router-fade" mode="out-in">
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
  </keep-alive>

</transition>
<transition name="router-fade" mode="out-in">
  <router-view v-if="!$route.meta.keepAlive"></
router-view>
</transition>

vue3:

// App.vue
<router-view v-slot="{ Component }">
    <transition name="router-fade" mode="out-in">
        <keep-alive>
            <component :is="Component"/>
        </keep-alive>
    </transition>

</router-view>

1.5. Data選項

2.x在根實例上可以聲明為純 JavaScript object MixinData 選項合並像是取並集?深度合並

3.x無論何時都應該聲明為function MixinData 選項合並像是取交集?淺層次執行合並

1.6. emits選項

vue3新增了 emits 選項,和 prop 類似,組件可觸發的事件可以通過 emits 選項被定義:

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>

</template>
<script>
  export default {
    props: ['text'],
    emits: ['accepted']
  }
</
script>

1.7. 事件api

2.x中用於事件總線上的$on/$off/$once實例方法已被移除

1.8. 過濾器

2.x的過濾器已被移除,3.x建議使用計算屬性或方法來替換過濾器,全局過濾器可以通過全局屬性在所有組件中使用它:

// main.js
const app = createApp(App)

app.config.globalProperties.$filters = {
  currencyUSD(value) {
    return '$' + value
  }
}

然后,你可以通過 $filters 對象修改所有的模板,像下面這樣:

<template>
  <h1>Bank Account Balance</h1>
  <p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>

注意,這種方式只能用於方法中,不可以在計算屬性中使用,因為后者只有在單個組件的上下文中定義時才有意義。

1.9. 片段

3.x支持多根節點的組件,但是要求開發者顯式定義 attribute 應該分布在哪里。

<!-- Layout.vue -->
<template>
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>

1.10. 全局api

3.x中調用 createApp 返回一個應用實例,任何全局改變 Vue 行為的 API 現在都會移動到應用實例上,以下是當前 2.x 全局 API 及其相應實例 API 的表:

2.x 全局 API 3.x 實例 API (app)
Vue.config app.config
Vue.config.productionTip removed
Vue.config.ignoredElements app.config.isCustomElement
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties

1.11. key attribute

3.x中在template上設置v-forkey要加在template

1.12. 按鍵修飾符

3.x不再支持使用數字 (即鍵碼) 作為 v-on 修飾符,不再支持 config.keyCodes 配置按鍵別名

1.13. propsData

propsData 選項已經被移除。如果你需要在實例創建時向根組件傳入 prop ,你應該使用 createApp 的第二個參數:

const app = createApp(
  {
    props: ['username'],
    template'<div>{{ username }}</div>'
  },
  { username'Evan' }
)

1.14. 過渡的 class 名更改

3.x中過渡類名 v-enter 修改為 v-enter-from、過渡類名 v-leave 修改為 v-leave-from

1.15. Transition 作為 Root

一個 <transition> 原本希望是被其子元素觸發的,而不是被 <transition> 自己切換。 換做向其組件傳遞一個 prop 就可以達到類似的效果:

<template>
  <transition>
    <div v-if="show" class="modal"><slot/></div>
  </transition>

</template>
<script>
export default {
  props: ['show']
}
</
script>
<!-- 用法 -->
<modal :show="showModal">hello</modal>

1.16. 移除v-on.native修飾符

  • 刪除 .native 修飾符的所有實例。
  • 確保所有組件都使用 emits 選項記錄其事件。

1.17. v-model

3.x 中,自定義組件上的 v-model 相當於傳遞了 modelValue prop 並接收拋出的 update:modelValue 事件:

<ChildComponent v-model="pageTitle" />

<!-- 是以下的簡寫: -->

<ChildComponent
  :modelValue="pageTitle"
  @update:modelValue="pageTitle = $event"
/>

若需要更改 model 名稱,作為組件內 model 選項的替代,現在我們可以將一個 argument 傳遞給 v-model

<ChildComponent v-model:title="pageTitle" />

<!-- 是以下的簡寫: -->

<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />

而且允許我們在自定義組件上使用多個 v-model

<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />

<!-- 是以下的簡寫: -->

<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>

對於所有不帶參數的 v-model,請確保分別將 propevent 命名更改為 modelValueupdate:modelValue

<ChildComponent v-model="pageTitle" />
// ChildComponent.vue

export default {
  props: {
    modelValueString // 以前是`value:String`
  },
  emits: ['update:modelValue'],
  methods: {
    changePageTitle(title) {
      this.$emit('update:modelValue', title) // 以前是 `this.$emit('input', title)`
    }
  }
}

1.18. v-if和v-for優先級

2.x 版本中在一個元素上同時使用 v-ifv-for 時,v-for 會優先作用。

3.x 版本中 v-if 總是優先於 v-for 生效。

1.19. v-bind合並行為

2.x,如果一個元素同時定義了 v-bind="object" 和一個相同的單獨的 property,那么這個單獨的 property 總是會覆蓋 object 中的綁定。

<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="red"></div>

3.x,如果一個元素同時定義了 v-bind="object" 和一個相同的單獨的 property,那么聲明綁定的順序決定了它們如何合並。換句話說,相對於假設開發者總是希望單獨的 property 覆蓋 object 中定義的內容,現在開發者對自己所希望的合並行為有了更好的控制。

<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="blue"></div>

<!-- template -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- result -->
<div id="red"></div>

1.20. VNode 生命周期事件

3.x父組件可以通過vnode-生命周期鈎子來監聽子組件生命周期中的關鍵階段。

<template>
 <child-component @vnode-updated="onUpdated">
</template>

或者在駝峰命名法的情況下附帶前綴 vnode

<template>
  <child-component @vnodeUpdated="onUpdated">
</template>

1.21. watch Array

3.x當使用 watch 選項偵聽數組時,只有在數組被替換時才會觸發回調。換句話說,在數組改變時 watch 回調將不再被觸發。要想在數組改變時觸發 watch 回調,必須指定 deep 選項。

watch: {
  bookList: {
    handler(val, oldVal) {
      console.log('book list changed')
    },
    deeptrue
  },
}


免責聲明!

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



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