Vue компонент как дочерний элемент другого компонента - PullRequest
0 голосов
/ 28 августа 2018

Я работаю над преобразованием существующей темы в повторно используемые компоненты.

У меня сейчас есть такой компонент кнопки:

<template>
    <a :href="link" class="button" :class="styling"><slot></slot></a>
</template>

<script>
export default {
    props: {
        link: {},
        styling: {
            default: ''
        }
    }
}
</script>

И, в моем HTML, я использую это так:

<vue-button link="#" styling="tiny bg-aqua">Button 1</vue-button>

Теперь я пытаюсь создать «группу кнопок», используя существующий компонент кнопки.

То, что я хотел бы сделать, это что-то вроде этого:

<vue-button-group styling="radius tiny">
    <vue-button link="#" styling="tiny bg-aqua">Button 1</vue-button>
    <vue-button link="#" styling="tiny bg-aqua">Button 2</vue-button>
    <vue-button link="#" styling="tiny bg-aqua">Button 3</vue-button>
    <vue-button link="#" styling="tiny bg-aqua">Button 4</vue-button>
</vue-button-group>

Я очень новичок в VueJS, и меня немного смущает правильный способ справиться с такой вещью. Я хотел бы иметь возможность передавать столько компонентов кнопок в группу, сколько необходимо.

Вот что у меня есть для группы кнопок:

<template>
    <ul class="button-group" :class="styling">
        <li><slot></slot></li>
    </ul>
</template>

<script>
    export default {
        props: {
            styling: {
                default: ''
            }
        }
    }
</script>

Это, конечно, будет работать с передачей одной кнопки, но я не могу понять, как допустить большее, при этом заключая каждую кнопку в отдельный элемент списка.

Буду очень признателен за любые предложения или исправления в отношении того, как я это делаю. Спасибо.

Ответы [ 4 ]

0 голосов
/ 28 августа 2018

Поскольку вы хотите выполнять более сложные действия с выводом вашего компонента, возможно, настало время перейти к функциям рендеринга , поскольку они обеспечивают гораздо большую гибкость:

Vue.component('button-group', {
    props: {
        styling: {
            default: ''
        }
    },
    render(createElement) { // createElement is usually called `h`
        // You can also do this in 1 line, but that is more complex to explain...
        // const children = this.$slots.default.filter(slot => slot.tag).map(slot => createElement('li', {}, [slot]))
        const children = [];
        for(let i = 0; i < this.$slots.default.length; i++) {
            if(!this.$slots.default[i].tag) {
                // Filter out "text" nodes, so we don't make li elements
                // for the enters between the buttons
                continue;
            }
            children.push(createElement('li', {}, [
                this.$slots.default[i]
            ]));
        }

        return createElement('ul', {staticClass: "button-group",class: this.styling}, children);
    }
})

var app = new Vue({
  el: '#app',
})
.rainbow-background {
    /* todo: implement rainbow background */
    border: red 1px solid;
}
.button-group {
    border-color: blue;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id="app">
    <button-group styling="rainbow-background">
        <button>hi</button>
        <button>How are you?</button>
        <button>I'm fine</button>
        <button>Have a nice day!</button>
    </button-group>
</div>

Функция рендеринга работает, возвращая виртуальную HTML-структуру, эта структура генерируется повторными вызовами функций createElement. createElement принимает 3 параметра, имя тега (например, ul или li), объект параметров и список дочерних элементов.

Сначала мы создадим список дочерних элементов с нашими входящими слотами, которые хранятся внутри this.$slots.default.

Затем мы перебираем этот список, отфильтровывая входящие данные слотов, которые в основном являются текстовыми, потому что HTML рассматривает пробелы между тегами как текст.

Теперь мы почти закончили с нашей окончательной структурой, теперь мы обертываем элемент слота недавно сгенерированным тегом li, а затем мы завершаем генерацию с упаковкой всего в новый тег ul с соответствующими именами классов. .

0 голосов
/ 28 августа 2018

Вы также можете попробовать использовать именованный слот

<template>
    <ul class="button-group">
        <li><slot name="buttons"></slot></li>
    </ul>
</template>

А чем:

<vue-button-group class="radius tiny">
    <template slot="buttons">
       <vue-button link="#" styling="tiny bg-aqua">Button 1</vue-button>
       <vue-button link="#" styling="tiny bg-aqua">Button 2</vue-button>
       <vue-button link="#" styling="tiny bg-aqua">Button 3</vue-button>
       <vue-button link="#" styling="tiny bg-aqua">Button 4</vue-button>
   </template>
</vue-button-group>
0 голосов
/ 28 августа 2018

Vue способ сделать это - использовать слоты имен и предоставить данные, которые ребенок использует, родителю. Данные будут передаваться ребенку через slot-scope.

Весь ключ к этому , данные передаются от родителя к потомку .

Вот рабочий код процесса: https://codepen.io/Flamenco/pen/ZMOdYz

В этом примере используется слот по умолчанию, поэтому атрибут name не требуется для родительского или дочернего элемента.

Родитель

<template>
    <ul class="button-group" :class="styling">
        <li v-for='item in items'><slot :item='item'></slot></li>
    </ul>
</template>

<script>
   ...
   props:{
      items: Array
   }
</script>

Дети

<vue-button-group class="radius tiny" :items='items'>
    <template slot-scope='scope'>
       <vue-button link="#" styling="tiny bg-aqua">{{scope.item.text}}</vue-button>
   </template>
</vue-button-group>


<script>
   ...
   data:{
      items:[{text:'Button 1'},{text:'Button 2'},{text:'Button 3}]
   }
</script>
0 голосов
/ 28 августа 2018

Возможным решением для этого является использование v-for .

<button v-for="button in buttons" :key="button">
Button{{button}}
</button>

Вот скрипка .

Оттуда вы можете построить свой <buttongroup> -компонент самостоятельно; передача «мета-информации» в ваш <buttongroup> как реквизит (в моей скрипке массив в data -части).

Слоты будет иметь смысл, если вы хотите визуализировать что-то еще, кроме кнопок, и вы хотите добавить компоненты для этого. В противном случае вы ничего не получите со слотами.

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