使用 computed和使用 watch来实现类似属性监听效果比较

调色板子组件

代码

<template>
  <div
    class="palette-container"
    @mouseenter="showPalette = true"
    @mouseleave="showPalette = false"
    @touchstart="showPalette = true"
    @touchend="showPalette = false"
  >
    <div class="palette-trigger" :style="{ color: currentColor }">
      <i class="iconfont icon-diaoseban"></i>
    </div>

    <transition name="slide">
      <div v-if="showPalette" class="palette-panel">
        <span
          v-for="color in colors"
          :key="color"
          class="color-dot"
          :style="{ backgroundColor: color }"
          @click="selectColor(color)"
        ></span>
      </div>
    </transition>
  </div>
</template>

<script>
export default {
  name: "ColorPalette",
  props: {
    current_color: {
      type: String,
      required: true,
    }
  },
  data() {
    return {
      showPalette: false,
      colors: [
        "#bddff5",
        "#f8b195",
        "#c5e1a5",
        "#ffccbc",
        "#90caf9",
        "#ffd54f",
        "#ce93d8"
      ]
    };
  },
  computed: {
    currentColor() {
      return this.current_color;
    }
  },
  methods: {
    selectColor(color) {
      this.$emit("select", color);
      this.showPalette = false;
    }
  }
};
</script>

<style scoped>
.palette-container {
  display: inline-block;
}

.palette-trigger {
  cursor: pointer;
}

.palette-panel {
  position: absolute;
  top: 0;
  left: -175px;
  display: flex;
  gap: 8px;
  background: #f2f2f2;
  padding: 10px;
  border-radius: 50px 0px 0px 50px;
  z-index: 10;
}

.color-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
  transition: transform 0.2s ease;
}

.color-dot:hover {
  transform: scale(1.2);
}

.slide-enter-active,
.slide-leave-active {
  transition: all 0.3s ease;
}
.slide-enter,
.slide-leave-to {
  opacity: 0;
  transform: translateX(1px);
}
</style>

父组件使用方式示例:

<ColorPalette @select="handleColorSelect" :current_color="gradientColor"/>

效果示例

使用 computed 的方式

✅ 优点

  • 自动依赖追踪:只要 current_color 发生变化,computed 会自动重新计算。

  • 更简洁:适合用于展示或绑定数据,不需要手动处理更新逻辑。

  • 性能更优:有缓存机制,只有依赖变化时才重新计算。

🚫 限制

  • 只读:不能直接修改 computed 属性(除非使用 get/set)。

  • 不适合副作用:如果你需要在 current_color 变化时执行动画、请求等副作用逻辑,computed 不适合。

示例

computed: {
  currentColor() {
    return this.current_color;
  }
}

用于模板:

<div :style="{ color: currentColor }"></div>

使用 watch 的方式

✅ 优点

  • 适合处理副作用:比如动画、日志记录、异步请求等。

  • 灵活性高:可以访问新值和旧值,做更复杂的逻辑处理。

  • 可以响应深层对象变化:通过 deep: true

🚫 限制

  • 需要手动写逻辑:不像 computed 那样自动绑定。

  • 没有缓存:每次变化都会触发回调。

示例

data() {
  return {
    internalColor: this.current_color
  };
},
watch: {
  current_color(newVal) {
    this.internalColor = newVal;
    // 可以在这里加动画、日志等副作用逻辑
  }
}

用于模板:

<div :style="{ color: internalColor }"></div>

🆚 总结对比表

特性computedwatch
响应式更新✅ 自动✅ 手动处理
用于模板绑定✅ 非常适合✅ 但需要额外变量
副作用处理❌ 不适合✅ 非常适合
性能✅ 有缓存❌ 每次变化都触发
代码简洁性✅ 简洁❌ 逻辑较多
可读性✅ 高✅ 高(但逻辑多时可能变复杂)

什么时候用哪个?

  • 如果你只是想展示或绑定 prop 的值,用 computed 更简单。

  • 如果你需要在 prop 变化时执行额外逻辑(比如动画、请求、状态同步),用 watch 更合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值