开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
vue2 -- vue3 的升级 可以拆分成几个方面,我们可以从这几点开分析, 响应式、DIFF、语法(API)、新增特性、生态, 下面咱们就先逐一查看他都更新了哪些东西, 不过有一些是 破坏式更新,咱们可以留到最后一起搞他
语法
vue3 的语法大部分其实还是复用了 vue2 的语法, 我们主要从下面这几个点 开进行学习
- ref ref 可以创建一个响应式对象,需要通过 .value 访问原始值, 当我们传入复杂数据类型的时候, 底层会调用 reactive
- isRef() 检测某个值是否为 ref
- toRef() 基于响应式对象 创建一个对应的 ref, 相当于解构响应式对象里面的某一个属性,而不破坏响应式
- reactive
不论是哪种写法,我们都可以在 script 上 增加 lang="ts” 用以支持我们的 ts
组合式 API
- 组合式 有两种写法
- 写法一:
<template>
<div class="app">
</div>
</template>
<script lang="ts">
import { defineComponent,ref } from 'vue';
export default defineComponent({
name:'' // 组件名
props:{
type: String,
size: [Number, String],
source: {
type: Object,
required: true,
},
}
components: {
,
},
setup(props,context){
// 代码逻辑
const count = ref(0)
reutrn{
// 需要再模板中访问的数据
count
}
}
});
</script>
这种写法也是需要配置的,包括我们的 组件, watch
,computed
等,这其中 ref
和 reactive
的区别 我会在后面的进阶篇中和大家分享
- 写法二:
<script setup>
import { ref } from 'vue' const count = ref(0)
import empty from '@/components/common/empty/index.vue';
</script>
这种写法不需要我们 进行配置, 导入的组件也不需要注册,我们声明的变量直接可以在模板中使用, 如果使用 vue2 开发的时间比较长,可以先使用写法一进行过渡
注意点
-
- 在 setup 中是没有 this 的, 其中的 this 是
undefined
- 在 setup 中是没有 this 的, 其中的 this 是
-
- 解构 props 会丢失响应式,可以使用 点语法访问,或使用 toRef
-
- setup 的第二个参数 context 上下文对象包含了 emit slots attrs 和 expose 四种属性(非响应式)
-
- setup 可以返回渲染函数,这一点在其源码上,对返回值的类型做了判断,如果返回的是一个函数,就会执行这个函数,返回的是对象,就会将对象中的key进行包装(响应式),后面我们进阶的时候会重点分享一下这里,这里也可以实现 jsx 的配合
-
生命周期
<script setup>
import { ref, onUpdated } from 'vue'
const count = ref(0)
onUpdated(() => {
console.log(document.getElementById('count').textContent) })
</script>
<template> <button id="count" @click="count++">{{ count }}</button>
</template>
- 组合式API 中的生命周期不同于之前 vue2 的, 没有了 beforeCreate 和 created, 因为这两个生命周期的执行时机 就相当于我们 setup 函数,其他的生命周期需要我们引入,语法上前面加了 on开头, 我们在写接口请求的时候, 是可以直接写在 setup 上的, 可以使用 then 语法, 也可以使用 await, 下面看一下如何在 setup 中使用 await:
// 第一种方式,我们可以生命一个函数,这个函数使用 async , watch 的回调也可以是 async
setup(){
const demo = asynv () => { await *** }
watch(count,async () => { await *** })
}
// 第二种方式 IIFE
setup(){
(async () => {
const data = await getDraftTotalApi({
sourceId: 2,
});
draft_sum.value = data.total;
})();
}
// 第三种方式 顶层 await
这种方式只能在我们的语法糖中使用 结果代码会被编译成 `async setup()`:, async setup 的写法,只能与 suspense 内置组件组合使用,且处于实验阶段。
<script setup>
await P
</script>
选项式 API
<script setup>
import { mapState, mapMutations } from 'vuex'
import { Fold } from '@element-plus/icons-vue';
defineProps({
msg: {
type: String,
required: true
}
})
export default {
data() {
return {
squareUrl: 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png',
}
},
components: {
Fold
},
computed: {
...mapState(['username'])
},
methods: {
...mapMutations(['updateUsername', 'updataRole', 'updateCheckedkeys']),
loginOut() {
}
}
}
</script>
选项式的这种写法 其实和 vue2 基本上就没有什么区别了,生命周期的配置也是没有改变的
新增特性
- Teleport 内置组件 可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。 听起来很简单,使用的时候,应用在模态框的场景可能会多一下,比如我们封装了一个弹窗,这个弹窗在我们封装的组件文件中,但我们最终想让这个弹窗层级实在 body下面, 就可以通过这个内置组件来实现,但是一般在我们使用 组件库的时候,组件库的 model 都会带这种配置项。
// `to` 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。
<button @click="open = true">打开弹窗</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>通过 to 指定父级的弹窗</p>
<button @click="open = false">关闭</button>
</div>
</Teleport>
- Fragments 片段 vue2 不支持多根节点, vue3 的模板中则可以使用多个, 可以 显式定义 attribute, 多跟节点不能进行透传(比如 calss, 会自行继承 合并), 链接: cn.vuejs.org/guide/compo…
- 单文件组件中状态驱动的 css 变量(style 中的 v-bind)
<script setup>
const theme = { color: 'red' }
</script>
<template> <p>hello</p>
</template>
<style scoped>
p { color: v-bind('theme.color'); }
</style>
还有一些新特性我们在项目中不常用到 大家可以访问链接自行查看
v3-migration.vuejs.org/zh/