原理:
1、利用float定位的元素的特点,float定位的元素允许文本和行内元素围绕;
2、float定位的元素会脱离文档流,即块状元素的位置不受float定位元素的影响;
思路:
1、对更多按钮和省略号(即展开按钮)设置float:right定位,此时展开按钮会浮在盒子的右上角;盒子中所有文本的行高一致;
2、思考如何让展开按钮浮动到右下角?由于浮动定位的元素不会影响块状元素,那么就可以在盒子的最上方放置一个块状元素,高度刚好为文字两行的高度,即可以将展开按钮挤到到右下角。
3、此时文字也会被块状元素挤下来,对文字设置margin-top的负值,即可让文字回到原位置。注意,此时的文字所在的盒子其实与块状元素时重合的,所以最好设置块状元素的背景色为透明。
展开收起效果图如下:
代码:
<template>
<div class="ellipsis-box" :class="[folder ? '' : 'auto']">
<template v-if="folder">
<div class="more" @click="toggleFolder">更多</div>
<div class="ellipsis">...</div>
</template>
<div class="ellipsis-text" ref="ellipsisRef">
本文的前端轮询主要讨论的是定时异步任务,定时异步任务相比与定时同步任务需要考虑更多的因素。这里的异步任务一般包括发送网络请求及响应后的状态更新。从技术层面上,需要考虑到开启定时、发送请求、状态更新之间的逻辑顺序。此外,本文不讨论利用websocket做服务端推送,只考虑在仅前端变更的情况下做轮询(在某些时候,确实只能如此)。
<span v-if="!folder && isOpenFolder" class="unfolder" @click="toggleFolder">收起</span>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue"
const ellipsisRef = ref<HTMLElement>()
const folder = ref<boolean>(false)
const isOpenFolder = ref<boolean>(false)
const toggleFolder = () => {
folder.value = !folder.value
}
const checkIsFolder = () => {
if(ellipsisRef.value.clientHeight > 90) {
folder.value = true
isOpenFolder.value = true
}
}
onMounted(() => {
checkIsFolder()
})
</script>
<style lang="scss" scoped>
.ellipsis-box {
width: 400px;
height: 90px;
line-height: 30px;
overflow: hidden;
&.auto {
height: auto;
}
.more, .ellipsis {
float: right;
}
.more, .unfolder {
color: #007fff;
cursor: pointer;
}
.ellipsis {
margin-right: 10px;
}
.ellipsis-text {
margin-top: -60px;
text-align: justify;
}
&::before {
content: "";
display: block;
width: 100%;
height: 60px;
}
}
</style>