修身养性,知行合一

  • 首页
  • 爱码
    • 系统
    • 数据库
    • JavaScript
    • CSharp
    • Python
  • 生活
    • 文化
    • 美食
  • 杂谈
  • 关于
修身养性,知行合一
码字,杂谈
  1. 首页
  2. 爱码
  3. 前端
  4. JavaScript
  5. Vue
  6. 正文

vue3上手 -- 更新 jz-gantt 小记

2021年9月26日 4281点热度 2人点赞 3条评论

开始之前

vue3 虽然已经出了快1年了,也没怎么好好用过,就是刚出来的时候尝了个鲜。然后紧跟着就一直在鼓捣 .net 的东西,前阵子搞了搞 docker,最近终于有时间正儿八经的用一下 vue3 了。哪里上手呢,之前有人问我有没有升级 jz-gantt 组件的计划。正好赶着这段时间连学习带升级,把它搞了。

什么是 jz-gantt

具体的甘特组件,之前写过 文章,同时也可以到 GitHub 查看源码,放了两个版本。

文档我也更新了,在 这里。

欢迎有需要的朋友们点个 star,也欢迎提 issue。

升级小记

vue3 的升级确实带来了更多的变化,Composition API 提供了更多的灵活性,所以在写组件时,我选择将之前的 jsx 方式更换为普通的 vue 文件方式。

不用 vuex 也是必须的,毕竟是内部组件,根本用不到组件,之前组件通信用的是 provide 和 inject,本来这样的方式在 vue3 中问题也不大,但是既然有更灵活的 Composition API,为什么不用用呢。

全局变量

Composition API 的灵活,我觉得不仅仅是可以复用,它打破了原来但组件中变量的界限,现在可以在一个组件中给全局变量赋值,然后在其他组件中使用,这样的方式简直爽的不要不要的。

当然这种方式一定要注意加载的先后顺序。

比如将根组件 ref 一下:

<template>
  <div ref="rootRef" class="gt-root">
  </div>
</template>

平时我们需要在组件内部定义一个变量关联该根组件,然后可以通过 provide 方法将其注册到全局。

现在我们可以用钩子函数,轻松解决。在 composables 文件夹下定义一个 useRootRef.ts 的文件:

import { ref } from "vue";
const rootRef = ref<HTMLDivElement>();

export default function () {
  return { rootRef };
}

将 rootRef 放在函数外面,它就是一个全局变量,当有其他调用该方法的地方出现时,依旧用的是同一个变量,简单多了。而且我们甚至可以在初始的地方使用一个 init 方法,使用的地方套一个 readonly,避免二次修改:

import { ref, readonly } from "vue";
const rootRef = ref<HTMLDivElement>();

export function useInitRootRef() {
  return { rootRef };
}

export default function () {
  return { rootRef: readonly(rootRef) };
}

这样的方式既整洁,又方便。现在哪里需要使用 rootRef,只需要:

const { rootRef } = useRootRef();

即可。

数据代理

得益于 vue3 大量使用 Proxy,我这组件内部的 Proxy 代理数据的方法直接就可以抛弃了。而且也不存在内部检测不到的情况,相比之前确实方便多了。

但是刚开始的时候,确实对于 ref、reactive、computed 等这些响应式方法,用起来有一些别扭。经常会有莫名其妙的 undefined 的 bug,一查就能发现不是少写了 value 就是多写了 value。现在用多了也就慢慢少了。

对于在 setup 中的内容,一定要套上这些方法,不然数据完全不是响应式的。

对于 props,不能直接解构它们,需要逐一通过 toRefs 或者 toRef 来解构,要不然就需要每次都用 props.xxx 来使用。

这些使用上的变化都是为了能有更好的响应式,用多了发现它们用起来还是比较统一的,一些希望的固定值也可以得到比较好的保留。

还有一个就是 reactive 和 computed 的区别。对于某些场景,如样式的传递:

