2.3.3
Criei uma reprodução mínima do comportamento que estou tentando testar, o exemplo só precisa do JSX para funcionar.
As propriedades transmitidas pelo pai devem aparecer em ctx.injections
.
Ctx.injections
existe, mas permanece vazio. As propriedades não estão sendo transmitidas ao contexto do componente funcional.
É porque em vez de parent
, child
é considerado filho de vm
(talvez um problema). Portanto, pode ser necessário escrever provide
em vm
.
BTW, seu violino está usando [email protected] 😅
O algoritmo de pesquisa para fornecer injetar é que a criança olha para si mesma em busca de atributos fornecidos e, em seguida, faz um loop em sua hierarquia $parent
em busca de adereços fornecidos até que esteja na raiz.
https://github.com/vuejs/vue/blob/b182ac40697edbe8253d4bd68b6ac09e93259e1c/src/core/instance/inject.js#L59 -L59
Não foi possível fazer o seu violino funcionar, mas quando eu executei https://jsfiddle.net/Austio/vhgztp59/7/ este violino o $ parent estava indefinido no componente filho quando cheguei ao contexto de pesquisa. Pelo menos isso é um começo, se não for um problema de renderização em slots e de não haver uma relação entre os componentes.
parece que o componente funcional é renderizado antes que os slots sejam resolvidos
@Kingwl correto, e isso é um tipo de requisito técnico.
Lembro que levantei a questão porque estava ficando louco com isso. No final, parecia normal para mim porque os componentes funcionais são anexados ao componente em que são renderizados e, portanto, quando usados em um slot, eles são anexados ao componente externo. No entanto, este não é o caso com componentes não funcionais:
O contêiner injeta mode: 'foo'
e renderiza <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>
editar: @alidcastano Eu atualizei o violino em seu comentário, pois o seu nem estava usando o Vue 2
Haha, desculpe por usar a versão errada do Vue no violino, eu estava muito preocupado em não conseguir configurar o JSX que não percebi. @posva Obrigado por corrigir meu exemplo!
-
Portanto, o problema aqui não é que o componente funcional não pode receber as propriedades fornecidas, mas que o componente funcional é renderizado antes do slot?
@LinusBorg Por "requisito técnico", isso significa que não há solução alternativa ou que o comportamento é intencional?
Deve um contêiner ser criado para servir como vm
que passa pelos adereços? Por exemplo, o design mudaria para este:
// before
<parent-component>
<child-component />
</parent-component>
// after
<vm-container>
<parent-component>
<child-component />
</parent-component>
<vm-container>
Mas o exemplo acima parece desnecessariamente inchado, uma vez que a essência do componente pai já envolvia todos os dados necessários para fornecer ao filho. Mas estou aberto a discussões; é isso que vocês sugerem?
o vm-container
não mudará nada porque o slot é renderizado no contexto app
Por "requisito técnico", isso significa que não há solução alternativa ou que o comportamento é intencional?
O comportamento é resultado da maneira como os componentes funcionais funcionam. Considere este conjunto de componentes:
<!-- template of a `parent` component -->
<template>
<Child>
<functional />
</Child>
</template>
Quando você passa um componente funcional para o slot de outro componente, ele deve ser renderizado antes de ser passado para o filho, para que esse componente filho possa receber os vNodes resultantes como o conteúdo do slot. (*)
No contexto do meu exemplo acima, isso significa que no momento em que o componente <functional>
é renderizado, o pai disponível é o componente externo ( <parent>
), não o <child>
.
Consequentemente, as únicas injeções disponíveis para o componente funcional são aquelas disponíveis em <parent>
também.
(*): É assim que a implementação atual do virtualdom funciona com componentes funcionais. Para mudar isso, seria necessário mudar bastante a mecânica interna.
@posva @LinusBorg Entendi, obrigado por explicar.
Portanto, devido a esses requisitos, a única maneira de usar fornecer / injetar componentes funcionais é ter os adereços fornecidos no contexto app
.
Tenho certeza de que essa restrição será esclarecida na documentação. Prossiga e feche este problema se não houver mais nada que precise ser feito ou esclarecido; obrigado novamente!
Talvez possamos encontrar uma maneira de melhorar o componente funcional no slot
Mas no momento, deve ser feito como @posva e @LinusBorg disseram
@Kingwl Obrigado por manter isto aberto.
Finalmente tive algum tempo para tentar incorporar isso em meu plug- in app
é que é mais difícil permitir flexibilidade com os componentes aninhados usados.
Por exemplo, tenho que exportar os componentes já registrados na instância do aplicativo:
...
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
}
})
Então, pelo meu entendimento, quando o usuário está usando o plugin, seria assim:
// 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')
}
}
Se minha implementação estiver correta, isso limita severamente o uso de fornecer / injetar componentes funcionais, uma vez que você não tem permissão para importar e registrar individualmente os componentes que deseja usar.
Eu usaria componentes completos em vez de oferecer suporte ao fornecimento / injeção
estou tentando resolver isso
talvez seja um longo processo🌚
@Kingwl Você conseguiu resolver isso?
Existem planos para resolver esse problema na v3?
Por exemplo, estou tentando abstrair um v-for em uma função de renderização, mas meus filhos podem ser componentes funcionais (portanto, eles já são renderizados ao entrar na função de renderização e não posso cloná-los).
Qualquer atualização?
Comentários muito úteis
Existem planos para resolver esse problema na v3?
Por exemplo, estou tentando abstrair um v-for em uma função de renderização, mas meus filhos podem ser componentes funcionais (portanto, eles já são renderizados ao entrar na função de renderização e não posso cloná-los).