Attribute patch in pinia store is working from one component, but not from another (Nuxt.js)

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

Attribute patch in pinia store is working from one component, but not from another (Nuxt.js)

问题

我有这两个使用Nuxt 3的组件。

在组件1中,setActive方法改变了activeColor的状态,但是在组件2中的cancelEdit方法没有改变activeColor的状态。

你知道为什么会出现这种情况吗?

组件1

这里的setActive方法改变了activeColor:

<template>
  <div class="f-button" @click="addColor">+ 添加颜色</div>
  {{ activeColor }}
  <div class="f-colors">
    <Color v-for="color in colors" :color="color" :edit="activeColor === color" @click="setActive(color)"/>
  </div>
</template>

<script>
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
import Color from "~/components/Color.vue";
export default defineComponent({
  name: "ColorManagement",
  components: {Color},
  setup() {
    const projectStore = useProjectStore()
    const { getColors, getActiveColor } = storeToRefs(projectStore);
    return {
      projectStore,
      colors: getColors,
      activeColor: getActiveColor
    };
  },
  methods: {
    addColor() {
      ...
    },
    setActive(color) {
      this.projectStore.$patch({ activeColor: color })
    }
  }
});
</script>

组件2

这里的cancelEdit方法没有改变activeColor:

  <div class="f-color">

    <div class="f-color__actions" v-if="edit">
      <div class="f-color__action" @click="cancelEdit">
        <Cancel /><span>取消</span>
      </div>
    </div>

  </div>

</template>

<script>
import Cancel from "~/components/icons/Cancel.vue";
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
export default defineComponent({
  name: "Color",
  components: {Cancel},
  props: ["color","edit"],
  setup() {
    const projectStore = useProjectStore()
    const { activeColor } = storeToRefs(projectStore);
    return {
      projectStore,
      activeColor
    };
  },
  methods: {
    cancelEdit() {
      this.projectStore.$patch({ activeColor: false })
    }
  }
});
</script> 

nuxt.config.ts

export default defineNuxtConfig({
    vite: {
        css: {
            preprocessorOptions: {
                scss: {
                    additionalData: '@use "@/assets/styles/_styles.scss" as *;'
                }
            }
        }
    },
    modules: ['@pinia/nuxt']
})

Store

import { defineStore } from "pinia";

export const useProjectStore = defineStore({
  id: 'project',
  state: () => {
    return {
      project: {
        colors: [{ color: false, name: '' }]
      },
      activeColor: null
    }
  },
  getters: {
    getColors(state){
      return state.project.colors || [];
    },
    getActiveColor(state){
      return state.activeColor;
    }
  }
});
英文:

I've those two components using Nuxt 3.

The setActive method in component 1 changes the state of activeColor, but the cancelEdit method in component 2 does not.

Any idea why this is the case?

Component 1

Here the setActive method changes activeColor:

<template>
  <div class="f-button" @click="addColor">+ Add Color</div>
  {{ activeColor }}
  <div class="f-colors">
    <Color v-for="color in colors" :color="color" :edit="activeColor === color" @click="setActive(color)"/>
  </div>
</template>

<script>
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
import Color from "~/components/Color.vue";
export default defineComponent({
  name: "ColorManagement",
  components: {Color},
  setup() {
    const projectStore = useProjectStore()
    const { getColors, getActiveColor } = storeToRefs(projectStore);
    return {
      projectStore,
      colors: getColors,
      activeColor: getActiveColor
    };
  },
  methods: {
    addColor() {
      ...
    },
    setActive(color) {
      this.projectStore.$patch({ activeColor: color })
    }
  }
});
</script>

Component 2

Here the cancelEdit method doesn't change activeColor:

  <div class="f-color">

    <div class="f-color__actions" v-if="edit">
      <div class="f-color__action" @click="cancelEdit">
        <Cancel /><span>Cancel</span>
      </div>
    </div>

  </div>

</template>

<script>
import Cancel from "~/components/icons/Cancel.vue";
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
export default defineComponent({
  name: "Color",
  components: {Cancel},
  props: ["color","edit"],
  setup() {
    const projectStore = useProjectStore()
    const { activeColor } = storeToRefs(projectStore);
    return {
      projectStore,
      activeColor
    };
  },
  methods: {
    cancelEdit() {
      this.projectStore.$patch({ activeColor: false })
    }
  }
});
</script> 

nuxt.config.ts

export default defineNuxtConfig({
    vite: {
        css: {
            preprocessorOptions: {
                scss: {
                    additionalData: '@use "@/assets/styles/_styles.scss" as *;'
                }
            }
        }
    },
    modules: ['@pinia/nuxt']
})

Store

import { defineStore } from "pinia";

export const useProjectStore = defineStore({
  id: 'project',
  state: () => {
    return {
      project: {
        colors: [{ color: false, name: '' }]
      },
      activeColor: null
    }
  },
  getters: {
    getColors(state){
      return state.project.colors || [];
    },
    getActiveColor(state){
      return state.activeColor;
    }
  }
});

答案1

得分: 1

好的,如果我理解正确,问题是这样的:

你所谓的 Component 2 是在 Component 1 中使用的 <Color ... 组件,对吗?

当你在 Component 2(也就是 Color)中触发 cancelEdit 时,由于 <Color ...@click="setActive(color)",你也在触发 setActive 的逻辑... 所以你的 activeColor 被设置为 false(来自 cancelEdit 方法),但紧接着又被重新设置为 active,明白吗?

要解决这个问题(如果你不想改变你的 HTML 结构),你可以在 cancelEdit 方法中使用事件的 stopPropagation 方法:

cancelEdit(e) {
  e.stopPropagation()
  this.projectStore.$patch({ activeColor: false })
}

Event.stopPropagation() 参考文档

英文:

Ok, if I got this correctly, the deal is this:

Your so called Component 2 is the <Color ... component being used in Component 1, right?

When you trigger cancelEdit inside Component 2 (aka Color) you are also triggering the logic from setActive due to this <Color ...@click="setActive(color)"...so your activeColor is set to false (from the cancelEdit method) but right after it is set to active again, got it?

To fix this (if you don't want to change your HTML structure) you can use events stopPropagation method inside the cancelEdit:

cancelEdit(e) {
  e.stopPropagation()
  this.projectStore.$patch({ activeColor: false })
}

Event.stopPropagation() reference

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

发表评论

匿名网友

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

确定