接上篇内容。继续添加内容。
以下方案建立在App.vue设置了flex布局。
<template>
<view style="flex: auto; background-color: red">
<view style="bottom: 0">我固定在底部view>
view>
template>
我试着向上面这样添加一个底部工具栏,但是发现不行bottom: 0
无法生效。
于是我想到用position: absolute做绝对定位:
<template>
<view style="flex: auto; background-color: red">
<view style="position: absolute; bottom: 0px">我固定在底部view>
view>
template>
这样就可以了,因为position: absolute;
是在父元素的束缚下进行绝对定位的,这样就是我想要的效果。
那我继续添加一些内容,看看会不会影响到它:
<template>
<view style="flex: auto; background-color: red">
<view>干扰一view>
<view style="position: absolute; bottom: 0px">我固定在底部view>
<view>干扰二view>
view>
template>
可以发现,不管我在它上面还是下面添加元素,都不影响它:
继续加大难度,给元素增加高度满屏高度,看看会不会挤压它:
<template>
<view style="flex: auto; background-color: red">
<view style="height: 100%">干扰一view>
<view style="position: absolute; bottom: 0px">我固定在底部view>
<view>干扰二view>
view>
template>
可以发现,底部元素纹丝不动,但是“干扰二”不见了,调试发现:
它被挤到下面去了,但是因为底部导航栏是顶层元素,所以将他覆盖了。这也正常。目前测试功能很好。absolute的解析看这篇
也可以像下面的顺序放置,效果也一样(变化了一下父级关系):
<template>
<view style="flex: auto; background-color: red">干扰一view>
<view style="position: absolute; bottom: 0px">我固定在底部view>
template>
上面方案是使用absolute,效果很好。我发现还有一种方案,也记录一下:
<template>
<view style="flex: auto; background-color: red">干扰一view>
<view style="bottom: 0px">我固定在底部view>
template>
与上面的不同是去掉了position: absolute;
:
发现,一样可以让其固定在底部,但是它的底色就不是红色了。这时候就体现出absolute的层次效果了。因为absolute会让它“隐身”,上面的元素感知不到它的存在,所以红色理所应当的把全屏占掉了。但是不用的话,两组元素是并存的关系。所以底部元素占用的位置不会被红色侵占。
这种方式依赖“flex: auto; ”,这会让元素占满父元素剩余空间。
我给它添加一些干扰,看看是否会影响底部元素的位置:
<template>
<view style="flex: auto; background-color: red; height: 200px">干扰一view>
<view style="bottom: 0px; height: 50px">我固定在底部view>
template>
可以看到,我给上面的元素设置的高度超过了它可占用的空间,然后底部元素和它都被一定程度压缩了。
这是因为flex布局的默认值是:当父元素空间小于子元素空间之和时(空间指的长度或者宽度),会进行等比缩小。所以只需要设置底部元素不缩小即可。这个flex
的默认值是0 1 auto
。第一个值表示放大的比例,第二个表示缩小的比例,都设置为0就不放大也不缩小了。auto就去看这篇解析吧,所以只需要设置成flex:0 0 auto
。这样就不受影响了:
<template>
<view style="flex: auto; background-color: red; height: 200px">干扰一view>
<view style="flex: none; bottom: 0px; height: 50px">我固定在底部view>
template>
这里面:flex: auto
等于flex:1 1 auto
。flex: none;
等于flex: 0 0 auto
。
所以这种方案也是可行的。
但是,这种方案并不稳定,如果上面的元素包含的子元素高度大于了其本身,就会改变它的高度。导致底部元素被压缩:
<template>
<view style="flex: auto; background-color: red; height: 200px">
<view style="height: 180px; background-color: blue"> 干扰一 view>
view>
<view style="flex: none; bottom: 0px; height: 50px">我固定在底部view>
template>
因为“干扰一” 的布局是display: block;
。这么看来,这种方案不如第一个稳定。还是会被其他布局的元素给影响。
当然也有解决方案,给上面的元素添加overflow
属性。可以选择将超出部分被裁减,也可以变成滚动区域,但是,它需要父元素指定高度。
下面这种方式不行(最外层view的父元素是flex布局,且指定了height: 100%;
),即使使用flex: auto;
占满高度也是不行的。子元素超过父元素高度会导致滚动贯穿。
<template>
<view style="flex: auto; display: flex; flex-direction: column">
<view style="flex: auto; background-color: red; height: 200px; overflow: auto">
<view style="height: 180px; background-color: blue"> 干扰一 view>
view>
<view style="flex: none; bottom: 0px; height: 50px">我固定在底部view>
view>
template>
需要在父元素指定高度:
<template>
<view style="height: 100%; display: flex; flex-direction: column">
<view style="flex: auto; background-color: red; height: 200px; overflow: auto">
<view style="height: 180px; background-color: blue"> 干扰一 view>
view>
<view style="flex: none; bottom: 0px; height: 50px">我固定在底部view>
view>
template>
对比上面就把flex: auto
换成height: 100%
,可以使用相对高度,所以也能接受。
第一种方案,它的特点是上面的元素始终占满整个可用空间,包括底部元素的空间,只是底部元素位于它的上面一层,所以不会被其遮挡,对于上面的元素而言,它是感知不到底部元素的存在的。
第二种方案,上面的元素和底部元素是并存的,是可以相互感知到彼此的存在。这样,上面的元素是能够获取到自己真实的高度。当然,底部元素也依赖于上面元素占用剩余空间,才会把自己的位置定死在底部。就稳定性而言,第一种更好。