Как создать слот Vue.js программно? - PullRequest
0 голосов
/ 03 мая 2018

У меня есть следующий компонент со слотом:

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

По некоторым причинам я должен вручную создать экземпляр этого компонента. Вот как я это делаю:

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

Проблема в том, что я не могу программно создавать содержимое слотов. Пока что я могу создать простой слот на основе строк:

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

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

instance.$mount(body);

Вопрос в том, как я могу создать $slots программно и передать его экземпляру, который я создаю, используя new?

Примечание. Я не использую полную сборку Vue.js (только во время выполнения). Поэтому у меня нет компилятора Vue.js для компиляции шаблона на лету.

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

(Это на самом деле не отвечает How to create Vue.js slot programatically?. Но это действительно решает вашу проблему.)

Этот трюк менее хакерский по сравнению с использованием $createElement().

По сути, создайте новый компонент, который зарегистрирует MyComponent как локальный компонент.

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

Демо: https://jsfiddle.net/jacobgoh101/shrn26p1/

0 голосов
/ 30 октября 2018

Мне кажется, я наконец-то наткнулся на способ программно создать элемент слота. Из того, что я могу сказать, похоже, что подход не работает для функциональных компонентов. Я не уверен почему.

Если вы реализуете свой собственный метод рендеринга для компонента, вы можете программно создавать слоты, которые вы передаете дочерним элементам, используя метод createElement (или любой другой, к которому вы добавили псевдоним в методе рендеринга), и передавая хеш данных, который включает в себя {slot: NAME_OF_YOUR_SLOT}, за которым следует массив дочерних элементов в этом слоте.

Например:

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/vue@2.5.17/dist/vue.js"></script>

<div id='app'>
</div>
0 голосов
/ 03 мая 2018

Я просмотрел файлы определений TypeScript Vue.js и обнаружил недокументированную функцию в экземпляре компонента Vue: $createElement(). Я предполагаю, что это та же самая функция, которая передается функции render(createElement) компонента. Итак, я могу решить это как:

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);

Но это явно недокументированный и, следовательно, сомнительный подход. Я не буду отмечать ответ, если есть какой-то лучший подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...