前言
7月1号,尤大在博客上宣布了 vue2.7 版本的正式发布,这对于 vue2 版本的用户来说绝对是一个利好消息,不需要大刀阔斧的重构就能体验到 vue3 中的核心特性了;
尽管 Vue 3 现在是默认版本,但我们了解到仍有许多用户由于依赖兼容性、浏览器支持要求或根本没有足够的带宽升级而不得不留在 Vue 2。在 Vue 2.7 中,我们从 Vue 3 向后移植了一些最重要的功能,以便 Vue 2 用户也可以从中受益。尤雨溪发布vue2.7 时的介绍
升级流程
package.json 配置升级
注意我的项目基础架构是 webpack 5 + vue 2.6, 没有使用 vue-cli 脚手架哦,以下升级步骤都基于此架构;首先将 node_modules 和 lock.json 文件都删除,修改一下配置,然后重新安装。
- vue-template-compiler 可以删掉了,因为 vue 2.7 中不再需要它
- eslint-plugin-vue 需要升级到 9
javascript
复制代码
// "vue": "^2.6.14", "vue": "^2.7.8", // "vue-template-compiler": "^2.6.14", // "eslint-plugin-vue": "^8.6.0", "eslint-plugin-vue": "^9.0.0",
踩坑:升级过程中遇到的 bug
[webpack-cli] Error: Cannot find module 'ajv/dist/compile/codegen'
分析: ajv 是一个 JSON schema 的模式验证工具(文档),不知道为何 vue2.7 会依赖这个,先不管,我们安装一下试试;
javascript
复制代码
npm install --save-dev ajv@^7
装好这个包后发现这个报错消失了。
Cannot read properties of undefined (reading 'replace')
这个错误最终发现是 node-sass 的版本问题导致的,因为我项目中同时使用了 less、sass, 升到 2.7 后,发现 sass 无法使用了,怀疑是版本问题,尝试升级 node-sass 到 7.0.1, 问题解决。
javascript
复制代码
npm install node-sass@7.0.1
注意 node-sass 依赖的 node 版本至少要 14+,否则找不到包。
/deep/ 语法警告
vue2.7 中不再推荐 /deep/ 这种写法,虽然还能正常使用,但会在控制台报警告信息,建议使用 :deep() 方法来替换。
基于 vue 2.7 新特性编写页面
组合式 API 基本用法
组合式 API (Composition API) 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue 组件。它是一个概括性的术语,涵盖了以下方面的 API:
- 响应式 API:例如 ref() 和 reactive(),使我们可以直接创建响应式状态、计算属性和侦听器。
- 生命周期钩子:例如 onMounted() 和 onUnmounted(),使我们可以在组件各个生命周期阶段添加逻辑。
- 依赖注入:例如 provide() 和 inject(),使我们可以在使用响应式 API 时,利用 Vue 的依赖注入系统。
个人最直观的感受是没有 this 对象了,更接近函数式编程的写法,更加简洁了。
基本写法示例
<template> <div> {{data.age}} {{data.name}} <button @click="increment">点击了:{{ count }} 次</button> </div> </template> <script setup> import { ref, onMounted } from 'vue' // ref() 可以接受任何值类型。ref 会返回一个包裹对象,并在 .value 属性下暴露内部值,而在模板中访问 ref 定义的变量时不需要使用 .value const count = ref(0) // reactive 只适用于对象 (包括数组和内置类型,如 Map 和 Set),可以这样写,通过 data.‘propertyName’ 来访问和修改 const data = reactive({ age: 18, name: 'ethan' }) // 更改状态、触发更新的函数 function increment() { count.value++ } // 生命周期钩子 onMounted(() => { console.log(`计数器初始值为 ${count.value}。`) }) </script>
组件无需注册
在使用 <script setup>
的单文件组件中,导入的组件可以直接在模板中使用,无需注册了;
挂载在 Vue.prototype 原型上的方法怎么调用
因为使用 setup, 获取不到 this 对象了,所以挂载在 vue prototype 上的方式调用失败,此时可以使用 getCurrentInstance,不过不推荐;
// proxy 可以代替 this 使用 const { proxy } = getCurrentInstance() proxy.$toast()
路由使用
参考上面,新的 proxy 对象,proxy.$router.push()
计算属性的用法
计算属性在组合式 API 中,以一个函数的形式来使用
const hideCompleted = ref(false) const todos = ref([ /* ... */ ]) const filteredTodos = computed(() => { // 根据 `todos.value` & `hideCompleted.value` // 返回过滤后的 todo 项目 })
监听器的用法
watch(count, (newCount) => { console.log(`new count is: ${newCount}`) })
Props 的使用
组合式API中可以通过 defineProps 方法来定义 props, 注意 defineProps() 是一个编译时宏,并不需要导入,一旦声明,msg prop 就可以在子组件的模板中使用。它也可以通过 defineProps() 所返回的对象在 JavaScript 中访问。
<!-- ChildComp.vue --> <script setup> const props = defineProps({ msg: String }) </script> <ChildComp :msg="greeting" />
Emits 的使用
组合式API中的emits 使用相比vue2.6 来说多了一个生命的过程,需要通过 defineEmits 方法来声明 emits
<script setup> // 声明触发的事件 const emit = defineEmits(['response']) // 带参数触发 emit('response', 'hello from child') </script>
vuex 的使用
组合式API 写法中,mapState 等 vuex 的写法不再支持了,没找到特别好的方案,暂时当成普通 js 文件中那样用;
import store from '@/store/index'; // state store.state.moduleName.stateName //actions store.dispatch("moduleName/actionName", paramsObj);
总结
升级过程总体还是顺利的,主要就是几个包的 版本问题,升级后除了 :deep 需要更换写法外,之前的代码基本上不用改动, 后面基于 2.7,我们可以逐步过渡到组合式 API 的写法上去了。 当然像 vuex 这种貌似在 2.7 中,没有之前使用方便了,这个暂时没有找到啥好的办法。