Vue:在子组件之间共享 vue 元素

问题描述 投票:0回答:1

小提琴:https://codesandbox.io/s/frosty-sound-xxn73s?file=/src/App.vue

我有两个

Vue
组件使用相同的
HappyDog.vue
组件:
HumanJoe.vue
AlienBob.vue
。当其内部状态(苹果的数量)发生变化(随机增加或减少)时,
HappyDog.vue
会发出事件。在更大的项目中,使用
HappyDog
的组件可以通过将反应数据作为 props 传递来改变其内部状态。

我希望能够在其他几个组件中使用相同的

HappyDog
组件,以便所有使用
HappyDog
的组件引用相同的组件,并具有相同数量的苹果。

App.vue

<template>
  <HumanJoe />

  <AlienBob />
</template>

<script>
import HumanJoe from "./components/HumanJoe.vue";
import AlienBob from "./components/AlienBob.vue";

export default {
  name: "App",
  components: {
    HumanJoe: HumanJoe,
    AlienBob: AlienBob,
  },
};
</script>

<style>
</style>

HappyDog.vue

<template>
  <div class="dog">
    <b>Dog with {{ this.apples }} apples</b>

    <div class="dog-apples">
      <div class="apple" v-for="a in this.apples" :key="a"></div>
    </div>
  </div>
</template>

<script>
export default {
  props: {},

  data() {
    return {
      apples: 100,
    };
  },

  created() {
    this.interval = setInterval(() => this.changeApples(), 3000);
  },

  methods: {
    changeApples() {
      let add = 1 === Math.floor(Math.random() * 2) + 1; // [1, 2]

      let random = 0;
      if (add) {
        random = Math.floor(Math.random() * 100) + 1; // [1, 100]

        this.apples += random;

        this.$emit("gain", this.apples);
      } else {
        random = Math.floor(Math.random() * 50) + 1; // [1, 50]

        this.apples -= random;

        if (this.apples < 0) {
          this.apples = 0;

          this.$emit("loss", this.apples);
        }
      }
    },
  },
};
</script>

<style scoped>
.dog {
  width: 200px;
  height: 200px;

  background-color: orange;
  font-weight: bold;
  font-size: 200%;

  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;

  overflow: scroll;
}

.dog-apples {
  display: flex;
  flex-wrap: wrap;

  width: 100%;
  height: 100%;

  margin: 5px;
}

.apple {
  background-color: red;
  border-radius: 50%;

  width: 20px;
  height: 20px;

  margin: 5px;
}
</style>

以及使用

HappyDog.vue
的组件 - 为简单起见,它们几乎完全相同,但在更大的项目中,它们可以有自己的规则来决定如何对
HappyDog
发出的事件做出反应,以及可能的更改
HappyDog
的状态:

HumanJoe.vue

<template>
  <div class="joe">
    <b> Joe </b>
    <HappyDog />
  </div>
</template>


<script>
import HappyDog from "./HappyDog.vue";

export default {
  name: "App",
  components: {
    HappyDog: HappyDog,
  },
};
</script>


<style scoped>
.joe {
  background-color: cyan;

  display: flex;
  flex-direction: column;

  margin: 2em;
  padding: 2em;
}

.joe b {
  font-size: 200%;
}
</style>

AlienBob.vue

<template>
  <div class="bob">
    <b> Bob </b>
    <HappyDog />
  </div>
</template>


<script>
import HappyDog from "./HappyDog.vue";

export default {
  name: "App",
  components: {
    HappyDog: HappyDog,
  },
};
</script>


<style scoped>
.bob {
  background-color: lime;

  display: flex;
  flex-direction: column;

  margin: 2em;
  padding: 2em;
}

.bob b {
  font-size: 200%;
}
</style>

我意识到,在这个简单的示例中,我可以通过传递一个将在

HappyDog
内部更新的反应式道具,在
HumanJoe
AlienBob
中制作不同的
App.vue
组件,并拥有相同数量的苹果,或者使用发出的事件来更新
apples
中的
App.vue
数据,该数据将作为道具传递给
HumanJoe
AlienBob
,但是,我真的希望它们都能够使用相同的
HappyDog
组件,如果这完全有可能。

我已经搜索过它,并找到了插槽和

is
,但我不确定这就是我要找的,因为我找不到共享相同组件的示例,而不是动态传递名称要创建的组件。

javascript vue.js vuejs3 vue-component
1个回答
0
投票

当您的 Vue 应用程序正在转换最终在具有 props 的组件之间产生严重耦合的内容时(如您的情况),最好使用状态管理。

状态管理有一个全局“存储”,您可以在其中定义状态(或多个状态)和操作。通过这种管理模型,您可以保存可在多个组件之间共享的“全局”数据。 在这里阅读更多相关信息

一个例子是存储用户会话信息(即用户名、电子邮件等),或者在您的情况下,存储可以访问(查看)和更改(操作)的苹果数据(状态)。

Vuex 通常是首选,但它已经过渡到 Pinia - 所以我建议使用它。

© www.soinside.com 2019 - 2024. All rights reserved.