No Angular, um componente é uma diretiva especial, e sua característica especial é que ele possui seu próprio template (html) e estilo (css). Portanto, usar componentes pode tornar nosso código altamente desacoplado, reutilizável e facilmente extensível. Os componentes usuais são definidos da seguinte forma:
demo.component.ts:
demo.component.html:
demo.component.scss:
Quando referenciamos o componente, o conteúdo analisado do componente é renderizado:
Suponha que haja necessidade de o componente aceitar conteúdo projetado externamente, o que significa que o componente acaba apresentando mais do que apenas o que define. Neste momento, o protagonista deste artigo é convidadong-conteúdo。
Projeção simples
Vamos começar pelo mais simples, adicione o demo.component.html modificado e o demo.component.scss ao demo.component.html, da seguinte forma:
demo.component.html:
demo.component.scss:
Para efeitos especiais, a cor de fundo do recipiente é deliberadamente definida como laranja.
Neste ponto, podemos transmitir conteúdo de fora ao referenciar o componente, e o conteúdo externo será exibido na área laranja:
Projeção direcionada
Se houver vários ao mesmo tempo, como o conteúdo externo será projetado?
Vamos dar uma olhada em um exemplo primeiro: para efeitos de distinção, adicionei uma área azul, o demo.component.html modificado e demo.component.scss da seguinte forma:
demo.component.html:
demo.component.scss:
Para referenciar o componente:
Neste ponto, veremos que o conteúdo externo é projetado para a área azul:
Claro, se você colocar o código de área laranja após o código azul, então o conteúdo externo será projetado para a área laranja:
Então, pelo exemplo acima, podemos ver que se também houver um simples , então o conteúdo externo será projetado no último do template de componente.
Então, conhecendo esse problema, podemos nos perguntar: será que podemos projetar conteúdo externo de forma direcionada? A resposta obviamente é sim.
Para lidar com isso, apoie umselecionarAtributos que permitem projetar conteúdo específico em um lugar específico. Essa propriedade suporta seletores CSS (seletor de tags, seletor de classe, seletor de atributos、... ) para combinar com o que você quer. Se nenhum atributo select for definido no ng-content, ele receberá o conteúdo completo, ou o conteúdo que não corresponde a nenhum outro elemento ng-content.
Olhando diretamente para o exemplo, o demo.component.html modificado e o demo.component.scss são os seguintes:
demo.component.html:
demo.component.scss:
Como você pode ver no código acima, a área azul receberá a parte do cabeçalho da tag, a área vermelha receberá a parte do div com a classe "demo2", a área verde receberá a parte do div com o nome da propriedade "demo3" e a área laranja receberá o restante do conteúdo externo (start, I sou o conteúdo do embeding externo, fim).
Para referenciar o componente:
Neste ponto, veremos o conteúdo externo projetado no arquivo especificado .
Expanda o conhecimento
ngProjectAs
Agora sabemos que a propriedade select do ng-content permite especificar que conteúdo externo é projetado em um dado .
Para projetar corretamente o conteúdo com base no atributo select, há uma limitação – seja um cabeçalho de tag, um div com a classe "demo2" ou um div com o nome de propriedade "demo3", todas essas tags são subnós diretos da tag component.
O que aconteceria se não fosse por ser um subnó direto? Vamos simplesmente modificar o código que faz referência ao componente demo-component, colocar o cabeçalho da tag em um div e modificá-lo da seguinte forma:
Neste ponto, vemos que a parte do cabeçalho de aba do conteúdo não é mais projetada na área azul, mas sim na área laranja. O motivo é que <ng-content select="header"></ng-content> não pode corresponder ao cabeçalho da tag anterior, então essa parte do conteúdo é projetada para a <ng-content></ng-content> área laranja.
Para resolver esse problema, precisamos usar a propriedade ngProjectAs, que pode ser aplicada a qualquer elemento. Os detalhes são os seguintes:
Ao definir a propriedade ngProjectAs, o div onde o cabeçalho da tag está localizado aponta para select="header", e a parte do cabeçalho da tag é projetada para a área azul:
<ng-content>Não "gere" conteúdo Faça um experimento Para fazer um experimento, primeiro defina um componente demo-filho-componente:
componente demo-componente para:
Então, em demo-componente, caste demo-componente-filho:
Neste ponto, no console, vemos que a inicialização do componente demo-filho está completa! Essas palavras. Mas quando clicamos no botão para mudar de operação, a inicialização do componente filho demo está completa! Ele não é mais impresso, o que significa que nosso componente demo-filho só é instanciado uma vez – nunca destruído e recriado.
Por que isso está acontecendo?
Causas de ocorrência
<ng-content> Ele não "produz" conteúdo, apenas projeta conteúdo existente. Você pode pensar nisso como equivalente ao node.appendChild(el) ou ao método $(node).append(el) no jQuery: com esses métodos, o nó não é clonado, ele simplesmente é movido para sua nova localização. Portanto, o ciclo de vida do conteúdo projetado será limitado ao local onde ele é declarado, não exibido no local.
Isso também explica a pergunta anterior do princípio:Se houver vários ao mesmo tempo, como o conteúdo externo será projetado?
Esse comportamento é feito por dois motivos: consistência e desempenho. O que "consistência desejada" significa que, como desenvolvedor, você pode imaginar o comportamento da sua aplicação com base no código. Vamos supor que eu escreva o seguinte código:
Obviamente, o componente demo-child-component será instanciado uma vez, mas agora, se usarmos um componente de uma biblioteca de terceiros:
Se uma biblioteca de terceiros tem controle sobre o ciclo de vida de um componente demo-child, não terei como saber quantas vezes ele foi instanciado. A única maneira de fazer isso é olhar para o código das bibliotecas de terceiros para entender a lógica interna de processamento delas. O significado de vincular o ciclo de vida de um componente aos nossos componentes de aplicação em vez de wrappers é que os desenvolvedores podem controlar que os contadores sejam instanciados apenas uma vez, sem conhecer o código interno das bibliotecas de terceiros.
Razões para o desempenhoé mais importante. Como o ng-content é apenas um elemento móvel, ele pode ser feito em tempo de compilação, não em tempo de execução, o que reduz muito a carga de trabalho da aplicação real.
Solução alternativa
Para que o componente controle a instância dos subcomponentes projetados, podemos fazer isso de duas maneiras: usando <ng-template> elementos e ngTemplateOutlets ao redor do nosso conteúdo, ou usando diretivas de estrutura com sintaxe "*". Para simplificar, usaremos Syntax no exemplo <ng-template> .
componente demo-componente para:
Depois, incluímos o componente demo-child-component no ng-template:
Neste ponto, quando clicamos no botão para trocar, o console imprimiráInicialização do componente demo-filho concluída!Essas palavras.
|