web-dev-qa-db-fra.com

Comment créer un slot Vue.js par programme?

J'ai le composant suivant avec un slot:

<template>
    <div>
        <h2>{{ someProp }}</h2>
        <slot></slot>
    </div>
</template>

Pour certaines raisons, je dois instancier manuellement ce composant. Voici comment je le fais:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
}).$mount(body);

Le problème est: je ne suis pas en mesure de créer le contenu d'un slot par programme. Jusqu'à présent, je peux créer un slot simple basé sur une chaîne:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
});

// Creating simple slot
instance.$slots.default = ['Hello'];

instance.$mount(body);

La question est - comment puis-je créer $slots par programme et le transmettre à l'instance que je crée en utilisant new?

Remarque: je n'utilise pas une version complète de Vue.js (runtime uniquement). Je n'ai donc pas de compilateur Vue.js disponible pour compiler le modèle à la volée.

15
Harshal Patil

J'ai regardé dans les fichiers de définition TypeScript de Vue.js Et j'ai trouvé une fonction non documentée sur Vue instance du composant: $createElement(). Je suppose que c'est la même fonction qui est passé à render(createElement) fonction du composant. Donc, je suis capable de le résoudre comme:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
});

// Creating simple slot
const node = instance.$createElement('div', ['Hello']);
instance.$slots.default = [node];

instance.$mount(body);

Mais cette approche est clairement non documentée et donc discutable. Je ne marquerai pas sa réponse s'il existe une meilleure approche.

8
Harshal Patil

Je pense que j'ai finalement trouvé un moyen de créer par programme un élément slot. D'après ce que je peux dire, l'approche ne semble pas fonctionner pour les composants fonctionnels. Je ne suis pas sûr pourquoi.

Si vous implémentez votre propre méthode de rendu pour un composant, vous pouvez créer par programmation des emplacements que vous transmettez aux éléments enfants à l'aide de la méthode createElement (ou tout ce que vous avez défini comme alias dans la méthode de rendu), et en passant un hachage de données qui inclut {slot : NAME_OF_YOUR_SLOT} suivi du tableau des enfants dans cet emplacement.

Par exemple:

Vue.config.productionTip = false
Vue.config.devtools = false;

Vue.component('parent', {
  render (createElement) {
    return createElement('child', [
      createElement('h1', { slot: 'parent-slot' }, 'Parent-provided Named Slot'),
      createElement('h2', { slot: 'default' }, 'Parent-provided Default Slot')
    ])
  }
})

Vue.component('child', {
  template: '<div><slot name="parent-slot" /><slot /></div>'
})

new Vue({
  el: '#app',
  template: '<parent />'
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

<div id='app'>
</div>
3
Andrew H

(Cela ne répond pas vraiment à How to create Vue.js slot programatically?. Mais cela résout votre problème.)

Cette astuce est moins hackeuse que l'utilisation de $createElement().

Fondamentalement, créez un nouveau composant qui enregistre MyComponent en tant que composant local.

const Constr = Vue.extend({
  template: `
  <MyComponent someProp="My Heading">
    <div>slot here !!!</div>
  </MyComponent>
  `,
  components: {
    MyComponent: MyComponent
  }
});
const instance = new Constr().$mount('#app');

Démo: https://jsfiddle.net/jacobgoh101/shrn26p1/

1
Jacob Goh

Je viens de trouver une réponse à cela dans vue forum: slots

Le principe est le suivant: il n'y a rien de tel que createElement ('slot' ..) Au lieu de cela il y a une fonction de rendu qui fournit le fendu innerHtml comme fonction: $ scopedSlots .défaut()

Usage:

render: function (createElement) {
  const self = this;
  return createElement("div", this.$scopedSlots.default());
}

Si vous souhaitez fournir une valeur par défaut au cas où aucun contenu n'est donné pour les emplacements, vous devez coder vous-même une distinction et rendre autre chose. (Le lien ci-dessus contient un exemple plus détaillé)

La fonction renvoie un tableau, elle ne peut donc pas être utilisée comme racine pour la fonction de rendu. Il doit être encapsulé dans un nœud de conteneur unique comme div dans l'exemple ci-dessus.

0
Disco12