发现个Vue3的问题,感觉写Vue3的响应式反而增加了心智负担

121 阅读1分钟
  1. 编写了一个用途是处理class样式的hook,用于为所有的css类增加一个前缀

  2. 代码大概如下,返回computed的本意是响应属性的变化

  1. 本来想要的用法是这样,最终想要在config.prefix和props.disabled发生变化的时候,自动重新计算computed

但是,上面这种写法,在props.disabled变化的时候压根不会响应。不光如此,想让他响应起来,可能要费点劲。

写vue3的时候,需要额外考虑这个对象是否响应,是否是Ref,增加了很多心智负担

这里有一个最小复现的demo,如下:

父组件:

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld :disabled="disabled" />
</template>

<script>
import HelloWorldVue from "./components/HelloWorld.vue";
export default {
  name: "App",
  components: {
    HelloWorld: HelloWorldVue,
  },
  data() {
    return {
      disabled: false,
    }
  },
  mounted() {
    setInterval(() => {
      this.disabled = !this.disabled;
    }, 1000);
  }
};
</script>

子组件:

<template>
  <div :class="className">Hello World!</div>
  <div :class="classNameReactive">Hello World Reactive!</div>
  <div :class="classNameRef">Hello World Ref!</div>
  <div :class="classNameComputed">Hello World Computed!</div>
</template>

<script setup>
import { reactive, computed, ref } from "vue";
import { useClassName, useClassNameRef } from "./useClassName";

const props = defineProps({
  disabled: Boolean,
});


const className = useClassName({
  "hello-world-disabled": props.disabled,
});
const classNameReactive = useClassName(reactive({
  "hello-world-disabled": props.disabled,
}));

const refClassItem = ref({
  disabled: props.disabled
});
const classNameRef = useClassNameRef(refClassItem);

const computedClassItem = computed(() => {
  return { "hello-world-disabled": props.disabled }
})

const classNameComputed = useClassNameRef(computedClassItem);

</script>

useClassName.js:

import { computed, unref } from 'vue';

export function useClassName(cls) {

  return computed(() => {

    return Object.keys(cls).reduce((list, key) => {
      const value = cls[key];
      if (value) {
        return [...list, key];
      }
      return list;
    }, [])
  });
}

export function useClassNameRef(cls) {

  return computed(() => {
    const unrefCls = unref(cls)
    return Object.keys(unrefCls).reduce((list, key) => {
      const value = unrefCls[key];
      if (value) {
        return [...list, key];
      }
      return list;
    }, [])
  });
}

最后,发现了一个看起来不那么蠢的写法

通过传递方法将依赖收集延迟到computed中进行

如图,用的时候传递方法

谁还有更合理的写法,大家交流交流