我正在将现有主题转换为可重用组件。

我目前有一个像这样的按钮组件:

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

这当然适用于传入的单个按钮,但我似乎无法弄清楚如何允许更多,同时将每个按钮封装在其自己的列表项中。

对我处理此事的方式的任何建议或更正将不胜感激。谢谢你。

最佳答案

由于您想对组件的输出进行高级操作,因此现在可能是使用 render functions 的时候了,因为它们提供了更大的灵活性:

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 个参数,一个标签名称(如 ulli ),一个选项对象和一个子项列表。

我们首先通过我们的传入槽生成一个子节点列表,这些子节点存储在 this.$slots.default 中。

然后我们遍历这个列表,过滤掉基本上是文本的传入槽数据,这是因为 HTML 将标签之间的空白视为文本的方式。

我们现在几乎完成了我们的最终结构,我们现在将 slot 元素包装在一个新生成的 li 标签中,然后我们将所有内容包装在具有正确类名的新 ul 标签中,从而完成生成。

关于javascript - Vue 组件作为另一个组件的子组件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52064702/

10-12 12:18
查看更多