À quoi servent les valeurs par défaut de l'importation / exportation dans un objet uiElement?

8

Dans de nombreux constructeurs de modèles de vue d'élément d'interface utilisateur de Magento 2, le defaultstableau aura une propriété importsor exports.

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

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

En regardant la source du uiElementmodule,

#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');
    },

Ces importations / exportations semblent avoir quelque chose à voir avec la "liaison" d'informations entre les objets lorsqu'un objet est instancié. Cependant, il n'est pas clair comment ce lien fonctionne (basé sur uiRegistry?) Ou quelle est la syntaxe des chaînes comme ${ $.provider }:data.items. Il est clair que ces chaînes utilisent des littéraux de modèle qui se développent en quelque chose comme

foo_bar:data.items

Mais la signification de cette chaîne finale est encore mystérieuse.

Quelqu'un sait-il comment fonctionnent les propriétés d'importation / exportation de ces objets?

Alan Storm
la source
Je ne posterai pas de réponse car je ne les ai pas réellement utilisées, mais les devdocs donnent un peu plus d'informations: devdocs.magento.com/guides/v2.1/ui-components/…
Vinai

Réponses:

21

Ces propriétés permettent aux composants d'être connectés afin qu'ils puissent interagir les uns avec les autres. Le principe est assez simple: importer (prendre) une valeur d'un autre composant ou exporter (envoyer) une valeur vers un autre composant ou faire les deux.


Remarque: pour maintenir la clarté de cette réponse, un "composant" est un objet Javascript qui est renvoyé par RequireJS, a un nom spécifique et est accessible par ce nom via UIRegistry.

De plus, tous les exemples ci-dessous se trouveraient dans la defaults: {}propriété du composant.


Avec le principe énoncé, commençons par ce que je considère comme le concept le plus simple:

Importations

Cette propriété prend une valeur d'un autre composant et l'affecte à la propriété spécifiée. Dans l'exemple suivant, nous déclarons une importation:

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

Lorsque Magento initialise ce composant, il tentera d'attribuer la valeur à la messagepropriété. Cette propriété sera disponible dans le contexte KnockoutJS. Comme nous le savons , cependant, il évaluera d'abord la imports.messagevaleur en tant qu'expression littérale de modèle. Dans ce cas, Magento analysera le $.provideret devrait obtenir une valeur. Bien que cela puisse être un certain nombre de choses, dans cet exemple et selon de nombreux cas d'utilisation principaux de Magento, c'est le nom d'un composant qui se trouve dans le registre de l'interface utilisateur. Cela sera analysé avant la prochaine étape.

Étant donné que la messagepropriété est dans la importspropriété, elle sera transmise à la setLinks()méthode dans uiElement.initLinks(). La setLinks()méthode est en place Magento/Ui/view/base/web/js/lib/core/element/links.js. Là, il boucle sur toutes les propriétés (uniquement messageici) dans l'objet qui a été passé ( importsdans ce cas). Sur ces propriétés, il tentera de transférer des données d'un composant à l'autre.

La transfer()fonction est le prochain lieu d'intérêt. Ici, le registre est recherché pour le composant qui est le "propriétaire", dans le cas d'une importation. Ce composant est celui qui "détient" actuellement ou possède les données et serait le $.providerdans l'exemple ci-dessus. Si le composant est trouvé, il procédera alors à la liaison des données avec la setLink()fonction.

Il y a deux choses à noter dans cette méthode: premièrement, elle définit un écouteur d'événements sur la propriété, et deuxièmement, elle transférera immédiatement les données si l'indicateur applicable a été envoyé. Lors de mes tests, il a toujours passé le immediateparamètre afin que le transfert se produise lors de l'initialisation. Toutefois, en raison de l'écouteur d'événements qui a été associé à la première étape, il continuera à mettre à jour les valeurs, si elles changent, afin que les deux composants restent synchronisés.

