【问题标题】:Vue dynamic styles binding is not fluid with computed propertiesVue 动态样式绑定不具有计算属性
【发布时间】:2021-08-20 11:39:27
【问题描述】:

我有一个 NuxtJS 应用程序,我想在其中创建一个自定义 <Radio> 组件。

我动态绑定了一个 CSS 类,因此我可以在选中单选按钮后更改其 font-weight

初始加载后第一次点击按钮,可以看到文字大小略有变化,有一种“缩小/扩大”的效果,但之后不再出现,过渡更加流畅然后。 这可能是由于计算属性的工作方式造成的吗?

I made a video of it to make it clearer.

Inspiration drawn from Stephanie Eckles

<template>
  <div :class="containerClasses">
    <label :class="radioClasses">
      <span class="radio__wrapper">
        <input
          :id="radioId"
          class="radio__input"
          type="radio"
          :checked="shouldBeChecked"
          :value="radioValue"
          @change="updateRadio"
        />
        <span class="radio__control"></span>
      </span>
      <span :for="radioId" class="radio__label">{{ radioLabel }}</span>
    </label>
  </div>
</template>

<script lang="ts">
import { defineComponent, toRefs, computed } from '@nuxtjs/composition-api';

export default defineComponent({
  name: 'Radio',
  model: {
    prop: 'modelValue',
    event: 'change',
  },
  props: {
    id: {
      type: String,
      required: true,
    },
    label: {
      type: String,
      required: true,
    },
    value: {
      type: String,
      default: undefined,
    },
    modelValue: {
      type: String,
      default: '',
    },
  },
  setup(props, { emit }) {
    const { label, id, value, modelValue } = toRefs(props);

    const updateRadio = () => {
      emit('change', value.value);
    };

    const shouldBeChecked = computed(() => modelValue.value === value.value);

    const containerClasses = computed(() => ({
      container: true,
      'container--active': shouldBeChecked.value,
    }));

    const radioClasses = computed(() => ({
      radio: true,
      'radio--active': shouldBeChecked.value,
    }));

    return {
      radioLabel: label,
      radioId: id,
      radioValue: value,
      shouldBeChecked,
      updateRadio,
      containerClasses,
      radioClasses,
    };
  },
});
</script>

<style lang="scss" scoped>
.container {
  --border-width: 1px;

  position: relative;
  border: solid var(--border-width) transparent;
  border-radius: 16px;
  background: $color-white;
  background-clip: padding-box;
  cursor: pointer;

  &::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: calc(var(--border-width) * -1);
    border-radius: inherit;
    background: $color-dark-grey;
  }

  &--active {
    &::before {
      background: $gradient-blue-purple;
    }
  }
}

.radio {
  display: grid;
  grid-gap: 1.6rem;
  grid-template-columns: min-content auto;
  padding: 2rem $spacing-s;
  font-size: $font-size-s;

  &__wrapper {
    display: flex;
  }

  &--active {
    font-weight: $font-weight-medium;
  }

  &__input {
    width: 0;
    height: 0;
    opacity: 0;

    + .radio__control::before {
      content: '';
      width: 1rem;
      height: 1rem;
      transform: scale(0);
      transition: 180ms transform ease-in-out;
      border-radius: 50%;
      box-shadow: inset 0.5em 0.5em currentColor;
    }

    &:checked + .radio__control::before {
      transform: scale(1);
    }
  }

  &__control {
    display: grid;
    width: 2.4rem;
    height: 2.4rem;
    transform: translateY(-0.1em);
    border: 1px solid currentColor;
    place-items: center;
    border-radius: 50%;
  }

  &__label {
    display: flex;
    align-items: center;
    line-height: 1;
  }
}
</style>

【问题讨论】:

    标签: css vue.js nuxt.js vue-composition-api


    【解决方案1】:

    This 将我引导到正确的方向以及此样式调整以使其看起来正确。

    // Before
    .radio {
      display: grid;
      grid-gap: 1.6rem;
    }
    
    // After
    .radio {
      display: flex;
      gap: 1.6rem;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 2018-02-12
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      相关资源
      最近更新 更多