默认排序
- flex 内部三个模块,默认按从左到右顺序排列
- 为了美观,使 模块2 占剩余所有宽度(flex-grow:1),内部元素向右对齐(justify-content: flex-end),模块1 和 模块3 不被压缩(flex-shrink: 0)

html
<div class="titleLine">
<div class="mainTitle">主要标题</div>
<div class="subTitles">
<div class="sinText">小标题1</div><div class="sinText">小标题2</div><div class="sinText">小标题3</div>
</div>
<div class="optionBtn">操作按钮 ></div>
</div>
<style scoped lang="scss">
.titleLine {
display: flex;
align-items: center;
justify-content: space-between;
.mainTitle {
flex-shrink: 0;
}
.subTitles {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: flex-end;
.sinText {
margin-left: 10px;
}
}
.optionBtn {
flex-shrink: 0;
}
}
</style>
适应宽度
- 宽度变小时,调整模块的 order 属性,在不手动改变 dom 顺序的情况下,保证页面美观不变形
order 为负值
- 为 模块3 添加 order: -1 属性,将其提到最前边,并改变 width 属性,使其独占一行
- 模块1 和 模块2 仍保持默认的 order: 0,保持在一行不变

html
<style scoped lang="scss">
.titleLine {
flex-wrap: wrap;
height: unset;
.optionBtn {
order: -1;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
}
}
</style>
order 为正值
- 为 模块2 添加 order:1 属性,将其提到最后
- 模块1 和 模块3 仍保持默认的 order: 0,保持在一行不变

html
<style scoped lang="scss">
.titleLine {
flex-wrap: wrap;
height: unset;
.subTitles {
order: 1;
}
}
</style>
order 值越大越靠后
- 为 模块2 添加 order:2 属性,将其提到最后,并改变 width 属性,使其独占一行
- 为 模块3 添加 order:1 属性,将其提到 模块2 之前,并改变 width 属性,使其独占一行
- 模块1 和 模块4 仍保持默认的 order: 0,保持在一行不变

html
<div class="titleLine">
<div class="mainTitle">主要标题</div>
<div class="subTitles subTitles1">
<div class="sinText">小标题1</div><div class="sinText">小标题2</div><div class="sinText">小标题3</div>
</div>
<div class="subTitles subTitles2">
<div class="sinText">小标题4</div><div class="sinText">小标题5</div>
</div>
<div class="optionBtn">操作按钮 ></div>
</div>
<style scoped lang="scss">
.titleLine {
flex-wrap: wrap;
height: unset;
.subTitles1 {
flex-grow: unset;
order: 2;
width: 100%;
}
.subTitles2 {
flex-grow: unset;
order: 1;
width: 100%;
}
}
</style>
完整代码
html
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
const flexBoxRef = ref<HTMLElement | null>(null); // 盒子
let boxWidth = ref(0); // 盒子宽
onMounted(() => {
handleResize(); // 默认执行-获取宽度
window.addEventListener("resize", handleResize); // 宽度变化监听
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize); // 销毁移除事件
});
// 处理逻辑
function handleResize() {
boxWidth.value = flexBoxRef.value ? flexBoxRef.value.clientWidth : 0;
}
</script>
<template>
<div ref="flexBoxRef" :class="['flexBox', boxWidth <= 500 ? 'hasOrder' : '']">
<div class="watchLine">当前 flexBox 的宽度为:{{ boxWidth }}px</div>
<div class="sinBox sinBox1">
<div class="titleLine">
<div class="mainTitle">主要标题</div>
<div class="subTitles">
<div class="sinText">小标题1</div>
<div class="sinText">小标题2</div>
<div class="sinText">小标题3</div>
</div>
<div class="optionBtn">操作按钮 ></div>
</div>
<div class="content">
<p>order 是负值</p>
<p>把该元素提到最前边</p>
<p>剩余元素仍在一行</p>
</div>
</div>
<div class="sinBox sinBox2">
<div class="titleLine">
<div class="mainTitle">主要标题</div>
<div class="subTitles">
<div class="sinText">小标题1</div>
<div class="sinText">小标题2</div>
<div class="sinText">小标题3</div>
</div>
<div class="optionBtn">操作按钮 ></div>
</div>
<div class="content">
<p>order 是正值</p>
<p>把该元素提到后边</p>
</div>
</div>
<div class="sinBox sinBox3">
<div class="titleLine">
<div class="mainTitle">主要标题</div>
<div class="subTitles subTitles1">
<div class="sinText">小标题1</div>
<div class="sinText">小标题2</div>
<div class="sinText">小标题3</div>
</div>
<div class="subTitles subTitles2">
<div class="sinText">小标题4</div>
<div class="sinText">小标题5</div>
</div>
<div class="optionBtn">操作按钮 ></div>
</div>
<div class="content">
<p>order 值越大越靠后</p>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.flexBox {
background: #fff;
padding: 10px;
.watchLine {
margin-bottom: 40px;
font-size: 20px;
font-weight: bold;
}
.sinBox {
margin-bottom: 20px;
border: 1px solid #ccc;
.titleLine {
height: 40px;
padding: 0 20px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
.mainTitle {
font-size: 20px;
font-weight: bold;
flex-shrink: 0;
}
.subTitles {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: flex-end;
.sinText {
margin-left: 10px;
}
}
.optionBtn {
font-size: 16px;
color: #666;
margin-left: 20px;
flex-shrink: 0;
}
}
.content {
border-top: 1px solid #ccc;
background: #f7f7f7;
padding: 20px;
box-sizing: border-box;
p {
margin: 0;
}
}
}
}
.hasOrder {
.sinBox1 {
.titleLine {
flex-wrap: wrap;
height: unset;
.optionBtn {
order: -1;
width: 100%;
text-align: right;
padding-right: 20px;
box-sizing: border-box;
}
}
}
.sinBox2 {
.titleLine {
flex-wrap: wrap;
height: unset;
.subTitles {
order: 1;
}
}
}
.sinBox3 {
.titleLine {
flex-wrap: wrap;
height: unset;
.subTitles1 {
flex-grow: unset;
order: 2;
width: 100%;
}
.subTitles2 {
flex-grow: unset;
order: 1;
width: 100%;
}
}
}
}
</style>