uniapp 动态组件实现Tabs标签切换组件(喜马拉雅app作为案例)
uniapp 动态组件实现Tabs标签切换组件
一、功能描述
拿喜马拉雅app作为案例,它的tabs标签有很多,如:推荐、小说、儿童等等。用户点击小说就会切换到小说组件,如果仔细看第一次是有一个加载的过程,如果你再返回到推荐页,再次点击小说时就没有加载过程,而是直接显示出来。
这就有两个知识点
(1)动态组件切换 (vue3 中 component组件 is属性)(2)保持组件被移除时的状态(vue3 中是 KeepAlive)
二、在uniapp中实现动态组件切换需看uniapp是否支持
从官方文档看到,component是支持 App 和 H5的(我实在app上实现的),而keepAlive只支持H5
<template> <!-- 标签数据 --> <u-tabs class="tabsBox" :list="tabData" @click="changeTab" :scrollable="false" lineColor="#000" :activeStyle="{color: '#000',fontWeight: 'bold',transform: 'scale(1.05)'}" :inactiveStyle="{color: '#000'}" ></u-tabs> <!-- 组件切换 --> <component :is="tabData[current].comName"></component> </template> <script setup> import {ref,reactive,onMounted,markRaw} from 'vue'; import A from "./a.vue"; import B from "./b.vue"; import C from "./c.vue"; let tabData = reactive([ {name: '体育',comName:markRaw(A)}, {name: '经济',comName:markRaw(B)}, {name: 'IT信息',comName:markRaw(C)} ]); //切换标签事件 let current = ref(0); const changeTab = (obj)=>{ current.value = obj.index; } </script>
解释一下:
(1)u-tabs 是 uview-plus 里面的标签组件
(2)markRaw 将一个对象标记为不可被转为代理。返回该对象本身,不然用响应式的ref 会报出警告
关于如何保持组件被移除时的状态,我也在寻找方案
uniapp实现tab分类切换
<template> <view class="content"> <view class="nav"> <!-- 选项卡水平方向滑动,scroll-with-animation是滑动到下一个选项时,有一个延时效果 --> <scroll-view class="tab-scroll" scroll-x="true" scroll-with-animation :scroll-left="scrollLeft"> <view class="tab-scroll_box"> <!-- 选项卡类别列表 --> <view class="tab-scroll_item" v-for=" (item,index) in category" :key="index" :class="{'active':isActive==index}" @click="chenked(index)"> {{item.name}} </view> </view> </scroll-view> </view> <!-- 选项卡内容轮播滑动显示,current为当前第几个swiper子项 --> <swiper @change="change" :current="isActive" class="swiper-content" :style="fullHeight"> <swiper-item class="swiperitem-content"> <scroll-view scroll-y style="height: 100%;"> <view class="nav_item" v-for="(item,index) in add":key="index" > <view class=""> {{item.name}} </view> <view class=""> {{item.num}} </view> <view class=""> {{item.pink}} </view> </view> </scroll-view> </swiper-item> </swiper> </view> </template> <script> export default { watch:{ // swiper与上面选项卡联动 currentindex(newval){ this.isActive = newval; this.scrollLeft = 0; // 滑动swiper后,每个选项距离其父元素最左侧的距离 for (let i = 0; i < newval - 1; i++) { this.scrollLeft += this.category[i].width }; }, }, data() { return { isActive: 0, index: 0, currentindex:0, category:[ { id:1, name:'选项卡一', }, { id:2, name:'选项卡二', }, { id:3, name:'选项卡三', }, { id:4, name:'选项卡四', }, { id:5, name:'选项卡五', }, { id:6, name:'选项卡六', }, ], contentScrollW: 0, // 导航区宽度 scrollLeft: 0, // 横向滚动条位置 fullHeight:"", arr:[ { name:'123444', num:'dfrgthh', pink:'1000', type:1 },{ name:'kkkkkkkk', num:'dfrgthh', pink:'1000', type:1 },{ name:'123444', num:'dfrgthh', pink:'1000', type:1 },{ name:'vvvvvvvv', num:'dfrgthh', pink:'1000', type:2 },{ name:'aaaaaaaaa', num:'dfrgthh', pink:'1000', type:3 },{ name:'gggggggg', num:'dfrgthh', pink:'1000', type:5 },{ name:'ddddddd', num:'dfrgthh', pink:'1000', type:5 }, ], add:[] } }, mounted() { var that = this; //获取手机屏幕的高度,让其等于swiper的高度,从而使屏幕充满 uni.getSystemInfo({ success: function (res) { that.fullHeight ="height:" + res.windowHeight + "px"; } }); // 获取标题区域宽度,和每个子元素节点的宽度 this.getScrollW() }, methods: { // 获取标题区域宽度,和每个子元素节点的宽度以及元素距离左边栏的距离 getScrollW() { const query = uni.createSelectorQuery().in(this); query.select('.tab-scroll').boundingClientRect(data => { // 拿到 scroll-view 组件宽度 this.contentScrollW = data.width }).exec(); query.selectAll('.tab-scroll_item').boundingClientRect(data => { let dataLen = data.length; for (let i = 0; i < dataLen; i++) { // scroll-view 子元素组件距离左边栏的距离 this.category[i].left = data[i].left; // scroll-view 子元素组件宽度 this.category[i].width = data[i].width } }).exec() }, // 当前点击子元素靠左留一个选项展示,子元素宽度不相同也可实现 chenked(index) { if(index == 0){ this.add = this.arr }else{ let ass = [] for(let i in this.arr){ if(this.arr[i].type == index){ ass.push(this.arr[i]) } } this.add =ass } console.log(this.add); // this.isActive = index; // this.scrollLeft = 0; // for (let i = 0; i < index - 1; i++) { // this.scrollLeft += this.category[i].width // }; }, // swiper滑动时,获取其索引,也就是第几个 change(e){ const {current} = e.detail; this.currentindex = current; }, } } </script> <style lang="scss"> page{ height: 100%; display: flex; background-color: #FFFFFF; } .content{ display: flex; flex-direction: column; width: 100%; flex: 1; .nav{ border-top: 1rpx solid #f2f2f2; background-color: #fceeee; position: fixed; z-index: 99; width: 100%; align-items: center; height: 100rpx; .tab-scroll{ flex: 1; overflow: hidden; box-sizing: border-box; padding-left: 30rpx; padding-right: 30rpx; .tab-scroll_box{ display: flex; align-items: center; flex-wrap: nowrap; box-sizing: border-box; .tab-scroll_item{ line-height: 60rpx; margin-right: 35rpx; flex-shrink: 0; padding-bottom:10px; display: flex; justify-content: center; font-size: 16px; padding-top: 10px; } } } } .swiper-content{ padding-top: 120rpx; flex: 1; .swiperitem-content{ background-color: #ffffff; .nav_item{ background-color: #FFFFFF; padding:20rpx 40rpx 0rpx 40rpx ; } } } } .active { position: relative; color: #ff0000; font-weight: 600; } .active::after { content: ""; position: absolute; width: 130rpx; height: 4rpx; background-color: #ff0000; left: 0px; right: 0px; bottom: 0px; margin: auto; } /* 隐藏滚动条,但依旧具备可以滚动的功能 */ /deep/.uni-scroll-view::-webkit-scrollbar { display: none } </style>
到此这篇关于uniapp 动态组件实现Tabs标签切换组件的文章就介绍到这了,更多相关uniapp Tabs标签切换组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
浅谈js对象属性 通过点(.) 和方括号([]) 的不同之处
下面小编就为大家带来一篇浅谈js对象属性 通过点(.) 和方括号([]) 的不同之处。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2016-10-10Google Suggest ;-) 基于js的动态下拉菜单
Google Suggest ;-) 基于js的动态下拉菜单...2006-10-10
最新评论