发出事件不起作用并激活当前按钮上的图标 Vue3

huangapple go评论70阅读模式
英文:

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=&quot;$emit(&#39;color&#39;, colors[themeColor])&quot;,

but you are listening to an event called colors at &lt;ThemeChanger :theme-colors=&quot;themeColors&quot; @colors=&quot;c =&gt; color = c&quot; /&gt;

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:

&lt;button
  class=&quot;rounded-full&quot;
  v-for=&quot;(themeColor, index) in themeColors&quot;
  :key=&quot;`theme-changer-${index}`&quot;
  :class=&quot;[index ? &#39;p-3&#39; : &#39;p-1&#39;]&quot;
  :style=&quot;{ backgroundColor: colors[themeColor][500] }&quot;
  @click=&quot;$emit(&#39;color&#39;, colors[themeColor])&quot;
&gt;
&lt;svg v-if=&quot;currentThemeColor === themeColor&quot; ... &gt;
&lt;/div&gt;

This way, your ThemeChanger would be re-rendered every time the prop changes and react accordingly. Using refs 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.

huangapple
  • 本文由 发表于 2023年2月27日 10:00:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75576228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定