1. 更改script标签
为了方便写代码,在这里我们使用<script setup>...<script>标签
2. 定义变量的不同
vue2中的data()内是用来定义变量的,如
<script> export default { data () { return { loginForm: { username: "", password: "", code: "", rpassword: "" }, passwordType: "password" } } </script>
而在vue3里我们使用ref()定义简单数据类型,reactive()定义复杂数据类型 上述的变量即可定义为:
<script setup> import {getCurrentInstance, ref, reactive} from 'vue' const loginForm=reactive({ username: "", password: "", code: "", rpassword: "" }) const passwordType=ref("password")
在这里我建议不要用reactive声名数据类型,因为它不支持直接赋值,只能为里面的子对象赋值,所以上述代码可以写成
<script setup> import {getCurrentInstance, ref, reactive} from 'vue' const loginForm=ref({ username: "", password: "", code: "", rpassword: "" }) const passwordType=ref("password")
在<script>
标签里,若是vue2,可以直接使用this.passwordType调用这个变量,但是在vue3中不可以使用this,在调用变量时,直接用passwordType.value即可调用,如:
const exmaple=()=>{ passwordType.value="" }
注:若在<template>
内,不需要加.value,与vue2一样直接调用即可
3. 定义方法(函数)的不同
在vue2中使用的是methods,在其中定义方法,如:
<script> export default { data () { return { loginForm: { username: "", password: "", code: "", rpassword: "" }, passwordType: "password" } } methods: { showPassword () { this.passwordType == "" ? (this.passwordType = "password") : (this.passwordType = ""); } } </script>
在vue3中,直接定义即可
<script setup> import {getCurrentInstance, ref, reactive} from 'vue' const loginForm=ref({ username: "", password: "", code: "", rpassword: "" }) const passwordType=ref("password") const showPassword = () => { passwordType.value === "" ? (passwordType.value = "password") : (passwordType.value = ""); }
4. vue3该如何使用this
在vue2中我们总是使用this来调用相关属性,但是在vue3中没有this,所以我们使用getCurrentInstance()来获取上下文属性
const { proxy } = getCurrentInstance(); //获取上下文实例,proxy=vue2的this
当我们需要调用相关操作时,可以使用proxy直接调用,如:
proxy.$axios.post("/login",loginForm).then()
5.自定义指令
在Vue3中,Vue实例的全局API已经发生了变化。例如,我们使用createApp来创建Vue实例,而不是使用Vue构造函数。另外,Vue.directive已经被移动到了app.directive中。你需要更新你的代码以使用新的全局API。
以下是一个Vue2应用程序中使用全局API的示例:
Vue.directive('my-directive', { bind: function (el, binding, vnode) { // do something } })
以下是相同应用程序的Vue3版本:
import { createApp } from 'vue' const app = createApp({}) app.directive('my-directive', { beforeMount: function (el, binding, vnode) { // do something } })
6.v-if 和v-for 优先级发生变化
2.x 版本在一个元素上同时使用v-if 和 v-for,v-for会优先作用,3.x中v-if 总是优先于 v-for,可视化项目有大量v-if 和 v-for使用场景,此变化必然影响逻辑判断
7.v-bind=“object” 现在排序敏感
-
Vue 2.x 如果一个元素同时定义了 v-bind=“object” 和一个相同的单独的 property,那么这个单独的 property 总是会覆盖 object 中的绑定。
-
Vue 3.x 声明绑定的顺序决定了它们如何合并。
**此修改影响应该不大**
// 2.x中 id最终为red 3.x中 id为blue <div id="red" v-bind="{ id: 'blue' }"></div>
8.v-for 中的 ref 不再注册 ref 数组
-
Vue 2 中,在 v-for 里使用 ref属性时,从$refs中获取的相应属性会是一个ref数组。
-
Vue 3中则将ref绑定到一个更灵活的函数上 (ele) => { …//保存ele的操作 }:
**此修改影响应该不大**
template:
<div v-for="item in list" :ref="setItemRef"></div>
script:
import { ref, onBeforeUpdate, onUpdated } from 'vue' export default { setup() { let itemRefs = [] const setItemRef = el => { itemRefs.push(el) } onBeforeUpdate(() => { itemRefs = [] }) onUpdated(() => { console.log(itemRefs) }) return { itemRefs, setItemRef } } }
9.default prop 工厂函数不再可以访问 this 上下文
<template> <div> props默认值的工厂函数 <br/> {{parentMsg}} </div> </template> <script> export default { props:{ parentMsg:{ default(){ //这里输出this为null return "工厂函数的值" } } } } </script>
把组件接收到的原始 prop 作为参数传递给默认函数,这个prop是传递给组件的原始值
10.自定义指令的 API 已更改为与组件生命周期一致,且 binding.expression 已移除
vue3中指令api和组件的api保持一致,具体的表现有:
-
created - 新增!在元素的 attribute 或事件监听器被应用之前调用。
-
bind → beforeMount
-
inserted → mounted
-
beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
-
update → 移除!该钩子与
updated
有太多相似之处,因此它是多余的。请改用updated
。 -
componentUpdated → updated
-
beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用。
-
unbind -> unmounted
11.来自 mixin 的 data 选项现在为浅合并
将共享数据提取到外部对象并将其用作 data 中的 property
重写对共享数据的引用以指向新的共享对象
当来自组件的 data()
及其 mixin 或 extends 基类被合并时,合并操作现在将被浅层次地执行:
const Mixin = { data() { return { user: { name: 'Jack', id: 1 } } } } const CompA = { mixins: [Mixin], data() { return { user: { id: 2 } } } }
在 Vue 2.x 中,生成的 $data
是:
{ "user": { "id": 2, "name": "Jack" } }
在 3.0 中,其结果将会是:
{ "user": { "id": 2 } }
12.一些过渡的 class 被重命名
过渡类名 v-enter
修改为 v-enter-from
、过渡类名 v-leave
修改为 v-leave-from
。
13.<TransitionGroup>不再默认渲染包裹元素
Vue 2.x 的<transition-group>
Vue 2.x <transition-group>
跟自定义组件一样,需要一个根元素。我们可以通过tag
prop 来进行手动设定。如果我们不进行手动的设定,Vue 会默认添加<span>
作为根元素。
<template> <transition-group tag="ul"> <li v-for="item in items" :key="item"> {{ item }} </li> </transition-group> </template> <script> export default { data() { return { items: [1, 2, 3], }; }, }; </script>
Vue 3.x <transition-group> 不再需要根元素 到了 Vue 3.x,Vue 不再需要添加根元素。但是我们仍可以通过tag prop 来进行手动设定根元素。只是如果我们不主动设置,Vue 不再会自动添加<span>根元素了。
如果您已经tag在Vue 2代码中定义了prop,就像上面的示例一样,一切将像以前一样工作 如果您没有定义一个样式,而您的样式或其他行为依赖于<span>根元素的存在才能正常工作,则只需添加 tag="span" 到 <transition-group>:
<transition-group tag="span"> <!-- --> </transition-group>
14.当侦听一个数组时,只有当数组被替换时,回调才会触发,如果需要在变更时触发,则必须指定 deep 选项
15.vuex 调整
升级前,我们使用时写法一般如下:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ modules: { ... }, ... })
升级后,修改为如下写法:
import { createStore } from 'vuex' const store = createStore({ modules: { ... }, ... })
16.vue-router 调整
升级前,我们使用时写法一般如下:
import Vue from 'vue' import Router from 'vue-router' const constantRouterMap = { // 路由配置 ... } Vue.use(Router) const createRouter = () => new Router({ ... routes: constantRouterMap }) const router = createRouter() export default router
升级后,修改为如下写法:
import { createRouter, createWebHashHistory } from 'vue-router' const constantRouterMap = { // 路由配置 ... } /* 官方文档说明: 新的 history 配置取代 mode# mode: 'history' 配置已经被一个更灵活的 history 配置所取代。根据你使用的模式,你必须用适当的函数替换它: "history": createWebHistory() "hash": createWebHashHistory() "abstract": createMemoryHistory() 更多内容可以参见官方文档:https://router.vuejs.org/zh/guide/migration/index.html#%E6%96%B0%E7%9A%84-history-%E9%85%8D%E7%BD%AE%E5%8F%96%E4%BB%A3-mode */ const router = createRouter({ history: createWebHashHistory(), // hash模式 scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap, }) export default router
17.main.js 调整
升级前,我们使用时写法一般如下
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' ... import util from './utils/export' // 自己封装的全局通用方法库 // 可以直接这样绑定到Vue的原型链上 Vue.prototype.$util = util ... new Vue({ el: '#app', router, store, render: h => h(App) }).$mount('#app')
升级后,修改为如下写法:
import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' ... import util from './utils/export' ... const app = createApp(App) app.use(router) app.use(store) app.config.globalProperties.$util = util ... app.mount('#app')
18. 更新插件和库
如果你在你的Vue2应用程序中使用了许多插件和库,你需要确保它们也支持Vue3。如果不支持Vue3,你需要寻找一个适配Vue3的替代品。
参考文档介绍 | Vue.js