Les données sont ensuite définies sur (ou, en termes plus simples: "renvoyé au") composant qui avait la imports: {}propriété. Comme je l'ai mentionné précédemment, il est ensuite affecté directement à la propriété du composant qui l'a déclaré - essentiellement this.messagedans l'exemple ci-dessus et non this.defaults.imports.message. Par conséquent, data-bind="text: messagedoit afficher la valeur renvoyée par la data.messagepropriété du composant lié .

Cette approche vous permet de définir le nom de la propriété dans le composant source. Dans l'exemple ci-dessus, vous pouvez utiliser alertMessage: ...au lieu de messagecomme nom de propriété de votre composant.

Exportations

Les exportations sont l'inverse de imports. Ils sont basés sur la même fonctionnalité que les importations, mais au lieu de prendre des données d'un composant et de les affecter à lui-même, il envoie ses propres données à un autre composant. En conséquence, presque tout est le contraire. Prenez cet exemple:

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

Dans cet exemple, setLinks()prend la valeur de la phoneNumberpropriété de ce composant et l'affecte à la phonepropriété du formulaire de contact . Cela revient à déclarer explicitement une phonepropriété dans le $.contactFormcomposant. Sans aucune configuration particulière dans le $.contactForm, vous pouvez alors accéder directement à ces données. Peut-être comme celui - ci dans un modèle knock - out: data-bind="text: phone.

Liens

Enfin, la linkspropriété revient à déclarer les deux importset exportspour la même propriété. À première vue, cela peut sembler une référence circulaire. Bien que ce soit en quelque sorte, il y a des moments où cela pourrait être utile. Bien que je sois sûr qu'il existe de nombreux autres cas d'utilisation, celui que je peux voir est la capacité d'un composant à manipuler dynamiquement les données d'un autre composant. Dans ce cas, ComponentA est la source de certaines données et les affiche sur la page. ComponentB doit manipuler ces données et ainsi linksà cette propriété. Il peut à la fois afficher les données et manipuler les données réelles dans ComponentA sans jamais étendre ou modifier ComponentA.

Une chose à noter, cependant, est que, par défaut, ce linksn'est pas un moyen de connecter deux autres modules. En d'autres termes, ComponentC ne peut pas linkComponentA à ComponentB. Il s'agit d'une méthode de synchronisation bidirectionnelle d'un composant avec un autre.


Lier ( imports, exportset links) peut faciliter presque toujours des fonctions assignées à ces propriétés ainsi. J'ai rencontré un comportement étrange lors de la création d'observables et de l'utilisation, linksmais dans l'ensemble, cela a très bien fonctionné.

La liaison fournit des valeurs qui sont disponibles dans la portée KnockoutJS et peuvent être manipulées comme vous le feriez pour toute autre propriété. Et, réitérer clairement: rappelez - vous que la imports, exportset linksde l' objet des clés se réfèrent toujours à des propriétés de la composante de courant (celui dans lequel ces propriétés ont été déclarées), alors que la valeur a trait au nom et les propriétés du composant distant .


En conclusion, Magento utilise cette fonctionnalité de liaison pour connecter différents composants entre eux et c'est un moyen que nous pouvons accéder, fournir ou synchroniser des données avec d'autres composants.

bassplayer7
la source
Grande explication @ bassplayer7 - En avez-vous des exemples? Je comprends comment cela fonctionne, mais pour la vie de moi, je ne peux pas obtenir que deux de mes composants d'interface utilisateur simples partagent un KO observable.
Ben Crook
@BenCrook, malheureusement, je n'ai pas fait grand-chose avec ça depuis un moment donc je n'en ai pas tout de suite. À présent, je suis sûr que vous l'avez compris, mais je suggère de travailler avec importset exportsplutôt que links. J'ai trouvé linksplus obscur et fragile. Si vous avez rencontré un exemple, pourriez-vous partager un lien?
bassplayer7
J'ai essayé et échoué à faire fonctionner les importations / exportations / liens, Vinai a répondu à la question ici même si je n'ai pas encore eu l'occasion de l'essayer.
Ben Crook
Cette information serait formidable sur les documents officiels de développement. Le processus de composant d'interface utilisateur est juste une bête effrayante.
Nathaniel Rogers