2.3.3
我对要测试的行为进行了最小化的复制,该示例只需要JSX即可工作。
从父级传递过来的属性应显示在ctx.injections
。
Ctx.injections
存在,但为空。 这些属性未传递到功能组件上下文。
这是因为child
被认为是vm
子代(可能是一个问题),而不是parent
。 因此,您可能需要在vm
写入provide
vm
。
顺便说一句,你的提琴使用[email protected] 😅
提供注入的查找算法是子级自行查看提供的属性,然后循环其$parent
层次结构以查找提供的道具,直到其位于根目录为止。
https://github.com/vuejs/vue/blob/b182ac40697edbe8253d4bd68b6ac09e93259e1c/src/core/instance/inject.js#L59 -L59
无法运行您的小提琴,但是当我运行https://jsfiddle.net/Austio/vhgztp59/7/时,当我进入查找上下文时,在子组件上未定义$ parent。 如果这与渲染插槽无关紧要,并且组件之间没有关系,那么至少这是一个开始。
似乎在解决插槽之前就渲染了功能组件
@Kingwl正确,这是一种技术要求。
我记得我提出这一点是因为我对此感到疯狂。 最后,对我来说这看起来很正常,因为功能组件已附加到要在其中渲染的组件,因此在插槽中使用时,它们会附加到外部组件。 但是,对于非功能组件则不是这种情况:
容器注入mode: 'foo'
并渲染<div><slot/></div>
<!-- rendered in App -->
<container>
<!-- parent is App, mode is undefined -->
<functional></functional>
</container>
<container>
<!-- parent is container, mode is foo -->
<not-functional></not-functional>
</container>
编辑: @alidcastano我更新了您评论中的小提琴,因为您的评论甚至没有使用Vue 2
哈哈,抱歉在小提琴中使用了错误的Vue版本,我因为无法配置我没有意识到的JSX而深陷其中。 @posva感谢您修复我的示例!
-
因此,这里的问题不是功能组件无法接收所提供的属性,而是功能组件在插槽之前呈现?
@LinusBorg通过“技术要求”是否意味着没有解决方法或该行为是预期的?
是否应该创建一个容器来充当传递道具的vm
? 例如,设计将更改为:
// before
<parent-component>
<child-component />
</parent-component>
// after
<vm-container>
<parent-component>
<child-component />
</parent-component>
<vm-container>
但是上面的示例似乎不必要地already肿,因为父组件的本质已经包含了它需要提供给子组件的所有数据。 但是我愿意讨论。 这是你们的建议吗?
vm-container
不会更改任何内容,因为广告位是在app
上下文中呈现的
“技术要求”是否意味着没有解决方法或该行为是预期的?
该行为是功能组件工作方式的结果。 考虑以下一组组件:
<!-- template of a `parent` component -->
<template>
<Child>
<functional />
</Child>
</template>
当您将功能组件传递到另一个组件的插槽中时,必须先将其呈现,然后再将其传递给子组件,以便该子组件可以接收生成的vNode作为插槽内容。 (*)
在上面的示例中,这意味着在<functional>
组件呈现时,可用的父对象是外部组件( <parent>
),而不是<child>
。
因此,功能部件可用的唯一进样也是<parent>
中可用的进样。
(*):这就是虚拟域的当前实现与功能组件一起工作的方式。 要改变这一点,就需要改变很多内部机制。
@posva @LinusBorg知道了,谢谢您的解释。
因此,由于这些要求,使用提供/注入功能组件的唯一方法是在app
上下文中提供props。
我确定此约束条件将在文档中阐明。 如果没有其他需要完成或澄清的问题,请继续并解决此问题; 再次感谢!
也许我们可以找到一种方法来改善插槽中的功能组件
但是目前,它应该像@posva和@LinusBorg所说的那样完成
@Kingwl感谢您保持打开状态。
我终于有时间尝试使用上述建议将其合并到我的vue-mobiledoc-editor插件中。 我预见到是否需要从app
实例中使用组件的一个问题是,使用嵌套的组件要灵活得多。
例如,我必须导出已在该应用程序实例下注册的组件:
...
export default Vue.extend({
render (h) {
return (
<div>
<ParentComp>
<ChildFuncComp/>
</ParentComp>
</div>
)
},
provide () { // data that needs to be injected into functional components
return {
msg: 'hello'
}
},
components: {
ParentComp,
ChildFuncComp
}
})
然后,据我了解,当用户使用插件时,会像这样:
// template
<div id="app">
<div id="#someWhereInApp" />
</div>
// script
import SuperCoolComponent from 'SuperCoolComponent'
export default {
mounted () {
this.$once('mounted', () => new SuperCoolComponent().$mount('#someWhereInApp'))
this.$emit('mounted')
}
}
如果我的实现是正确的,那么这将严重限制功能组件的提供/注入的使用,因为不允许您单独导入和注册要使用的组件。
我会使用完整的组件来支持提供/注入
我正在尝试解决这个问题
也许这是一个漫长的过程🌚
@Kingwl您能解决吗?
是否有计划在v3中解决此问题?
例如,我试图将v-for抽象化为渲染函数,但是我的孩子可以是功能组件(因此进入渲染函数时它们已经被渲染了,我无法克隆它们)。
任何更新?
最有用的评论
是否有计划在v3中解决此问题?
例如,我试图将v-for抽象化为渲染函数,但是我的孩子可以是功能组件(因此进入渲染函数时它们已经被渲染了,我无法克隆它们)。