【问题标题】:Vue 3 Composition API - Props default and DOM inside lifecycle methodsVue 3 Composition API - 生命周期方法中的 Props 默认值和 DOM
【发布时间】:2021-10-14 22:15:55
【问题描述】:

我在 NuxtJS 应用程序中有一个 Vue 组件,我正在使用 @nuxtjs/composition-api。 我有这个组件,它是一个<Link> 组件,我想让代码更清晰。

  1. 我有一个计算属性,它决定了我的UiIcon 的颜色来自iconColor, iconColorHover, IconActive。但最重要的是,如果我的根组件上有一个禁用类,我想将其设置为特定颜色。它是这样工作的,但我相信它看起来不太好。

  2. 我发现undefined 是唯一可以用来获取UiIcon 默认道具(如果未定义)的值。像'' 这样的空字符串会更有意义,但它被视为有效值。我必须在我的UiIcon 中做一些三元条件,我想避免这种情况。

    <template>
      <div ref="rootRef" class="row">
        <UiIcon
          v-if="linkIcon"
          :type="linkIcon"
          :color="linkIconColor"
          class="icon"
        />
        <a
          class="link"
          :href="linkHref"
          :target="linkTarget"
          :rel="linkTarget === 'blank' ? 'noopener noreferrer' : null"
          @mouseover="linkActive = true"
          @mouseout="linkActive = false"
        >
          <slot></slot>
        </a>
      </div>
    </template>
    
    <script lang="ts">
     import {
       defineComponent,
       computed,
       ref,
       toRefs,
       nextTick,
       onBeforeMount,
     } from '@nuxtjs/composition-api';
     import { Colors } from '~/helpers/styles';
    
     export default defineComponent({
      name: 'Link',
      props: {
       href: {
        type: String,
        default: undefined,
       },
       target: {
        type: String as () => '_blank' | '_self' | '_parent' | '_top',
        default: '_self',
       },
       icon: {
        type: String,
        default: undefined,
       },
       iconColor: {
        type: String,
        default: undefined,
       },
       iconHoverColor: {
        type: String,
        default: undefined,
       },
     },
     setup(props) {
       const { href, target, icon, iconColor, iconHoverColor } = toRefs(props);
       const linkActive = ref(false);
       const rootRef = ref<HTMLDivElement | null>(null);
    
       const writableIconColor = ref('');
       const linkIconColor = computed({
         get: () => {
           const linkDisabled = rootRef.value?.classList.contains('disabled');
           if (linkDisabled) {
             return Colors.DARK_GREY;
           }
           if (linkActive.value && iconHoverColor.value) {
             return iconHoverColor.value;
           }
           return iconColor.value;
         },
         set: (value) => {
           writableIconColor.value = value;
         },
       });
    
       onBeforeMount(() => {
         nextTick(() => {
           const linkDisabled = rootRef.value?.classList.contains('disabled');
           if (linkDisabled) {
             linkIconColor.value = Colors.DARK_GREY;
           }
         });
       });
    
       return {
         rootRef,
         linkHref: href,
         linkTarget: target,
         linkIcon: icon,
         linkIconColor,
         linkActive,
       };
      },
     });
    </script>
    

【问题讨论】:

    标签: vue.js nuxt.js vuejs3


    【解决方案1】:
    1. 为组件实现禁用状态意味着它将处理两个因素:样式(禁用颜色)和功能。显示禁用的颜色只是样式/css 的问题。以编程方式实现它意味着在用户端完全呈现需要更长的时间,并且会失去更多的 SEO 分数。从浏览器检查 UiIcon 的 DOM 并使用 Deep selectors 覆盖样式。

    如果我正在处理这种情况,我会用 css 描述颜色并尽量减少对样式的编程操作。

    <template>
      <div :disabled="disabled">
      </div>
    </template>
    <script>
    export default {
      props: {
        disabled: {
          type: Boolean,
          default: false,
        }
      }
    }
    </script>
    // it does not have to be scss.
    // just use anything that's
    // easier to handle variables.
    <style lang="scss">
    // I would normally import css with prepend option from webpack,
    // but this is just to illustrate the usage.
    @import 'custom-styles.scss';
    
    &::v-deep button[disabled] {
      color: $disabled-color;
    }
    </style>
    
    1. 在道具对象上附加validator函数。 it'll automatically throw errors on exceptions
    {
    props: {
      icon: {
        type: String,
        default: "default-icon",
        validator(val) {
          return val !== "";
          // or something like, 
          // return val.includes(['iconA', 'iconB'])
        },
      },
    }
    }
    

    【讨论】:

    • 我之前确实通过 CSS stroke 属性覆盖了样式,因为图标是 SVG,但我认为在 CSS 和 JS 中使用颜色不是一个好习惯
    • 但我最终只为一个颜色做了很多哈哈
    • 你的意思是['iconA', 'iconB'].includes(value) 对吧?
    • 是的。我是即时编写代码的,对错误深表歉意。
    • js 和 css 中不需要区分颜色。可以只使用一个 .js 文件来声明颜色并通过 emotion 在 css 中使用它。
    猜你喜欢
    • 2021-09-15
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 2022-01-19
    • 2020-06-20
    • 2022-01-06
    • 2013-02-21
    • 2021-09-05
    相关资源
    最近更新 更多