Vue3新特性
vue2 更新到 vue3
首先卸载旧版本
npm uninstall vue-cli -g
然后安装新版本
npm install -g @vue/cli
项目创建方式
在vue3 中有 三种项目创建方式
使用脚手架 Vite
在以往 Vue使用的是vue-cli脚手架, React使用 create-react-app脚手架,虽然脚手架工具不同,但是内部的打包工具还是webpack。而Vite脚手架的底层打包工具是 Rollup 支持打包多页应用程序和工具库,所以Vite脚手架能够在多个框架中都能够使用。
Vite 为什么比webpack快启动快?
在webpack中,每次启动都会把整个程序进行打包,而且热部署的时候会把相关的依赖再打包
Vite 把项目分成了两个部分 依赖配置和源代码
依赖配置 依赖部分不会经常变,所以Vite会提前把用到的依赖打包并保存到
node_modules/.vite
文件中,依赖的打包使用的是ESBuild工具,使用GO语言开发的所以速度要比JavaScript快得多。Vite 只有在 第一次启动/依赖变动/配置变动 才会重新打包依赖,打包完成之后通过http缓存到浏览器中
源代码 直接运行在浏览器中,利用浏览器原生的ESM语法加载模块,当源代码发生变化时,模块热部署只会更新当前页面中的最少的代码
缺点
- HMR有时不会更新
- 有些错误提示不友好
使用Vite创建项目
npm init vite@latest [项目名] -- --template vue
图形化创建
vue ui
vue3 中提供了一种图形化创建项目的的方式,运行命令之后, 就会启动一个本地服务,类似于控制台,所有的插件配置的修改都可以通过傻瓜式的方式
vue create [项目名]
新特性
CompositionAPI
Vue2.x
vue2.x是使用的 Options API 也就是选项,在脚本中会定义 data,methods,computed等等属性,可以把他们看成一个一个的选项,然后使用这些选项进行开发。
当代码很少时,使用OptionsAPI开发会使代码结构很清晰。但是当代码量过多时,代码会变得非常臃肿,一个功能可能用到了多个选项属性,散落在各个地方,会使我们的代码变得难以阅读和维护。而CompositionAPI就是为了解决这个问题
Vue3.x
CompositionAPI 是基于函数组合的API 又叫组合式API,可以将一个功能中不同的代码放在一个函数中。还可以根据业务进行部分逻辑封装。为vue应用提供了更好的逻辑复用和代码组织 你
当然,vue2的mixin也可以实现,但是在mixin中,当多个mixin合在一起且其中有重名的变量时会发生错误,还有当代码量过多时会分不清哪一块逻辑属于哪一个mixin的问题。
CompositionAPI的使用
setup函数
- setup 是使用 CompositionAPI 的入口,关于CompositionAPI的代码都写在setup函数中
- setup 又是一个生命周期钩子函数,它会在 beforeCreate 之前调用
- 在setup中,不能使用this
- 在setup中定义的数据或方法,若需要在模板中使用则都必须要return出去
下面介绍一下Vue2 OptionsAPI 中 各个选项在 Vue3 中的实现
data
data在vue2中用于定义响应式的数据引用,在vue3中则使用ref函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
<div id="app">
<p>{{name}}</p>
<p>{{age}}</p>
</div>
</template>
<script>
// 1. 导入ref 函数
import { ref } from 'vue'
export default {
setup() {
// 2. 使用ref函数定义数据,此时定义的name是一个响应式对象
const name = ref('fish')
const age = ref(18)
// 3. 若需要在模板中使用name这个响应式对象,则需要把name 放在一个对象中并返回
return { name, age }
}
}
</script>methods
在vue3中定义方法,直接在setup函数中定义即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<template>
<div id="app">
<p>{{name}}</p>
<p>
{{age}}
<!-- 绑定事件 -->
<button @click="addAge">+</button>
</p>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const name = ref('fish')
const age = ref(18)
// 创建对应事件函数
function addAge(){
// age++; 此时的age是一个响应式对象,不是一个Number变量
// 若需要修改它,则修改他的value属性
age.value++
}
// 将函数返回
return { name, age, addAge }
}
}
</script>computed
vue3中的计算属性需要将 computed方法导入,然后传入回调函数进行数据处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<template>
<div id="app">
<p>{{name}}</p>
<p>
<button @click="changeAge(-1)">-</button>
{{age}}
<button @click="changeAge(1)">+</button>
</p>
<p>出生年份 {{year}}</p>
</div>
</template>
<script>
// 导入 computed计算属性
import { ref, computed } from 'vue'
export default {
setup() {
const name = ref('fish')
const age = ref(18)
// 调用计算属性方法,并传入一个回调函数,进行数据处理
const year = computed(()=>{
return 2021 - age.value
})
function changeAge(value){
age.value += value
}
// 将计算属性返回
return { name, age, changeAge, year }
}
}
</script>
- watch
1 | <template> |
生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<template>
<div id="app">
</div>
</template>
<script>
// 导入 生命周期钩子
// 在vue3中 可用的钩子如下
//onBeforeMount
//onMounted
//onBeforeUpdate
//onUpdated
//onBeforeUnmount
//onUnmounted
//onActivated
//onDeactivated
//onErrorCaptured
import { onMounted, onUpdated, onUnmounted } from 'vue'
export default {
setup() {
onBeforeMount(() => {
// ...
})
onMounted(() => {
// ...
})
onBeforeUpdate(() => {
// ...
})
}
}
</script>
响应式对象
在上面的代码中可以看到,如果定义的数据或方法很多时,return语句就会很长。所以vue3提供了一个 reactive函数,可以定义一个响应式对象,然后把想要return的值都放在这个对象里面,使用了响应式对象,声明的时候就可以不使用ref
1 | <template> |
当使用reactive时,需要在模板中使用 data.属性名 才可以取到值。我们可以使用 toRefs 函数
1 | <template> |
setup 的参数
props 用于接受参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44<template>
<div id="app">
<p>{{name}}</p>
<p>
<button @click="changeAge(-1)">-</button>
{{age}}
<button @click="changeAge(1)">+</button>
</p>
<p>出生年份 {{year}}</p>
</div>
</template>
<script>
import { computed, reactive, toRefs, watch } from 'vue'
export default {
props:{
title: String
},
// 定义props接收参数
setup(props) {
// 然后传入setup中
const data = reactive({
name: 'fish',
age: 18,
year: computed(()=>{
return 2021 - data.age
})
});
function changeAge(value){
data.age += value;
}
watch(()=> data.age, (newAge, oldAge)=>{
console.log(newAge);
console.log(props.title);
// 随后即可取到props中的值
})
return { ...toRefs(data), changeAge }
}
}
</script>context
之前说到在setup中没有this,但是某些功能确实需要this时,可以使用context
1 | <template> |
自定义指令
1 | //在 vue2 中,自定义指令是通过Vue的directive方法 |
变化较大的地方
移除了 filter 过滤器,转而使用 计算属性代替
移除了 $children ,如果需要访问子组件实例,建议使用 $refs
移除了 Vue.extend
在vue3 中可以有多个根节点
Vue.prototype 替换成 config.globalProperties
1
2
3
4
5
6// 之前 - Vue 2
Vue.prototype.$http = () => {}
// 之后 - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}dom 相关操作
1
2
3
4
5import { nextTick } from 'vue'
nextTick(() => {
// 一些和 DOM 有关的东西
})注册组件
1 | import ComA from './components/ComA.vue'; |