最近一直都在使用 vue3,vue3 的优化当然是有目共睹的,但是仍然有一些让我觉得不习惯的地方。
reactive 和 ref
如果使用 setup
语法,ref
在 template
里可以直接使用,但是在 script
里需要使用 value
虽然有新语法糖 $ref,但目前版本还没有正常发布。
<script setup>
import { computed, ref } from "vue";
const count = ref(10);
const db = computed(() => count.value * 2);
</script>
<template>
<p>count: {{ count }}</p>
<p>Dubble: {{ db }}</p>
</template>
如果只是在同一个组件内还好,如果是在 hooks
中,很容易被忽略
<script setup>
import { computed, ref } from "vue";
function useMyState() {
const msg = ref("");
return { msg };
}
const { msg } = useMyState();
// 错误
// const len = computed(() => msg.length);
const len = computed(() => msg.value.length);
</script>
<template>
<p>msg {{ msg }}</p>
<p>len {{ len }}</p>
</template>
使用 reactive
时,修改值的时候很麻烦
赋值一个多属性的对象时,和重置对象时
<script setup>
import { onMounted, reactive } from "vue";
const form = reactive({});
onMounted(() => {
const responseFormFetch = { id: "01", name: "Jake" };
Object.assign(form, responseFormFetch);
});
const onResetForm = () => {
form.id = undefined;
form.name = undefined;
};
</script>
<template>
<p>form {{ form }}</p>
<button @click="onResetForm">reset</button>
</template>
如果你使用 ref 来保存对象时,上述问题可以解决,但是又出现 第一点
的问题
计算属性
computed
获取值也要使用 .value
我是没有想到的
根据 computed 的语法糖。
const someState = computed(() => Math.random())
// 无法获取值
console.log('someState', someState)
// 可以获取
console.log('someState', someState.value)
关于自动导入
当你使用 defineProps
并通过 import { defineProps } from "vue";
引入时,会有警告。意思是 defineProps
已经自动导入了,不需要再手动导入。
`defineProps` is a compiler macro and no longer needs to be imported.
无法理解的是,那些常用的 api ,例如 reactive
, ref
, computed
都没有自动导入。
props 的定义和类型检查
根据官方文档说明,定义一些比较简单的 props 还是比较方便的。但是如果需要定义一个具有复杂类型的属性时,就比较的麻烦。
以文档为例:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
}
defineProps({
author: Person
})
例子很简单,但是这样写是会报错的。
如果直接在 script
里面定义并使用 Person
类,会出现以下错误
正确的完整的写法查看下图。只需要把类型定义的文件单独出来即可。
注意:使用的是 setup 语法
还没有完,这样的类型定义,只能获取属性签名,但是不能获取属性值类型提示。你还需要通过默认值的方式,来让编辑器推导出属性值的类型
export class Person {
// constructor(firstName, lastName) {
// 设置默认值,让编辑器知道这两个属性都是 string 类型
constructor(firstName = '', lastName = '') {
this.firstName = firstName
this.lastName = lastName
}
}
可以看到,这种写法很麻烦,但是也有简单的解决方式,就是使用 typescript
在 script 中指定语言为 ts <script setup lang=”ts” >
而对于 react ,就比较的简单。因为 react 函数式组件本身就是 js 的语法,并且有 js-doc 的支持,可以很方便的定义组件的 props。
第三方UI组件的属性提示
以 element-plus
为例,如果使用全局注册的方式,在使用时无法获得组件的属性提示;只有使用按需引入的方式才有提示。
<script setup>
import { ElAvatar } from "element-plus"
</script>
<template>
<h1>Home</h1>
<!-- 当输入 size 时,会有智能提示 -->
<ElAvatar size="large" />
</template>
错误定位有差别
在 template 中有错误的话,编辑器中不会报错,运行之后报错;并且错误的定位有很大偏差
结合 vue query
vue-query 是一个用于管理接口请求的工具库
已知的一些bug:
- 无法监听 props 的变化
- 返回的 api 无法直接执行,它会告诉你它不是个函数;
结合 pinia
pinia 确实大大提高了开发效率,并且很容易上手。但是有一个很麻烦的问题,就是如果在使用时进行解构,会导致丢失响应式。当然,官方也提供了解决的方案,但还是麻烦。
相对的,react 使用状态管理就可以直接解构使用
这里使用的库是 recoil