Vue3js 上手体验

89 阅读2分钟

原帖

最近一直都在使用 vue3,vue3 的优化当然是有目共睹的,但是仍然有一些让我觉得不习惯的地方。

reactive 和 ref

如果使用 setup 语法,reftemplate 里可以直接使用,但是在 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 我是没有想到的

根据 ref,很可能以后还会有一个ref,很可能以后还会有一个 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 类,会出现以下错误

%E6%88%AA%E5%B1%8F2023-01-02_11.30.31.png

正确的完整的写法查看下图。只需要把类型定义的文件单独出来即可。

注意:使用的是 setup 语法

%E6%88%AA%E5%B1%8F2023-01-02_11.32.03.png

还没有完,这样的类型定义,只能获取属性签名,但是不能获取属性值类型提示。你还需要通过默认值的方式,来让编辑器推导出属性值的类型

export class Person {
  // constructor(firstName, lastName) {

  // 设置默认值,让编辑器知道这两个属性都是 string 类型
  constructor(firstName = '', lastName = '') {
    this.firstName = firstName
    this.lastName = lastName
  }
}

可以看到,这种写法很麻烦,但是也有简单的解决方式,就是使用 typescript

在 script 中指定语言为 ts <script setup lang=”ts” >

%E6%88%AA%E5%B1%8F2023-01-02_11.40.25.png

而对于 react ,就比较的简单。因为 react 函数式组件本身就是 js 的语法,并且有 js-doc 的支持,可以很方便的定义组件的 props。

%E6%88%AA%E5%B1%8F2023-01-02_11.53.31.png

第三方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 无法直接执行,它会告诉你它不是个函数;

%E6%88%AA%E5%B1%8F2023-01-02_12.17.20.png

结合 pinia

pinia 确实大大提高了开发效率,并且很容易上手。但是有一个很麻烦的问题,就是如果在使用时进行解构,会导致丢失响应式。当然,官方也提供了解决的方案,但还是麻烦。

%E6%88%AA%E5%B1%8F2023-01-02_12.31.59.png

相对的,react 使用状态管理就可以直接解构使用

这里使用的库是 recoil

%E6%88%AA%E5%B1%8F2023-01-02_12.39.26.png