首页 > 其他分享 >uniapp vue3 虚拟下拉滚动

uniapp vue3 虚拟下拉滚动

时间:2024-06-20 14:24:06浏览次数:22  
标签:uniapp 滚动 name vue3 startIndex state props const itemSize

下面是vue3的写法   如果想查看vue2的写法   请移步至github链接    https://github.com/Arvin-Cui/vue-virtual-scroll/blob/master/pages/index/index.vue
1.index.vue    index.vue页面中加一个共用组件VirtualList.vue
<template>   <view>     <VirtualList :listData="state.dateList" :itemSize="100"></VirtualList>   </view> </template>   <script setup lang="ts"> import { reactive } from 'vue' import { onShow } from '@dcloudio/uni-app' const state = reactive({   dateList: [] }) onShow(() => {   inits() }) const inits = () => {   state.dateList = [     { name: 1 },{ name: 2 }, { name: 3 }, { name: 4 },{ name: 5 }, { name: 6 }, { name: 7 },{ name: 8 },{ name: 9 }, { name: 10 },     { name: 11 },{ name: 12 },{ name: 13 },{ name: 14 },{ name: 15 },{ name: 16 },{ name: 17 },{ name: 18 },{ name: 19 },{ name: 20 },     { name: 21 },{ name: 22 },{ name: 23 },{ name: 24 },{ name: 25 },{ name: 26 },{ name: 27 },{ name: 28 },{ name: 29 },{ name: 30 },     { name: 31 },{ name: 32 },{ name: 33 },{ name: 34 },{ name: 35 },{ name: 36 },{ name: 37 },{ name: 38 },{ name: 39 },{ name: 40 },     { name: 41 },{ name: 42 },{ name: 43 },{ name: 44 },{ name: 45 },{ name: 46 },{ name: 47 },{ name: 48 },{ name: 49 },{ name: 50 },     { name: 51 },{ name: 52 },{ name: 53 },{ name: 54 },{ name: 55 },{ name: 56 },{ name: 57 },{ name: 58 },{ name: 59 },{ name: 60 },     { name: 61 },{ name: 62 },{ name: 63 },{ name: 64 },{ name: 65 },{ name: 66 },{ name: 67 },{ name: 68 },{ name: 69 },{ name: 70 },     { name: 71 },{ name: 72 },{ name: 73 },{ name: 74 },{ name: 75 },{ name: 76 },{ name: 77 },{ name: 78 },{ name: 79 },{ name: 80 },     { name: 81 },{ name: 82 },{ name: 83 },{ name: 84 },{ name: 85 },{ name: 86 },{ name: 87 },{ name: 88 },{ name: 89 },{ name: 90 },  { name: 91 },{ name: 92 },{ name: 93 },{ name: 94 },{ name: 95 },{ name: 96 },{ name: 97 },{ name: 98 }, { name: 99 },{ name: 100 },  { name: 101 },{ name: 102 }, { name: 103 }, { name: 104 },{ name: 105 }, { name: 106 }, { name: 107 },{ name: 108 },{ name: 109 }, { name: 110 },     { name: 111 },{ name: 112 },{ name: 113 },{ name: 114 },{ name: 115 },{ name: 116 },{ name: 117 },{ name: 118 },{ name: 119 },{ name: 120 },     { name: 121 },{ name: 122 },{ name: 123 },{ name: 124 },{ name: 125 },{ name: 126 },{ name: 127 },{ name: 128 },{ name: 129 },{ name: 130 },     { name: 131 },{ name: 132 },{ name: 133 },{ name: 134 },{ name: 135 },{ name: 136 },{ name: 137 },{ name: 138 },{ name: 139 },{ name: 140 },     { name: 141 },{ name: 142 },{ name: 143 },{ name: 144 },{ name: 145 },{ name: 146 },{ name: 147 },{ name: 148 },{ name: 149 },{ name: 150 },     { name: 151 },{ name: 152 },{ name: 153 },{ name: 154 },{ name: 155 },{ name: 156 },{ name: 157 },{ name: 158 },{ name: 159 },{ name: 160 },     { name: 161 },{ name: 162 },{ name: 163 },{ name: 164 },{ name: 165 },{ name: 166 },{ name: 167 },{ name: 168 },{ name: 169 },{ name: 170 },     { name: 171 },{ name: 172 },{ name: 173 },{ name: 174 },{ name: 175 },{ name: 176 },{ name: 177 },{ name: 178 },{ name: 179 },{ name: 180 },     { name: 181 },{ name: 182 },{ name: 183 },{ name: 184 },{ name: 185 },{ name: 186 },{ name: 187 },{ name: 188 },{ name: 189 },{ name: 190 },  { name: 191 },{ name: 192 },{ name: 193 },{ name: 194 },{ name: 195 },{ name: 196 },{ name: 197 },{ name: 198 }, { name: 199 },{ name: 200 },   ] } </script> <style lang="scss" scoped> </style>   2.VirtualList.vue 页面  逻辑都在这个页面
    <template>   <view class="content">     <!-- 使用 scroll-view 组件来实现滚动 -->     <scroll-view       ref="list"       scroll-y="true"       class="list-container"       @scroll="handleScroll"       style="height: 100vh"       :scroll-top="state.startOffset"     >       <view class="list-phantom" :style="{ height: listHeight + 'px' }"></view>       <view class="list" :style="{ transform: getTransform }">         <view           v-for="(item, index) in visibleData"           class="list-item"           :key="index"           :style="{ height: props.itemSize + 'px', lineHeight: props.itemSize + 'px' }"         >           {{ item.name }}         </view>       </view>     </scroll-view>   </view> </template> <script setup lang="ts"> import { reactive, onMounted, computed } from 'vue' import { debounce } from '@/utils/tools' const state = reactive({   listHeight: 0,   screenHeight: 0, // 屏幕高度即可视区域高度   startOffset: 0, // 顶部偏移量   startIndex: 0, // 可视化区域的数据开始下标   endIndex: 0 // 可视化区域的数据结束下标 }) const props = defineProps({   listData: {     type: Array,     default: () => []   },   //每项高度   itemSize: {     type: Number,     default: 200   } }) const listHeight = computed(() => {   return props.listData.length * props.itemSize }) const visibleCount = computed(() => {   return Math.ceil(state.screenHeight / props.itemSize) || 0 }) const getTransform = computed(() => {   return 'translate3d(0,' + state.startOffset + 'px,0)' }) const visibleData = computed(() => {   return props.listData.slice(state.startIndex, Math.min(state.endIndex, props.listData.length)) }) onMounted(() => {   console.log(props.listData)   init() }) const init = () => {   getScreenHeight()   // 设置初始滚动距离  state.startIndex = 0   如果不是从第一个开始滚动 num为第几个开始  state.startIndex = num  state.startOffset = num * props.itemSize   //   state.startIndex = 0   state.startIndex = 20   state.startOffset = 20 * props.itemSize   state.endIndex = state.startIndex + visibleCount.value }   // 获取屏幕高度即可视化区域高度 const getScreenHeight = () => {   uni.getSystemInfo({     success: function (res) {       state.screenHeight = res.screenHeight     }   }) } // 防抖 节流方法   debounce第三个参数没用  可以删除 const debounce= (fn, delay,_this) => {   vardelay = delay || 200 var timer = null return function () { let self = _this || this let args = arguments timer && clearTimeout(timer) timer = setTimeout(function () { timer = null fn.apply(self, args)     }, delay)   } } const handleScroll = debounce(   (e) => {     //当前滚动位置     let scrollTop = e.detail.scrollTop     //开始索引     state.startIndex = Math.floor(scrollTop / props.itemSize)     //结束索引     state.endIndex = state.startIndex + visibleCount.value     //顶部偏移量     state.startOffset = scrollTop - (scrollTop % props.itemSize)   },   10,   '' ) </script> <style lang="scss" scoped> .list-container {   height: 100%;   overflow: auto;   position: relative;   .list-phantom {     position: absolute;     left: 0;     top: 0;     right: 0;     z-index: -1;   }   .list {     left: 0;     right: 0;     top: 0;     position: absolute;     .list-item {       text-align: center;       border-bottom: 1px solid #ccc;     }   } } </style>    最终效果图

 

 

    <template>   <view class="content">     <!-- 使用 scroll-view 组件来实现滚动 -->     <scroll-view       ref="list"       scroll-y="true"       class="list-container"       @scroll="handleScroll"       style="height: 100vh"       :scroll-top="state.startOffset"     >       <view class="list-phantom" :style="{ height: listHeight + 'px' }"></view>       <view class="list" :style="{ transform: getTransform }">         <view           v-for="(item, index) in visibleData"           class="list-item"           :key="index"           :style="{ height: props.itemSize + 'px', lineHeight: props.itemSize + 'px' }"         >           {{ item.name }}         </view>       </view>     </scroll-view>   </view> </template> <script setup lang="ts"> import { reactive, ref, onMounted, computed } from 'vue' import { onShow } from '@dcloudio/uni-app' import { debounce } from '@/utils/tools'
const state = reactive({   totalList: [],   listHeight: 0,   screenHeight: 0, // 屏幕高度即可视区域高度   startOffset: 0, // 顶部偏移量   startIndex: 0, // 可视化区域的数据开始下标   endIndex: 0 // 可视化区域的数据结束下标 }) const props = defineProps({   listData: {     type: Array,     default: () => []   },   //每项高度   itemSize: {     type: Number,     default: 200   } }) const listHeight = computed(() => {   return props.listData.length * props.itemSize }) const visibleCount = computed(() => {   return Math.ceil(state.screenHeight / props.itemSize) || 0 }) const getTransform = computed(() => {   return 'translate3d(0,' + state.startOffset + 'px,0)' }) const visibleData = computed(() => {   return props.listData.slice(state.startIndex, Math.min(state.endIndex, props.listData.length)) }) onMounted(() => {   console.log(props.listData)   init() }) const init = () => {   state.totalList = [     { name: 1 },     { name: 2 },     { name: 3 },     { name: 4 },     { name: 5 },     { name: 6 },     { name: 7 },     { name: 8 },     { name: 9 },     { name: 10 },     { name: 11 },     { name: 12 },     { name: 13 },     { name: 14 },     { name: 15 },     { name: 16 },     { name: 17 },     { name: 18 },     { name: 19 },     { name: 20 },     { name: 21 },     { name: 22 },     { name: 23 },     { name: 24 },     { name: 25 },     { name: 26 },     { name: 27 },     { name: 28 },     { name: 29 },     { name: 30 },     { name: 31 },     { name: 32 },     { name: 33 },     { name: 34 },     { name: 35 },     { name: 36 },     { name: 37 },     { name: 38 },     { name: 39 },     { name: 40 },     { name: 41 },     { name: 42 },     { name: 43 },     { name: 44 },     { name: 45 },     { name: 46 },     { name: 47 },     { name: 48 },     { name: 49 },     { name: 50 },     { name: 51 },     { name: 52 },     { name: 53 },     { name: 54 },     { name: 55 },     { name: 56 },     { name: 57 },     { name: 58 },     { name: 59 },     { name: 60 },     { name: 61 },     { name: 62 },     { name: 63 },     { name: 64 },     { name: 65 },     { name: 66 },     { name: 67 },     { name: 68 },     { name: 69 },     { name: 70 },     { name: 71 },     { name: 72 },     { name: 73 },     { name: 74 },     { name: 75 },     { name: 76 },     { name: 77 },     { name: 78 },     { name: 79 },     { name: 80 },     { name: 81 },     { name: 82 },     { name: 83 },     { name: 84 },     { name: 85 },     { name: 86 },     { name: 87 },     { name: 88 },     { name: 89 },     { name: 90 },     { name: 91 },     { name: 92 },     { name: 93 },     { name: 94 },     { name: 95 },     { name: 96 },     { name: 97 },     { name: 98 },     { name: 99 },     { name: 100 },
    { name: 101 },     { name: 102 },     { name: 103 },     { name: 104 },     { name: 105 },     { name: 106 },     { name: 107 },     { name: 108 },     { name: 109 },     { name: 110 },     { name: 111 },     { name: 112 },     { name: 113 },     { name: 114 },     { name: 115 },     { name: 116 },     { name: 117 },     { name: 118 },     { name: 119 },     { name: 120 },     { name: 121 },     { name: 122 },     { name: 123 },     { name: 124 },     { name: 125 },     { name: 126 },     { name: 127 },     { name: 128 },     { name: 129 },     { name: 130 },     { name: 131 },     { name: 132 },     { name: 133 },     { name: 134 },     { name: 135 },     { name: 136 },     { name: 137 },     { name: 138 },     { name: 139 },     { name: 140 },     { name: 141 },     { name: 142 },     { name: 143 },     { name: 144 },     { name: 145 },     { name: 146 },     { name: 147 },     { name: 148 },     { name: 149 },     { name: 150 },     { name: 151 },     { name: 152 },     { name: 153 },     { name: 154 },     { name: 155 },     { name: 156 },     { name: 157 },     { name: 158 },     { name: 159 },     { name: 160 },     { name: 161 },     { name: 162 },     { name: 163 },     { name: 164 },     { name: 165 },     { name: 166 },     { name: 167 },     { name: 168 },     { name: 169 },     { name: 170 },     { name: 171 },     { name: 172 },     { name: 173 },     { name: 174 },     { name: 175 },     { name: 176 },     { name: 177 },     { name: 178 },     { name: 179 },     { name: 180 },     { name: 181 },     { name: 182 },     { name: 183 },     { name: 184 },     { name: 185 },     { name: 186 },     { name: 187 },     { name: 188 },     { name: 189 },     { name: 190 },     { name: 191 },     { name: 192 },     { name: 193 },     { name: 194 },     { name: 195 },     { name: 196 },     { name: 197 },     { name: 198 },     { name: 199 },     { name: 200 }   ]   getScreenHeight()   // 设置初始滚动距离  state.startIndex = 0   如果不是从第一个开始滚动 num为第几个开始  state.startIndex = num  state.startOffset = num * props.itemSize   //   state.startIndex = 0   state.startIndex = 20   state.startOffset = 20 * props.itemSize   state.endIndex = state.startIndex + visibleCount.value }
// 获取屏幕高度即可视化区域高度 const getScreenHeight = () => {   uni.getSystemInfo({     success: function (res) {       state.screenHeight = res.screenHeight     }   }) } const handleScroll = debounce(   (e) => {     //当前滚动位置     let scrollTop = e.detail.scrollTop     //开始索引     state.startIndex = Math.floor(scrollTop / props.itemSize)     //结束索引     state.endIndex = state.startIndex + visibleCount.value     //顶部偏移量     state.startOffset = scrollTop - (scrollTop % props.itemSize)   },   10,   '' ) </script> <style lang="scss" scoped> .list-container {   height: 100%;   overflow: auto;   position: relative;   .list-phantom {     position: absolute;     left: 0;     top: 0;     right: 0;     z-index: -1;   }   .list {     left: 0;     right: 0;     top: 0;     position: absolute;     .list-item {       text-align: center;       border-bottom: 1px solid #ccc;     }   } } </style>

标签:uniapp,滚动,name,vue3,startIndex,state,props,const,itemSize
From: https://www.cnblogs.com/dreammiao/p/18258506

相关文章

  • 需求:添加item后自动滚动到容器底部(如果有滚动条)
    大巧不工,用了原生js<template><divclass="app-container"><divclass="box"><divv-for="(item,index)incount":key="index"class="item">{{item}}</div>......
  • Vue3 状态管理 - Pinia,超详细讲解!
    前言:哈喽,大家好,我是前端菜鸟的自我修养!今天给大家分享【Vue3状态管理-Pinia】,超详细讲解!并提供具体代码帮助大家深入理解,彻底掌握!原创不易,如果能帮助到带大家,欢迎收藏+关注哦......
  • vue3的computed计算属性返回值注解
    //语法结构:computed<返回值的类型>()列子//定义数据constcuont=ref(0)typeItem={id:stringname:stringprice:number}constlist=ref<Item[]>([{id:'1001',name:'男鞋',price:888},{id:'1002',name:'女鞋......
  • vue3的defineProps接收类型注解
    //这是没有用ts语法接收的props参数defineProps({color:String,size:{type:String,required:false,default:'middle'},})//TS语法//格式:withDefaults(defineProps<类型>(),{默认值名:默认值})第一种写法:withDefa......
  • 基于SpringBoot+Vue+uniapp的社区门诊管理系统的详细设计和实现(源码+lw+部署文档+讲
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的校园二手交易平台的详细设计和实现(源码+lw+部署文档+讲
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • vue3标签模板上的ref类型注解
    子组件<scriptsetuplang="ts">import{ref,defineExpose}from'vue';constnum=ref<number>(10)defineExpose({num,//把值暴露出去,父级可以通过ref获取})</script><template><h1>我是组件</h1></template&g......
  • 用Python的pynput库追踪每一次点击和滚动
    哈喽,大家好,我是木头左!在编程的世界里,有时需要洞察用户的行为模式,尤其是在游戏开发、用户界面设计或者行为分析等领域。一个常见而有趣的任务是追踪鼠标的活动,比如左键点击、右键点击和滚轮滚动。今天,将探索如何使用Python的pynput库来实现这一功能,从而开启对用户交互行为的洞察......
  • nuxt3+vue3+vite+TS实现国际化
    前言博主最近打算用Nuxt3重构了自己SSR博客,打算添加国际化功能,众所周知,实现国际化已是一个很常见的功能。用户可以根据自己的喜好,设置页面的自己合适的语言,从而实现国际化浏览。这样用户体验度会大大提升。博客用的nuxt3+vue3+vite+TS实现国际化,国际化用的vue-i18n,下面我给大......
  • Vue3如何绑定全局方法和变量
    Vue2中Vue.prototype绑定全局方法,此写法在Vue3已经不存在了。与任何全局的东西一样,应该谨慎使用。Vue3使用provide/inject或者app.config.globalProperties进行绑定如果全局属性与组件自己的属性冲突,组件自己的属性将具有更高的优先级。 一、provide/inject方法......