[英]Correct way to pass props to all children through slot-scope in Vue.js
根据有关slot-scope的注释更新了代码
来自React,我很难理解Vue如何使用slot和slot-scope将prop传递给子组件。
在我当前的项目中,我有一个DataSlicer组件,该组件可以接收data
道具并对其执行一些操作。 然后,我想通过<slot>
将操纵后的数据传递给子组件。 component tells a child to pass something to its own children -- which seems to defeat the whole point (in terms of composition and separation of concerns). 我知道slot-scope
是实现此目的的方法,但它似乎仅在组件告诉孩子将某些东西传递给自己的孩子时才起作用-似乎在整个问题上(在关注点的构成和分离方面) )。
这是我现在正在工作的内容,基于阅读如何使用父级到子级-vuejs的插槽传递道具
App.vue
<DataSlicer
v-if="data"
y-axis-dimension="Subparameter"
x-axis-dimension="Year"
value-dimension="Total_Registrations"
:filters="{}"
:data="data"
>
<template slot-scope="childProps">
<Chart :title="title" :series-data="childProps.slicedData" />
</template>
</DataSlicer>
DataSlicer.vue
<template>
<div>
<slot :slicedData="slicedData"/>
</div>
</template>
我的期望是我可以在DataSlicer.vue的<template>
标记上定义slot-scope
,但这似乎不起作用。
我想念什么吗? 我不明白为什么App.vue需要知道或关心DataSlicer传递给其子级的内容。 我将组件拆分得越多,问题就越复杂(例如,如果我将DataSlicer粘贴在另一个组件中以抽象api调用,这些调用目前在App.vue级别处理,那么App.vue还必须告诉组件将数据传递到其DataSlicer子级。
也许我只是在这里停留在React思想上,并且有另一种或更好的方式来做到这一点?
编辑:
如果有帮助,我可以使用以下渲染函数来完成我想要的工作:
render: function (createElement) {
return createElement(
'div',
this.$slots.default.map(vNode => {
if (vNode.componentOptions) {
vNode.componentOptions.propsData.slicedData = this.slicedData;
}
return vNode;
})
)
}
这感觉有点骇人听闻/脆弱,也好像我正在扩展Vue,以在可能有更好的方法时以“反应方式”做某事。
编辑2:
经过更多的研究和实验,我也尝试了提供/注入方法。 这是可行的(通过使用defineObjectProperty为要传递的属性绑定动态获取器),但是这意味着必须显式编写子组件以接受提供的道具,而不仅仅是接受该道具(无论它是由父组件提供还是直接提供)。
我也尝试过使用动态组件和v-for( <component>
),但是由于我实际上将$ slots.default中收到的已经定义好的组件重新初始化为动态组件,所以它最终变得一团糟。当我希望这些组件也有子组件时,会引入一些递归怪异,并且很难处理非组件子组件。
这是React中非常常见的模式,实现起来很简单,所以我仍然很好奇是否还有另一种方式可以实现这一点,而这种方式更符合Vue的工作方式。
我正在尝试构建可重用,自包含和可组合的组件,因此每次在父组件中一起使用时必须在<template>
标记中指定slot-scope对我的目的而言并没有任何意义。 我的孩子组成部分不应该关心他们的道具来自哪里,我的孩子组成部分也不应该关心他们的孩子正在向自己的孩子传递什么道具。
我终于能够使用Vue 2.6中的新v-slot
作用域来实现我想要的功能,描述如下: https : //github.com/vuejs/vue/issues/9306
我的问题的一部分是Vue团队将我要使用的“状态提供程序”方法视为反模式,因为尚不清楚道具来自何处。 我明白了他们的观点,并且我认为新语法在清晰和避免包装子组件的<template>
标签过多样板之间取得了良好的平衡。 它还简化了组件并使其具有了能力,使之既可以使用提供的道具也可以使用“常规”道具,而不必关心它们的来源(我的提供/注入问题)。
最终结果如下所示:
App.vue
<DataGetter {...other props} v-slot="{ data }">
<DataSlicer {...other props} :data="data" v-slot="{ slicedData }">
<!-- Using provided data prop -->
<Chart :data="slicedData" />
<!-- Data prop explicitly defined -->
<Chart :data="[ 1, 2, 3 ]" />
</DataSlicer>
</DataGetter>
DataGetter
和DataSlicer
呈现函数:
render(h) {
if (this.$scopedSlots.default) {
return h(
'div',
this.$scopedSlots.default({ data: this.data })
)
}
}
我希望这对来自React的其他人有帮助。 如果有人提出更好的答案,我将保留这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.