vue.js - 有没有其他方法可以将数据从子组件传递到嵌套父组件(向上 6 层),而不使用 vuejs 中的发出和存储?

标签 vue.js components vue-component vuex

我需要将数据从子组件传递到父(嵌套)组件,我知道我们可以使用 emitstore 来做到这一点,但我想知道,还有其他吗方式,以更好的方式做到这一点?

我不想仅仅因为我的父组件向上 6 级而使用 emit

最佳答案

商店不一定需要 vuexpinia 。它可以是外部 reactive() ,导入到所有使用它的组件中,无论它们之间的关系如何。

将其视为 data: () => ({})对象,但没有组件。下面是一个示例,其中我创建了一个简单的响应式(Reactive)“store”,并将其注入(inject)到 App 和 Child 中(6 层深)。

const { createApp, reactive, defineComponent } = Vue;

const store = reactive({
  foo: 'bar'
})
const app = createApp({
  setup: () => ({ store })
});

app.component('parent', defineComponent({
  template: '<div class="parent">Parent<br><slot></slot></div>'
}));
app.component('child', defineComponent({
  setup: () => ({ store }),
  template: '<input v-model="store.foo">'
}));

app.mount('#app')
.parent .parent {
  padding-left: 1rem;
}
input {
  margin-left: 1rem;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="app">
  <parent>
    <parent>
      <parent>
        <parent>
          <parent>
            <child />
          </parent>
        </parent>
      </parent>
    </parent>
  </parent>
  <pre v-text="store" />
</div>

同样的事情,在 Vue2 中:

const store = Vue.observable({
  foo: 'bar'
})

Vue.component('parent', {
  template: '<div class="parent">Parent<br><slot /></div>'
});
Vue.component('child', {
  computed: {
    store: () => store
  },
  template: '<input v-model="store.foo">'
});

new Vue({
  computed: {
    store: () => store
  }
}).$mount('#app')
.parent .parent {
  padding-left: 1rem;
}
input {
  margin-left: 1rem;
}
<script src="https://cdn.jsdelivr.net/npm/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6e181b0b2e5c4058405f5a" rel="noreferrer noopener nofollow">[email protected]</a>"></script>
<div id="app">
  <parent>
    <parent>
      <parent>
        <parent>
          <parent>
            <child />
          </parent>
        </parent>
      </parent>
    </parent>
  </parent>
  <pre v-text="store" />
</div>

在真实的应用程序中,您将在文件中定义“store”并导入到使用它的任何组件中。 (例如:

import { reactive } from 'vue'
export const myStore = reactive({
  //...stuff
})

anywhere else: 
import { myStore } from './path/to/store'

注意:如果您使用的是 Vue2,则可以导入 reactive来自@vue/composition-api插件或者您可以使用 Vue.observable()反而。它提供相同的功能。

即使上述方法有效,您使用它的次数越多,您实际上从使用 pinia 中受益就越多或vuex ,因为它们具有与 vue devtools 集成的巨大好处。让您能够检查、回滚或重放 react 状态的更改。更不用说您还可以在商店上定义操作,因此您不必将它们分散在多个组件中,当您想要从两个或多个不同的组件执行相同的操作时特别有用。


另一个选择是使用 provide/inject专为绕过父/子链而开发。当您想要专门为当前组件的后代而不是其同级组件的后代提供时,它非常有用。例如:

item-1
  component
    component
      child-1
item-2
  component
    component
      child-2
      child-3

在上面的例子中,如果你想要child-2child-3继承/更新item-2但不影响item-1 ,那么您将使用 provideitem-2injectchild-2child-3 .

我个人没有使用过注入(inject)/提供,因为我发现与外部商店合作非常强大。即使从理论上讲,我遇到了上述情况。我只使用一家商店,在那里我可以唯一地识别祖先。孙辈使用该标识符来更新商店中适当的祖先。

事实上,我唯一使用emit的地方位于不可知组件中,它可以有任何父组件,接受一些输入,执行一些操作,然后更新其父组件(例如:上下文)。一个很好的例子是通用表单组件,它不必了解有关父表单的任何信息。
另一个这样的例子是 agonstic 列表渲染器,它同样不关心它们列出的内容。它们将点击操作“发出”到父组件,父组件知道该点击的实际含义。

关于vue.js - 有没有其他方法可以将数据从子组件传递到嵌套父组件(向上 6 层),而不使用 vuejs 中的发出和存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71472149/

相关文章:

vue.js - Ajax 调用后绑定(bind)样式

Angular Cli-在 StyleURL 中添加位于 node_module 目录中的 css 文件

javascript - 函数参数可以使用数组方法吗?

components - 使用原始 html 创建 vue 组件

vuejs2 - 使用 bootstrap-vue 对 b-table 中的 b-input 进行 Vue 数据绑定(bind)

javascript - 如何在事件总线上存储 'global var'

javascript - 来自 vuex 的 @click 在 vue 组件上不起作用

javascript - Vue 和重复的 Prop

vue.js - vuetify 带有子菜单的下拉菜单在选择时不会关闭

properties - 没有值(value)的 Vue 组件 Prop