官方文档地址:
- Vant Tab标签页文档示例
问题描述
在开发中使用
原因是
在移动端适配过程中,开发者通常会采取
解决策略
事实上如果该
但是既然页面问题已经出现了,当时能想到的解决问题的策略有如下几个:
-
生写一个原生的
tabs 标签页这个方案逻辑上的实现难度小到可以忽略,唯一的难点或许是点击未激活
tabs 标题时底部条的动画。如果只是一个页面用到了这个组件,生写一个原生的tabs 似乎并不是一个很划算的选择(即使个人能力能得到锻炼)。 -
修改源码
问题出现的原因已经知道了,修改源码如果能成功的话确实是一个最强势的方案。但是极有可能会导致解决了一个问题又创造了另一个新问题。
-
将
vant-tabs 元素移入.header 将
vant-tabs 元素移入.header ,让.header 元素引导tabs 标题栏的粘性布局。此外要放弃
vant-tabs 预设的内容区默认插槽(就是说不要在van-tab 那个双标签里写标签页内容,默认插槽在页面上的元素类名是.van-tabs__content ),在.header 元素的同级手写一个内容区div 进行每个标签页的展示,通过v-show="active==='a/b/c/d'" 进行切换。这个解决方案是四个方案中最稳定最具性价比的,但是缺点是
vant-tabs 关于标签页内容区的动画效果等附加内容几乎全部被阉割。 -
通过
js 动态获取到.header 元素的实际渲染高度,手动为offset-top 赋值只需要在合适的生命周期函数中拿到想要的高度值,在赋值给
offset-top 后让van-tabs 渲染出来即可。这个方案看起来几乎几乎是完美的,但是具体实现有一个致命的缺陷是在第一次上拉时标题栏大概率出现一次不明原因的瞬间抖动,持续的上拉会引起
.header 的不明原因高频抖动。
解决方案的代码示例
第三个解决方案的代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <template> <div class="container"> <div class="header"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio, a assumenda ratione harum sapiente itaque non perferendis reiciendis, corrupti <van-tabs v-model="active"> <van-tab title="标签 1" name="a"></van-tab> <van-tab title="标签 2" name="b"></van-tab> <van-tab title="标签 3" name="c"></van-tab> <van-tab title="标签 4" name="d"></van-tab> </van-tabs> </div> <div class="tabs-content"> <div v-show="active=='a'"> <span> Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem </span> </div> <div v-show="active=='b'"> <span> bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb </span> </div> <div v-show="active=='c'"> <span> ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc </span> </div> <div v-show="active=='d'"> <span> ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd </span> </div> </div> </div> </template> <script> export default { data() { return { active: 'a' } } } </script> <style scoped> .container { position: relative; height: 100%; overflow: scroll; background-color: lightgreen; background-repeat: no-repeat; background-size: 100%; } .header { background-color: #fff; position: sticky; top: 0; z-index: 999; overflow: hidden; } </style> |
第四个解决方案的代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <template> <div class="container"> <div class="header" ref="header" >Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio, a assumenda ratione harum sapiente itaque non perferendis reiciendis, corrupti sapiente itaque non perferendis reiciendis, corrupti</div> <!-- :offset-top="offsetTop" --> <van-tabs v-if="offsetTop" v-model="active" sticky :offset-top="offsetTop"> <van-tab title="标签 1" name="a"> <div> <span>Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem Lorem</span> </div> </van-tab> <van-tab title="标签 2" name="b"> <div> <span>bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb</span> </div> </van-tab> <van-tab title="标签 3" name="c"> <div> <span>ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc ccccc</span> </div> </van-tab> <van-tab title="标签 4" name="d"> <div> <span>ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd ddddd</span> </div> </van-tab> </van-tabs> </div> </template> <script> export default { data() { return { active: 'a', offsetTop: '' } }, mounted() { console.log(this.$refs.header.offsetHeight); this.offsetTop = this.$refs.header.offsetHeight } } </script> <style scoped> .container { position: relative; height: 100%; overflow: scroll; background-color: lightgreen; background-repeat: no-repeat; background-size: 100%; } .header { background-color: #fff; height: 200px; position: sticky; top: 0; z-index: 999; overflow: hidden; } </style> |
支线
笔者在工程中用的适配插件是
在写这篇文章时产生了一个疑问,为什么
如果能让适配插件对动态赋值的像素单位进行转换,或许能从根本上解决这一问题。