如何把Vue 2项目升级到Vue 3
使用Vue官方提供的工具(vue-codemod)和教程:
1. Vue 3 搭建项目有三种方式
- vite工具Vitejs.dev[支持React]
优点:远大于Webpack的开发速度,利用ES6中import会发送请求加载文件的特性,拦截请求,做一些预编译,省去了webpack冗长的打包时间;缺点是插件不够多
yarn global add create-vite-app //安装vite
cva project-name //创建项目目录
cd project-name
yarn //安装依赖
yarn dev
- vue-cli脚手架工具
vue create 项目名
- webpack打包工具
主要功能打包JS,不再是任务运行器;
loader
用于加载文件、plugin
用于扩展功能;
提供webpack-dev-server
2. Vue3的Template支持多个根标签,Vue2不支持
3. Vue3有createApp()
,而Vue2的是new Vue()
createApp(组件)
接受的是组件;
new Vue({template, render})
接受的是对象;
4. 升级到 Vue 3 后的两种API风格
Options API(传统 Vue 2)
用包含多个选项的对象来描述组件的逻辑,例如 data
、methods
和 mounted
。选项所定义的属性都会暴露在函数内部的 this
上,它会指向当前的组件实例
组合式 API (Composition API 借鉴React的Hooks)
用导入的 API 函数来描述组件逻辑,用<script setup>
标记告诉Vue编译时处理
- 使用
setup()
入口函数,在beforeCreate和created之间执行
beforeCreate // 组件刚被创建出来,组件中的data,methods还没有初始化好
setup
created // 组件刚被创建出来,组件中的data,methods已经初始化好了
// ref函数只能监听简单类型的变化,不能监听复杂类型的变化(数组,对象等)
import { ref } from 'vue'
export default{
setup(){
let count=ref(0)
//定义了一个名字为count的变量,且初始值为0,此值发生变化时vue会自动更新UI
function myFn(){
console.log(count.value)
count.value+=1
}
return { count,myFn }
//需要注意的是在组合API中定义方法,变量时要想在外部使用,必须return暴露出去
}
}
为什么要有组合式 API?
- 弥补选项式 API 中逻辑复用
mixins
机制的缺陷 - 逻辑集中:将一个逻辑关注点抽取重构到一个可复用的工具函数中
- 更好的类型推导:支持TS
与选项式 API 的关系
- 组合式 API 能够覆盖所有状态逻辑方面的需求。除此之外,只需要用到一小部分选项:
props
,emits
,name
和inheritAttrs
。 - 组合式 API 更适用于大型的项目,选项式 API适用于中小型项目
5. 路由用于页面切换Vue Router 4
npm info vue-router versions //查所有版本号
yarn add vue-router@4.0.0-beta.3 //安装vue-router
- 初始化
import {createWebHashHistory, createRouter} from 'vue-router'
const history = createWebHashHistory() //新建 history 对象
const router = createRouter({ //新建 router 对象
history:history,
routes:[
{path:'', component:Frank},
{path:'/xxx', component:Frank2}
]
})
const app = createApp(App)
app.use(router)
app.mount('#app')
//App.vue
//添加 <router-view>和<router-link>
<template>
<div>导航栏 | <router-link to="/">Frank</router-link>
| <router-link to="/xxx">Frank 2</router-link>
</div>
<hr/>
<router-view />
</template>
<script>
export default {
name: 'App',
}
</script>
6. 编程模型:内部数据v.s.父子数据
- 所有数据都在内部
setup(){
const checked = ref(false)
const toggle = ()=>{
checked.value = !checked.value
}
return {checked, toggle}
}
- 父子数据
值是从父组件拿到,该值需要通过input
事件告诉父组件要改value
,父组件改完之后,把最新的值再给子组件
setup(props, context){
const toggle = ()=>{
context.emit('input', !props.value)
}
}
7. v-model用法
- 简写效果
<Switch :value="y" @input="y = $event" />
<Switch v-model:value="y" /> //v-model简写
-
要求 属性名任意,假设为
x
,事件名必须为'update:x'
-
Vue 2用的
.sync修饰符
也被弃用
8. 属性绑定
- 默认所有属性都绑定到根元素
- 取消绑定:
inheritAttrs:false
- 获取所有属性:
$attrs
或者context.attrs
- 批量绑定属性:
v-bind="$attrs"
- 属性分开:
const {size, ...rest}=context.attrs
9. Vue 3组件传值之props与attrs的区别
$attrs属性是props属性的加强版,用于简化vue组件传值,区别为:\
- props要先声明才能取值,attrs不用先声明
- props声明过的属性,attrs里不会再出现
- props不包含事件,attrs包含
10. 用ref()
定义响应式变量
基于JS自身没有可以作用于所有值类型的"引用"机制,因此
Vue
提供了一个ref()
方法来允许创建可以使用任何值类型的响应式ref
ref()
将传入参数的值包装为一个带 .value
属性的 ref 对象
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
ref()
让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用。这个功能很重要,因为它经常用于将逻辑提取到组合函数中。
为 ref()
标注类型
- 在调用
ref()
时传入一个泛型参数,来覆盖默认的推导行为
// 得到的类型:Ref<string | number>
const year = ref<string | number>('2020')
year.value = 2020 // 成功!
// 推导得到的类型:Ref<number | undefined>
const n = ref<number>()