画面宽度发生变化,导致的按钮换行时,将按钮自动收起 2021-10-07

目的

画面宽度发生变化,导致的按钮换行时,将按钮自动收起

效果图

默认状态
默认状态
画面宽度缩小后
画面宽度缩小后

说明

如果要实际封装成组件,注册onresize的方式应该需要修改一下。

源码

<html>

<head>
    <link href="https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.8/dist/antd.css" rel="stylesheet">
    <style>
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.8/dist/antd.js"></script>
    <script>
        window.addEventListener("load", function () {
            Vue.use(antd);
            const autoBtns = Vue.component("autoBtns", {
                template: `<div ref="box">
                                    <span v-for="(s, i) in btns" v-show="isShowBtn(i)">
                                        <slot :name="'slot' + i"/>
                                    </span>
                                    <a-dropdown v-if="isInited" placement="bottomLeft" v-show="isShowMoreBtns()">
                                        <a-button icon="ellipsis"></a-button>
                                        <a-menu slot="overlay">
                                            <a-menu-item v-for="(item, i) in btns" :key="i" v-on="item.componentInstance.$listeners" v-show="i >= firstHideBtnIndex">
                                                {{item.elm.innerText}}
                                            </a-menu-item>
                                        </a-menu>
                                    </a-dropdown>
                            </div>`,
                data() {
                    return {
                        isResize: true,
                        isInited: false
                    };
                },
                created() {
                    this.btns.forEach((x, i) => {
                        this.$slots['slot' + i] = [x];
                    });
                },
                mounted() {
                    window.onresize = this.resize;
                    this.isInited = true;
                },
                methods: {
                    // 获取元素实际高度,包括margin
                    getOffsetWidth(el) {
                        let computedStyles = window.getComputedStyle(el);
                        let left = parseInt(computedStyles["margin-left"].slice(0, -2));
                        let right = parseInt(computedStyles["margin-right"].slice(0, -2));
                        return left + el.offsetWidth + right;
                    },
                    // 获取元素内部可用宽度,抛去边框和内边距之后
                    getInnerWidth(el) {
                        let computedStyles = window.getComputedStyle(el);
                        let leftP = parseInt(computedStyles["padding-left"].slice(0, -2));
                        let rightP = parseInt(computedStyles["padding-right"].slice(0, -2));
                        let leftB = parseInt(computedStyles["border-left"].slice(0, -2));
                        let rightB = parseInt(computedStyles["border-right"].slice(0, -2));
                        return leftP + leftB + el.offsetWidth + rightB + rightP;
                    },
                    isShowBtn(i) {
                        return i < this.firstHideBtnIndex;
                    },
                    isShowMoreBtns() {
                        return this.firstHideBtnIndex < this.btns.length;
                    },
                    resize() {
                        this.isResize = !this.isResize;
                    }
                },
                computed: {
                    btns() {
                        return this.$slots.default.filter(x => x.tag != null);
                    },
                    widths() {
                        if (this.isInited) {
                            return this.btns.map(x => this.getOffsetWidth(x.elm));
                        }
                        return [];
                    },
                    firstHideBtnIndex() {
                        this.isResize;
                        if (!this.isInited) return this.btns.length;
                        let boxW = this.getInnerWidth(this.$refs.box);
                        let totalW = 0;
                        let index = this.widths.findIndex(x => {
                            totalW += x;
                            return totalW > boxW;
                        });
                        if(index == -1){
                            return this.btns.length;
                        }
                        return index - 1;
                    }
                },
                beforeUpdate() {
                    this.btns.forEach((x, i) => {
                        this.$slots['slot' + i] = [x];
                    });
                },
                updated() {
                }
            });

            const app = new Vue({
                el: "#app",
                data() {
                    return {
                        slider: 300
                    };
                },
                mounted() {
                },
                methods: {
                    click() {
                    },
                    handleChange: (function () {
                        let t;
                        return function () {
                            if (t == null) {
                                this.$refs.autoBtns.resize();
                                t = setTimeout(() => t = null, 500);
                            }
                        }
                    })()
                }
            });
        });
    </script>
</head>

<body>
    <div id="app">
        <auto-btns ref="autoBtns" :style="{width: '20vw',background:'red'}">
            <a-button>按钮1</a-button>
            <a-button>按钮2</a-button>
            <a-button>按钮3</a-button>
            <a-button>按钮4</a-button>
            <a-button @click="click">按钮5</a-button>
        </auto-btns>
    </div>

</body>

</html>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值