目的
画面宽度发生变化,导致的按钮换行时,将按钮自动收起
效果图
默认状态
画面宽度缩小后
说明
如果要实际封装成组件,注册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>