<div :style="rootStyle"></div>
const { bgColor } = toRefs(props);
const rootStyle = computed(() => {
    return {
        background-color: bgColor.value
    }
});

// const rootStyle = reactive({background-color: bgColor.value});

像这样的数据传递,最好用 computed 返回,不要用 reactive,它可能不会响应。

生命周期

有了 setup,基本可以将大部分内容搬到这里面来。生命周期也不例外,我用的比较多的是 onMounted 和 onUpdated。里面的写法大同小异,但是有趣的是,它可以写多个,这也是很灵活的一面,可以将一个逻辑片段放在一个 composables 文件中,然后用过引用的方式调用,这样代码既简洁,可读性还提高了。

watch

watch 方法比之前有意思多了,它可以接收一个列表,同时监控多个属性,这样的方式对于我这个组件来说,根组件大量样式属性,变化时需要调用同一方法,简直爽的不要不要的。

watch(() => [props.bodyStyle, props.color, ...], () => saveStyle())

setup

vue3 最大的变化,在 vue 文件中,可能就体现在这个 setup 函数中了。前面也说了,它可以包含大部分内容。这个函数本身处于生命周期的 beforeCreate 和 created 之间,所以它也是有缺陷的,比如调用组件中的属性,没有 this 等等。

但可以通过参数解决,vue3 在该周期内将组件实例保存到一个变量中,我们可以通过 getCurrentInstance 方法获取。

这里有个问题,我本地开发没问题,但是打包为生产环境之后,该方法永远获取到的是 undefined,看了看好像大家都在说不要在生产环境下使用该方法,遂我放弃使用它。

那么有什么方法呢?

setup(props, {slots, attrs, emit}) {}

这些应该可以解决大部分问题。

对于 setup 中返回的内容过多,可以通过语法糖 <script lang="ts" setup> 轻松解决。

那么随之而来的问题是,参数又该如何定义?

const props = defineProps(sliderProps);
const emit = defineEmits<{
  (e: "row-click", data: any): void;
}>();
const slots = useSlots();
const attrs = useAttrs();

上面的 props 与 emit 定义方式类似,我分别用了参数与类型声明定义,两种方式均可。而 slots 和 attrs 可以获取到想要的插槽内容以及传入内容。

不过使用 setup 语法糖需要注意,不要在模板中写过多不管内容,因为它会默认导出所有定义的内容。推荐将不同的逻辑块封装在不同的 Composition API 中,用到调用即可。

最后

其实 vue3 更多的是思想上的变化,我觉得使用 Composition API 更贴近 react,同时它也保留了 vue2 的用法,叫 Option API。两种方式没有谁更好,只有谁更适合。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: vue
最后更新:2021年10月14日

jeremyjone

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • tyty

    大佬能发一下ts版的示例吗 :lol:

    2021年11月2日
    回复
    • jeremyjone

      @tyty 源码在 github,你看一下

      2021年11月2日
      回复
  • 1a1a

    大佬为什么expand-all这个属性无效

    2023年5月25日
    回复
  • 取消回复

    文章目录
    • 开始之前
    • 什么是 jz-gantt
    • 升级小记
      • 全局变量
      • 数据代理
      • 生命周期
      • watch
      • setup
    • 最后
    最新 热点 随机
    最新 热点 随机
    node-sass 的安装 解决端口被占的问题 vue3 组件 Props 的声明方式 给 div 添加选中状态 请求的取消 rgb 颜色小数兼容问题
    Windows Server 2019安装与配置(二) MongoDB安装后允许其他IP访问的方法 axios的二次封装 使用 windows 命令启动某个程序 resharper2019.3.3最新激活方案 真丶深入理解JavaScript异步编程(最终章):手撸 Promise

    (っ•̀ω•́)っ✎⁾⁾ 开心每一天

    COPYRIGHT © 2021 jeremyjone.com. ALL RIGHTS RESERVED.

    THEME KRATOS MADE BY VTROIS

    京ICP备19012859号-1

    京公网安备 11010802028585号