英文:
Emit event dont work and active icon on current button vue3
问题
我尝试使用Vue 3和Tailwind来实现主题切换器。我面临的问题与事件发射(emit)有关,我不知道如何显示当前选定的按钮。首先,事件发射的问题是我认为我已经正确设置了,可以参考上面的代码。第二个问题是,当我点击当前颜色主题时,如何在当前按钮上激活一个图标。如果我将代码放在组件外部,那么它可以正常工作。
主题切换器:
<template>
<div class="flex space-x-1 bg-white rounded-full px-2 py-1">
<button
class="rounded-full"
v-for="(themeColor, index) in themeColors"
:key="`theme-changer-${index}`"
:class="[index ? 'p-3' : 'p-1']"
:style="{ backgroundColor: colors[themeColor][500] }"
@click="$emit('color', colors[themeColor])"
>
<svg v-if="!index" class="text-white w-4 h-4" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M19.916 4.626a.75.75 0 01.208 1.04l-9 13.5a.75.75 0 01-1.154.114l-6-6a.75.75 0 011.06-1.06l5.353 5.353 8.493-12.739a.75.75 0 011.04-.208z" clip-rule="evenodd" />
</svg>
</button>
</div>
</template>
<script setup>
import colors from 'tailwindcss/colors'
defineProps({
themeColors: Array
})
defineEmits(['color'])
</script>
代码插入:
<template>
<ThemeChanger :theme-colors="themeColors" @colors="c => color = c" />
</template>
<script setup>
import { ref } from 'vue'
import ThemeChanger from '@/components/ThemeChanger.vue'
import colors from 'tailwindcss/colors'
const themeColors = [
'indigo',
'emerald',
'blue',
'yellow',
'orange',
'red',
]
const color = ref(colors[themeColors[0]])
</script>
英文:
I try to achieve a theme changer with vue3 and tailwind. The problem I face is with the emit event and I don't know how to show the selected current button. First the emit event problem is I setup "correctly" way, I think, see on code above. The second is I try when click the current color theme then an icon is active on the current button. If I set the code out side without be a component then works fine.
theme changer:
<template>
<div class="flex space-x-1 bg-white rounded-full px-2 py-1">
<button
class="rounded-full"
v-for="(themeColor, index) in themeColors"
:key="`theme-changer-${index}`"
:class="[index ? 'p-3' : 'p-1']"
:style="{ backgroundColor: colors[themeColor][500] }"
@click="$emit('color', colors[themeColor])"
>
<svg v-if="!index" class="text-white w-4 h-4" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M19.916 4.626a.75.75 0 01.208 1.04l-9 13.5a.75.75 0 01-1.154.114l-6-6a.75.75 0 011.06-1.06l5.353 5.353 8.493-12.739a.75.75 0 011.04-.208z" clip-rule="evenodd" />
</svg>
</button>
</div>
</template>
<script setup>
import colors from 'tailwindcss/colors'
defineProps({
themeColors: Array
})
defineEmits(['color'])
</script>
code implantation:
<template>
<ThemeChanger :theme-colors="themeColors" @colors="c => color = c" />
</template>
<script setup>
import { ref } from 'vue'
import ThemeChanger from '@/components/ThemeChanger.vue'
import colors from 'tailwindcss/colors'
const themeColors = [
'indigo',
'emerald',
'blue',
'yellow',
'orange',
'red',
]
const color = ref(colors[themeColors[0]])
</script>
答案1
得分: 1
你正在发出一个名为color
的事件,其绑定为@click="$emit('color', colors[themeColor])"
,
但你在监听一个名为colors
的事件,其绑定为<ThemeChanger :theme-colors="themeColors" @colors="c => color = c" />
。
我认为改变这两个事件的名称使它们匹配将足以使你的代码正常工作。
至于更改当前主题时的复选标记,有多种方法可以实现。我认为最好的方式(简单但可扩展)是在ThemeChanger
上添加另一个名为currentThemeColor
的prop。
然后,在你的v-for
循环中,你可以这样做:
<button
class="rounded-full"
v-for="(themeColor, index) in themeColors"
:key="`theme-changer-${index}`"
:class="[index ? 'p-3' : 'p-1']"
:style="{ backgroundColor: colors[themeColor][500] }"
@click="$emit('color', colors[themeColor])"
>
<svg v-if="currentThemeColor === themeColor" ... >
</div>
这样,每当prop发生变化时,你的ThemeChanger
会重新渲染并作出相应反应。使用ref
也是另一种方法,但我认为以后,你可能会希望将主题逻辑最终从父组件移出并移到某种全局提供程序中,使用props也可以在这种设置下工作,而且只需进行最少的更改。
英文:
You are emitting an event called color
at @click="$emit('color', colors[themeColor])"
,
but you are listening to an event called colors
at <ThemeChanger :theme-colors="themeColors" @colors="c => color = c" />
I think changing the event names so that these two match would be sufficient to get your code working.
In regards to getting the check mark change with the current theme, there are multiple ways you could go about it. I think the best way (easy, but scalabole) to do this would be to have another prop called something like currentThemeColor
on your ThemeChanger
.
Then, in your v-for
loop, you could do something like:
<button
class="rounded-full"
v-for="(themeColor, index) in themeColors"
:key="`theme-changer-${index}`"
:class="[index ? 'p-3' : 'p-1']"
:style="{ backgroundColor: colors[themeColor][500] }"
@click="$emit('color', colors[themeColor])"
>
<svg v-if="currentThemeColor === themeColor" ... >
</div>
This way, your ThemeChanger
would be re-rendered every time the prop changes and react accordingly. Using ref
s would be another way, but I think later on, you will want to eventually move the theme logic out of the parent component and move it to some kind of global provider, and using props would work with that kind of setup as well with minimal changes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论