Respostas:
Para entender o que checkoutProvidere displayAreasão, você deve primeiro entender o alcance que você está procurando em: jsLayout.
jsLayouté um monte de configuração do JavaScript para os elementos da interface do usuário do JavaScript na página de checkout. Se você olhar module-checkout/view/frontend/templates/onepage.phtml, notará os seguintes x-magento-initdados:
<script type="text/x-magento-init">
{
"#checkout": {
"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
}
}
</script>
Isso é onde tudo começa. Afirma:
Para o elemento
#checkout, inicialize oMagento_Ui/js/core/appcomponente com as seguintes informações: ...
E a informação que recebe é a informação criado no XML de layout: jsLayout. Agora, isso significa que tudo em seu XML agora é passado para o Magento_Ui/js/core/appcomponente (deixando plug-ins e processadores de layout e outras coisas fora da equação no momento ...)
Agora, não vou me aprofundar nos detalhes de como module-ui/view/base/web/js/core/app.jstudo se resume, porque isso tornaria este post muito, muito longo, mas o resumo é este:
Magento_Ui/js/core/appcomponente cria um checkoutcomponente.uiComponent(este é um componente muito genérico que pode ser usado para adiar seus próprios componentes de interface do usuário personalizados. Ele vem com renderização básica de modelo de knockout e outras coisas).Magento_Checkout/web/frontend/template/onepage.html.errors, estimation, steps, etc ...)stepscriança também será a uiComponent.Agora, para chegar à sua displayAreae provider-question: Como você viu acima, tudo é mapeado para as classes JavaScrip. A primeira vez que vemos o uso de displayAreaé quando nós criamos o steps-component, que é do tipo uiComponent. Então, uiComponentseria um candidato lógico para procurar o uso de displayArea.
Agora, a uiComponenté uma classe JavaScript do tipo Magento_Ui/js/lib/core/collection. (Você pode procurar isso em module-ui/view/base/requirejs-config.js). Isso mapeia para module-ui/view/base/web/js/lib/core/collection.js. Aqui vemos o seguinte uso:
/**
* Synchronizes multiple elements arrays with a core '_elems' container.
* Performs elemets grouping by theirs 'displayArea' property.
* @private
*
* @returns {Collection} Chainable.
*/
_updateCollection: function () {
var _elems = compact(this._elems),
grouped;
grouped = _elems.filter(function (elem) {
return elem.displayArea && _.isString(elem.displayArea);
});
grouped = _.groupBy(grouped, 'displayArea');
_.each(grouped, this.updateRegion, this);
this.elems(_elems);
return this;
},
Portanto, o que isso faz é "mapear" um uiComponent para um determinado grupo de componentes da interface do usuário. É importante saber, porque isso nos permite mover os componentes da interface do usuário para outros locais no layout, apenas manipulando o layout XML, assim como você faria com phtmlmodelos que são renderizados no servidor. Basta substituir o displayAreae você pode renderizar qualquer componente da interface do usuário JavaScript em qualquer outro lugar (considerando que a área de destino também é renderizada em algum lugar).
Agora, para a sua segunda pergunta: provider. Assim como procuramos displayArea, devemos começar a olhar primeiro para o componente da interface do usuário Magento_Checkout/js/view/form/element/email. E se olharmos para o requirejs-config.js, finalmente encontramos module-checkout/view/frontend/web/js/view/form/element/email.js.
Mas ... não provideré usado nesta classe. Então, vamos ver se conseguimos encontrar algo na classe que se estenda: Component(que é nossa uiComponentclasse-novamente).
Mas ... não providertambém. Bem, uiComponentsimplesmente se estende Element(que está localizado em module-ui/view/base/web/js/lib/core/element/element.js), então vamos dar uma olhada lá:
/**
* Parses 'modules' object and creates
* async wrappers for specified components.
*
* @returns {Element} Chainable.
*/
initModules: function () {
_.each(this.modules, function (name, property) {
if (name) {
this[property] = this.requestModule(name);
}
}, this);
if (!_.isFunction(this.source)) {
this.source = registry.get(this.provider);
}
return this;
},
Bingo! Acontece que o provedor é usado como uma fonte para buscar dados. Se olharmos para o construtor de Element, você verá que, por padrão, está definido como vazio:
provider: '',
Então, de volta à nossa configuração. Se agora lermos nossa configuração, entenderemos que o item shippingAddressé um componente Magento_Checkout/js/view/shipping, que busca seus dados no checkoutProvider.
Então, isso nos deixa com duas perguntas:
checkoutProviderdefinido?Bem, se você rolar até o final checkout_index_index.xml, notará que não passa de uma baunilha uiComponent:
<item name="checkoutProvider" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
</item>
E se você olhar module-checkout/view/frontend/web/js/view/shipping.js, verá que é usado assim:
registry.async('checkoutProvider')(function (checkoutProvider) {
var shippingAddressData = checkoutData.getShippingAddressFromData();
if (shippingAddressData) {
checkoutProvider.set(
'shippingAddress',
$.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
);
}
checkoutProvider.on('shippingAddress', function (shippingAddressData) {
checkoutData.setShippingAddressFromData(shippingAddressData);
});
});
Para ser honesto: é aqui que a minha análise para, porque também me torna difícil pesquisar e investir o que está acontecendo, mas espero que alguém possa buscá-lo daqui ...
Eu sei que tem algo a ver com o registry.async()retorno de um método que é executado imediatamente com uma função de retorno de chamada como argumento, mas alguém precisa explicar isso ...
* Aviso: Por todos os meios, por favor, corrija-me se eu estiver errado! Ainda não tentei nenhuma das opções acima, mas já trabalho há quase um ano com o Magento 2 e acredito que é assim que funciona. Infelizmente, não há muita documentação se você quiser mergulhar no fundo do oceano Magento.
Seis meses após minha resposta original, acho que posso fornecer uma resposta melhor sobre o que displayAreaé.
No meu entendimento, tudo isso vem junto com o getTemplate()método dos Knockouts , o getRegion()método e os filhos nos componentes da interface do usuário. Um bom exemplo disso pode ser visto quando você está examinando vendor/magento/module-checkout/view/frontend/templates/registration.phtmle vendor/magento/module-checkout/view/frontend/web/template/registration.html.
Em registration.phtml, você verá um componente Magento UI padrão que tem filhos:
<script type="text/x-magento-init">
{
"#registration": {
"Magento_Ui/js/core/app": {
"components": {
"registration": {
"component": "Magento_Checkout/js/view/registration",
"config": {
"registrationUrl": "<?php /* @escapeNotVerified */ echo $block->getCreateAccountUrl(); ?>",
"email": "<?php /* @escapeNotVerified */ echo $block->getEmailAddress(); ?>"
},
"children": {
"errors": {
"component": "Magento_Ui/js/view/messages",
"sortOrder": 0,
"displayArea": "messages",
"config": {
"autoHideTimeOut": -1
}
}
}
}
}
}
}
}
</script>
Observe o uso de displayAreano children-node. Basicamente, ele informa ao Knockout que esse elemento filho deve ser renderizado em uma região chamada 'mensagens' .
Agora dê uma olhada no topo de registration.html:
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
O que essa linha de código Knockout basicamente faz é: itera sobre todos os elementos filhos que estão presentes nas 'mensagens' displayArea e os renderiza.
Basicamente, o nome é um pouco confuso se você me perguntar. Por que você usaria 'displayArea' em um local e 'region' em outro local. Mas talvez minha suposição esteja totalmente incorreta. Talvez um desenvolvedor central do Magento possa esclarecer um pouco mais isso?
getRegione minha mente apenas implode. Obrigado por ambas as respostas, a propósito, muito útil!