调色板子组件
代码
<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>
🆚 总结对比表
特性 | computed | watch |
---|---|---|
响应式更新 | ✅ 自动 | ✅ 手动处理 |
用于模板绑定 | ✅ 非常适合 | ✅ 但需要额外变量 |
副作用处理 | ❌ 不适合 | ✅ 非常适合 |
性能 | ✅ 有缓存 | ❌ 每次变化都触发 |
代码简洁性 | ✅ 简洁 | ❌ 逻辑较多 |
可读性 | ✅ 高 | ✅ 高(但逻辑多时可能变复杂) |
什么时候用哪个?
-
如果你只是想展示或绑定 prop 的值,用
computed
更简单。 -
如果你需要在 prop 变化时执行额外逻辑(比如动画、请求、状态同步),用
watch
更合适。