vue 怎么拆分默认插槽中的数据?

作者站长头像
站长
· 阅读数 10

vue 怎么拆分默认插槽中的数据?

如上,我想做一个组件,里面有N个按钮(会根据不同状态显隐),当按钮数量小于3个时 全部显示出来,当按钮数量大于3个时 只显示前3个,然后自动显示一个更多按钮,点击更多后以弹框的形式显示其他按钮。

本来是想不用插槽,通过json数组的方式把按钮数据传到组件里,在组件里生成按钮,但是这样用起来不是很方便。

改成插槽后的写法:

父组件
<btns>
    <btn v-if="false">1</btn1>
    <btn v-if="false">2</btn1>
    <btn v-if="true">3</btn1>
    <btn v-if="false">4</btn1>
    <btn v-if="true">5</btn1>
    <btn v-if="true">6</btn1>
    <btn v-if="true">7</btn1>
</btns>
子组件
this.$slots["default1"] = this.$slots.default.slice(0, 3);
this.$slots["default2"] = this.$slots.default.slice(3);

<slot name="default1"></slot>
<slot name="default2"></slot>

我想把默认插槽里面的数据拆分成default1和default2两部分,但渲染不出来,请问有其他什么方法吗。

或者说不用这个思路,要做这种类型的组件,大家觉得应该怎么写,才能让使用者用起来最方便

回复
1个回答
avatar
test
2024-07-14

answer imageanswer image

首先理下需求,如上图,有一个按钮组,里面最多有N个按钮(按不同条件显示不同按钮),当显示的按钮超过3个时,只显示前3个,然后在左侧或者右侧显示一个更多按钮,点击后弹出剩下的按钮。

这里有如下两次使用方法。第一种使用方法我觉得太繁琐了。

1.我需要维护额外一个btnList变量,如果是一个任务列表,每条任务都有一个这种按钮组,那么我就需要在向后台请求到每一页任务的数据后,都要先循环任务数组,在每条任务的json中创建一个btnList变量,然后再渲染页面。
2.把按钮的样式封装进btns组件我感觉也不是很好,如果我想加功能,比如 改里面按钮的样式,或者在按钮上加一个badge小徽标 都不是很方便,需要在btnList数组里加新字段,然后改h-btns组件源码。
3.需要在子组件的@click事件中统一判断点击的是哪个按钮,这里感觉也不方便。

所以优先考虑第二种写法。

用法1
let btnList = [{text:'按钮1',class:'aaa'}{text:'按钮2',class:'bbb'},...];
<h-btns :btns='btnList' @click="在这里统一判断点击的是哪个按钮"></h-btns>

用法2
<h-btns>
    <h-btn v-if="true" class='' @click=''>按钮1</h-btn>
    <h-btn v-if="false" class='' @click=''><badge value="23">按钮2</badge></h-btn>
    <h-btn v-if="true" class='' @click=''>按钮3{{item.num}}</h-btn>
    <h-btn v-if="true" class='' @click=''>按钮4</h-btn>
    <h-btn v-if="false" class='' @click=''>按钮5</h-btn>
    <h-btn v-if="true" class='' @click=''>按钮6</h-btn>
    <h-btn v-if="true" class='' @click=''>按钮7</h-btn>
</h-btns>

然后第二种写法的核心问题就是怎么把插槽里面的按钮拆分成 默认显示的 和 更多弹框中 的两部分。这里没找到很好的方法,然后我想到了用css变相解决

源码
<div class="btns">
    <!--默认显示部分-->
    <slot name="default"></slot>
            
    <div class="btns_moreBox">
        <a href="javascript:;" class="btns_moreBtn">更多</a>
        <!--更多弹框-->
        <div class="btns_moreContent">
            <slot name="default"></slot>
        </div>
    </div>
            
</div>

编译后
<div class="btns">
    <!--默认显示部分-->
    <btn>按钮1</btn>
    <btn>按钮2</btn>
    <btn>按钮3</btn>
    <btn>按钮4</btn>
    <btn>按钮5</btn>
    <btn>按钮6</btn>
            
    <div class="btns_moreBox">
        <a href="javascript:;" class="btns_moreBtn">更多</a>
        <!--更多弹框-->
        <div class="btns_moreContent">
            <btn>按钮1</btn>
            <btn>按钮2</btn>
            <btn>按钮3</btn>
            <btn>按钮4</btn>
            <btn>按钮5</btn>
            <btn>按钮6</btn>
        </div>
    </div>
            
</div>

CSS核心部分
btn{flex:1;}
.btns_moreBox{none;}

btn:nth-child(3) ~ btn{display:none;}    //外部只显示前3个按钮
btn:nth-child(4) ~ .btns_moreBox{display:block;}    //超过3个显示更多按钮
.btns_moreContent btn{display:none;}
.btns_moreContent btn:nth-child(3) ~ btn{display:block;}    //更多弹层中只显示第3个以后的按钮
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容