一、Vue3优缺点
优点
-
使用
Proxy代替Vue2的Object.defineProperty()监听数据实现双向绑定,性能提高1-2倍,(能解决Object.defineProperty()无法监听动态新增的对象属性,数组的索引和length属性,数组push、unshift等问题)。 -
对
Typescript支持更友好,Vue3的源码是用ts编写的,又如props、emits可以跟ts合并使用。 -
Vue3使用
Composition API代替Vue2的Options API,解决Vue2中定义的属性方法分散,需要到处找方法的问题。Composition API更利于维护和阅读,一个功能的代码会都放在一起,尤其在项目大的时候,可以快速找到对应的代码。
- 源码体积更小(tree shaking),diff算法优化、SSR优化。
缺点
-
因为使用
proxy所以不再支持IE11。 -
对于小项目而言Vue2的
Options API更简洁方便。
生命周期变化
| vue2.x | vue3.x |
|---|---|
| beforeCreate | setup |
| created | setup |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestory | onBeforeUnmount |
| destory | onUnmounted |
二、<script setup>和普通<script>的区别和相应的代替用法
2.1 setup语法糖
vue3.2之前变量在setup里必须return
<script>
setup(props) {
return {
title: 'SABER',
name: 'saber',
}
}
</script>
vue3.2开始只需script加上setup属性即可使用
<script setup>
import { ref } from 'vue'
const title = ref('SABER')
const name = ref('saber')
</script>
2.2 ref / reactive
<template>
<p>{{ title }}</p>
<p>{{ obj.title }}</p>
</template>
<script setup>
import { ref, reactive } from 'vue'
// ref声明基本数据类型:
const title = ref('标题1')
// 取值赋值
title.value = '标题2'
// reactive声明引用数据类型:
const obj = reactive({
title: '标题1',
name: '名字1'
})
obj.title = '标题2'
</script>
注:使用reactive只能逐个修改值,要想使用如扩展运算符赋值,以下两种方式可实现:
<script setup>
import { ref, reactive } from 'vue'
const obj = {
title: '标题2',
name: '名字2'
}
// 方法一:使用ref创建引用数据类型
const title = ref({
title: '标题1',
name: '名字1'
})
title.value = {...obj}
// 方法二:使用reactive
const title = reactive({
data: {
title: '标题1',
name: '名字1'
}
})
title.data = {...obj}
</script>
2.3 <style> v-bind的使用
<template>
<button :style="{color: _color}">
颜色是: {{ _color }}
</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const _color = ref<string>('#ff0000')
</script>
<style lang="scss" scoped>
.color {
color: v-bind(_color);
}
</style>
2.4 组件的使用
直接import引用,无需components注册,自动以文件名作为组件名。但是无法自定义组件名,要想自定义组件名可以:
方法一:另写一个普通script。
<script lang="ts">
export default { name: "ChildName" }
</script>
方法二:使用插件vite-plugin-vue-setup-extend,则无需写两个script
<script setup lang="ts" name="ChildName">
代码...
</script>
2.5 props的使用
vue3.2开始defineProps无需引入,直接使用
①运行时声明;②类型声明(Typescript支持)
2.5.1 运行时声明:
<script setup lang="ts">
const props = defineProps({
name: String,
classify: {
type: Number,
default: 0
}
})
</script>
2.5.2 类型声明:
<script setup lang="ts">
const props = defineProps<{
name?: string,
classify?: number
}>()
</script>
要想设置默认值,可以使用辅助函数withDefaults(vue3.2)
<script setup lang="ts">
const props = withDefaults(defineProps<{
name?: string,
classify?: number
}>(), {
name: 'Saber',
classify: 0
})
</script>
2.6 emits的使用
vue3.2开始defineEmits无需引入,直接使用
①运行时声明;②类型声明。
2.6.1 运行时声明:
<script setup lang="ts">
const emits = defineEmits(['func1', 'func2'])
</script>
2.6.2 类型声明:
<script setup lang="ts">
const emits = defineEmits<{
(e: 'func1', data: string): void,
(e: 'func2', data?: number): void,
}>()
</script>
2.7 useAttrs()
接受props里没获取到的其他数据
<template>
<Child :msg1="msg1" :msg2="msg2" title="子组件" />
</template>
<script setup lang="ts">
import { useAttrs } from 'vue'
const props = defineProps('msg1')
const attrs = useAttrs()
// { msg2: 'msg2', title: '子组件' }
</<script>
2.8 defineExpose暴露属性
<script setup lang="ts">
defineExpose({ a, b })
</script>
2.9 provide / inject 多级传递
// parent.vue
<script setup lang="ts">
import { provide } from 'vue'
provide('name', '老脑')
</script>
// child.vue
<script setup lang="ts">
import { inject } from 'vue'
const name = inject('name') // 老脑
</script>
2.10 watch / computed / onMounted 等等
<script setup lang="ts">
const total = computed(() => count.value++)
watch(() => state.count, (newVal) => {
console.log(newVal, '新数据')
})
onMounted(() => {
// todo
})
</script>
2.11 Web Component
借助defineCustomElementAPI将Vue组件转换成Web组件
三、好用的插件
3.1 unplugin-auto-import
自动引入ref、onMounted等api,无需手动声明引入
3.2 @vitejs/plugin-vue-jsx
在vite + vue3.x中使用jsx开发
3.3 vite-plugin-pages
自动生成路由信息,无需配置
3.4 vite-plugin-svg-icons
快速实现svg图标
3.5 vite-plugin-vue-setup-extend
自定义组件名
四、RFC提案
4.1 烦人的.value
不再需要.value取值和赋值
<script setup lang="ts">
// 现在
const loading = ref(true)
loading.value = false
// 未来
const loading = $(ref(true))
loading = false
// 还原成.value
const loading_value = $$(loading)
</script>
4.2 $computed
<script setup lang="ts">
// 现在
const _num = computed(() => num.value++)
// 未来
const _num = $(computed(() => num++))
</script>
4.3 $fromRefs
配合toRefs使用
<script setup lang="ts">
const state = reative({
x: 0,
y: 0
})
// 现在
const {x, y} = toRefs(state)
// 赋值
// x.value = 1; y.value == 2;
// 未来
const {x, y} = $formRefs(toRefs(state))
// 赋值
// x = 1; y = 2;
</script>
4.4 props解构
<script setup lang="ts">
// 现在
const props = defineProps({
title: {
type: String,
default: '123'
}
})
// 取值:props.title
// 未来
const { title = '123' } = $(defineProps({ title: String }))
</script>