Quais são os `padrões 'de importação / exportação em um objeto uiElement?

8

Em muitos dos construtores de modelos de visualização de elementos de interface do usuário do Magento 2, o defaultsarray terá uma propriedade importsou exports.

return Collection.extend({
    defaults: {
        //...
        imports: {
            rows: '${ $.provider }:data.items'
        },

return Insert.extend({
    defaults: {
        //...
        exports: {
            externalFiltersModifier: '${ $.externalProvider }:params.filters_modifier'
        },

Olhando a fonte do uiElementmódulo,

#File: vendor/magento/module-ui/view/base/web/js/lib/core/element/element.js
    initLinks: function () {
        return this.setListeners(this.listens)
                   .setLinks(this.links, 'imports')
                   .setLinks(this.links, 'exports')
                   .setLinks(this.exports, 'exports')
                   .setLinks(this.imports, 'imports');
    },

Essas importações / exportações parecem ter algo a ver com "vincular" informações entre objetos quando um objeto é instanciado. No entanto, não está claro como essa vinculação funciona (com base no uiRegistry?) Ou como ${ $.provider }:data.itemssão a sintaxe das strings . É claro que essas strings usam literais de modelo que se expandem para algo como

foo_bar:data.items

Mas o significado dessa corda final ainda é misterioso.

Alguém sabe como as propriedades de importação / exportação desses objetos funcionam?

Alan Storm
fonte
Não vou postar uma resposta, já que eu realmente não as usei, mas os devdocs oferecem um pouco mais de informações: devdocs.magento.com/guides/v2.1/ui-components/…
Vinai

Respostas:

21

Essas propriedades permitem que os componentes sejam conectados para que eles possam interagir entre si. O princípio é um pouco simples: importar (obter) um valor de outro componente ou exportar (enviar) um valor para um componente diferente ou fazer as duas coisas.


Nota: para manter a clareza nesta resposta, um "componente" é um objeto Javascript retornado pelo RequireJS, tem um nome específico e pode ser acessado por esse nome através do UIRegistry.

Além disso, todos os exemplos abaixo estariam dentro da defaults: {}propriedade do componente.


Com o princípio estabelecido, vamos começar com o que considero o conceito mais fácil:

Importações

Esta propriedade pega um valor de outro componente e o atribui à propriedade especificada. No exemplo a seguir, declaramos uma importação:

imports: {
    message: '${ $.provider }:data.message'
}

Quando o Magento inicializa esse componente, ele tenta atribuir o valor à messagepropriedade. Esta propriedade estará disponível no contexto KnockoutJS. Como sabemos , no entanto, ele avaliará o imports.messagevalor como uma expressão literal do modelo primeiro. Nesse caso, o Magento analisará $.providere deve obter um valor. Embora possa haver várias coisas, neste exemplo e de acordo com muitos dos principais casos de uso do Magento, é o nome de um componente que está no registro da interface do usuário. Isso será analisado antes da próxima etapa.

Como a messagepropriedade está na importspropriedade, ela será passada para o setLinks()método in uiElement.initLinks(). O setLinks()método é, em Magento/Ui/view/base/web/js/lib/core/element/links.js. Lá, ele faz um loop sobre todas as propriedades (somente messageaqui) no objeto que foi passado ( importsneste caso). Nessas propriedades, ele tentará transferir dados de um componente para outro.

A transfer()função é o próximo local de interesse. Aqui, o registro é pesquisado para o componente que é o "proprietário", no caso de uma importação. Esse componente é o que atualmente "possui" ou possui os dados e seria $.providero exemplo acima. Se o componente for encontrado, ele continuará vinculando os dados à setLink()função.

Há duas coisas a serem observadas nesse método: primeiro, ele define um ouvinte de evento na propriedade e, segundo, transfere imediatamente os dados se o sinalizador aplicável tiver sido enviado. Nos meus testes, sempre passava o immediateparâmetro para que a transferência acontecesse durante a inicialização. No entanto, devido ao ouvinte de evento anexado na primeira etapa, ele continuará atualizando os valores, se eles forem alterados, para que os dois componentes permaneçam sincronizados.

Os dados são então configurados (ou, em termos mais simples: "retornados ao") componente que possuía a imports: {}propriedade. Como mencionei anteriormente, ele é atribuído diretamente à propriedade do componente que o declarou - essencialmente this.messageno exemplo acima e não this.defaults.imports.message. Como resultado, data-bind="text: messagedeve exibir o valor retornado da data.messagepropriedade do componente vinculado .

Essa abordagem permite definir qual é o nome da propriedade no componente de origem. No exemplo acima, você poderia usar em alertMessage: ...vez de messagecomo o nome da propriedade do seu componente.

Exportações

As exportações são inversas imports. Eles são baseados na mesma funcionalidade das importações, mas, em vez de pegar os dados de um componente e atribuí-los a si mesmo, ele envia seus próprios dados para outro componente. Como resultado, quase tudo é o oposto. Veja este exemplo:

exports: {
    phoneNumber: '${ $.contactForm }:phone'
}

Neste exemplo, setLinks()pega o valor da propriedade desse componentephoneNumber e o atribui à phonepropriedade do formulário de contato . É o mesmo que declarar explicitamente uma phonepropriedade no $.contactFormcomponente. Sem nenhuma configuração específica no $.contactForm, você pode acessar esses dados diretamente. Talvez como este em um modelo Knockout: data-bind="text: phone.

Ligações

Finalmente, a linkspropriedade é a mesma que declarar ambas importse exportspara a mesma propriedade. À primeira vista, isso pode parecer uma referência circular. De certa forma, há momentos em que isso pode ser útil. Embora eu tenha certeza de que existem muitos outros casos de uso, o que posso ver é a capacidade de um componente manipular dados de outro componente dinamicamente. Nesse caso, o ComponentA é a fonte de alguns dados e os exibe na página. ComponentB precisa manipular esses dados e, portanto, linkspara essa propriedade. Ele pode exibir os dados e manipular os dados reais no ComponentA sem nunca estender ou alterar o ComponentA.

Uma coisa a observar, porém, é que, por padrão, linksnão é uma maneira de conectar outros dois módulos. Em outras palavras, o ComponentC não pode linkComponentA para ComponentB. É um método de sincronizar bidirecionalmente um componente com outro.


Ligando ( imports, exportse links) quase sempre pode facilitar as funções atribuídas a essas propriedades também. Eu tive algum comportamento estranho ao criar observáveis ​​e usar, linksmas no geral funcionou muito bem.

A vinculação fornece valores que estão disponíveis no escopo KnockoutJS e podem ser manipulados como qualquer outra propriedade. E, para reiterar claramente: lembre-se que o imports, exportse linksdo objeto chaves sempre se referem a propriedades do componente de corrente (aquele em que essas propriedades foram declaradas), enquanto que pertence o valor para o nome e as propriedades do componente remoto .


Em conclusão, o Magento usa essa funcionalidade de conexão para conectar componentes diferentes entre si e é uma maneira de acessar, fornecer ou sincronizar dados com outros componentes.

bassplayer7
fonte
Ótima explicação @ bassplayer7 - Você tem exemplos disso? Entendo como funciona, mas para a minha vida não consigo que dois dos meus componentes simples da interface do usuário compartilhem um KO observável.
perfil completo de Ben Crook
@ BenCrook, infelizmente, eu não faço muito com isso há algum tempo, então não tenho um direito. Até agora eu tenho certeza que você já descobriu, mas sugiro trabalhar com importse exportsnão links. Eu achei linksmais obscuro e quebradiço. Se você encontrou um exemplo, poderia compartilhar um link?
bassplayer7
Tentei e não consegui fazer com que as importações / exportações / links funcionassem, o Vinai respondeu à pergunta aqui, embora ainda não tenha tido chance de testá-lo.
Ben Crook
Essa informação seria ótima nos desenvolvedores oficiais. O processo de Cmponent da interface do usuário é apenas uma fera assustadora.
Nathaniel Rogers #