vue 收藏按钮实现
实现 Vue 收藏按钮
基础实现
创建一个简单的收藏按钮组件,使用 v-model 或 v-bind 绑定状态:
<template>
<button @click="toggleFavorite" :class="{ 'active': isFavorited }">
{{ isFavorited ? '已收藏' : '收藏' }}
</button>
</template>
<script>
export default {
props: {
value: Boolean // 或使用 modelValue (Vue 3)
},
computed: {
isFavorited() {
return this.value;
}
},
methods: {
toggleFavorite() {
this.$emit('input', !this.isFavorited); // Vue 2
// this.$emit('update:modelValue', !this.isFavorited); // Vue 3
}
}
};
</script>
<style scoped>
.active {
color: gold;
}
</style>
使用图标库
集成 Font Awesome 或 Ionicons 等图标库增强视觉效果:

<template>
<button @click="toggleFavorite">
<i :class="['fas', isFavorited ? 'fa-star' : 'fa-star-o']"></i>
</button>
</template>
持久化存储
结合 Vuex 或 Pinia 管理全局收藏状态:

// Pinia 示例
import { defineStore } from 'pinia';
export const useFavoritesStore = defineStore('favorites', {
state: () => ({
items: []
}),
actions: {
toggle(itemId) {
const index = this.items.indexOf(itemId);
index === -1 ? this.items.push(itemId) : this.items.splice(index, 1);
}
}
});
服务器交互
添加 API 调用实现远程收藏功能:
methods: {
async toggleFavorite() {
try {
const action = this.isFavorited ? 'remove' : 'add';
await axios.post(`/api/favorites/${this.itemId}`, { action });
this.$emit('update', !this.isFavorited);
} catch (error) {
console.error('操作失败:', error);
}
}
}
动画效果
通过 Vue Transition 或 CSS 动画增强交互体验:
<transition name="bounce">
<i v-if="isFavorited" class="fas fa-star"></i>
</transition>
<style>
.bounce-enter-active {
animation: bounce-in 0.5s;
}
@keyframes bounce-in {
0% { transform: scale(0); }
50% { transform: scale(1.5); }
100% { transform: scale(1); }
}
</style>
完整组件示例
<template>
<button
@click="handleClick"
:disabled="loading"
class="favorite-btn"
:class="{ 'active': isFavorited }"
>
<transition name="fade">
<i
v-if="!loading"
:class="['icon', isFavorited ? 'fas fa-heart' : 'far fa-heart']"
></i>
</transition>
<span v-if="showLabel">{{ isFavorited ? '已收藏' : '收藏' }}</span>
</button>
</template>
<script>
export default {
props: {
itemId: [String, Number],
initialStatus: Boolean,
showLabel: { type: Boolean, default: true }
},
data() {
return {
isFavorited: this.initialStatus,
loading: false
};
},
methods: {
async handleClick() {
this.loading = true;
try {
await this.toggleFavorite();
this.isFavorited = !this.isFavorited;
} finally {
this.loading = false;
}
},
toggleFavorite() {
return api.post('/favorites', {
item_id: this.itemId,
action: this.isFavorited ? 'remove' : 'add'
});
}
}
};
</script>






