当前位置:   article > 正文

uniapp锚点定位 、自动吸顶、滚动自动选择对应的锚点_使用u-tabs实现滚动,点击跳转到顶部

使用u-tabs实现滚动,点击跳转到顶部

 vue3+uniapp+uview 

vue3 uview框架:https://vkuviewdoc.fsq.pub/components/picker.html

 

  1. <template>
  2. <view class="main">
  3. <view class="mt25 all-menu box-shadow border-radius5">
  4. <text class="title mb10">全部菜单</text>
  5. <view class="x-p-titleList">
  6. <u-sticky>
  7. <!-- 只能有一个根元素 -->
  8. <view class="sticky">
  9. <u-tabs :list="dataList" :is-scroll="true" v-model="current" @change="change">
  10. </u-tabs>
  11. </view>
  12. </u-sticky>
  13. <scroll-view class="scroller mt5" :scroll-into-view="toView" scroll-y="true"
  14. scroll-with-animation="true">
  15. <view class="x-p-listItem" v-for="item in dataList" :key="item.id" :id="item.id">
  16. <u-line color="#bbbbbb" />
  17. <view class="mt5 mb5">{{item.name}}</view>
  18. <view v-for="info in item.moduleList" :key="info.moduleId"
  19. class="listItem-dtl u-icon-wrap u-row-between">
  20. <view class="u-flex">
  21. <image :src="info.icon"></image>
  22. <text>{{info.label}}</text>
  23. </view>
  24. <view>
  25. <u-button type="primary" class="add-btn" v-if="isAdd">添加</u-button>
  26. <u-button class="add-btn" v-else>已添加</u-button>
  27. </view>
  28. </view>
  29. </view>
  30. </scroll-view>
  31. </view>
  32. </view>
  33. </view>
  34. </template>
  35. <script lang="ts">
  36. import {
  37. ref,
  38. reactive,
  39. onMounted,
  40. } from 'vue'
  41. export default {
  42. setup() {
  43. const keyword = ref('')
  44. // ----------------------------------------
  45. const current = ref(0)
  46. const dataList = reactive([{
  47. id: 'item1',
  48. name: '办公OA',
  49. moduleList: [{
  50. moduleId: '5001',
  51. label: '出差申请',
  52. icon: '../../static/logo.png'
  53. },
  54. {
  55. moduleId: '5002',
  56. label: '加班申请',
  57. icon: '../../static/images/nav_car_apply.png'
  58. },
  59. {
  60. moduleId: '5003',
  61. label: '请假申请',
  62. icon: '../../static/images/nav_car_apply.png'
  63. },
  64. {
  65. moduleId: '5004',
  66. label: '办公用品申请',
  67. icon: '../../static/images/nav_car_apply.png'
  68. }
  69. ]
  70. }, {
  71. id: 'item2',
  72. name: '生产管理',
  73. moduleList: [{
  74. moduleId: '6001',
  75. label: '生产',
  76. icon: '../../static/logo.png'
  77. },
  78. {
  79. moduleId: '6002',
  80. label: '领料',
  81. icon: '../../static/images/nav_car_apply.png'
  82. },
  83. {
  84. moduleId: '6003',
  85. label: '销售出库',
  86. icon: '../../static/images/nav_car_apply.png'
  87. },
  88. {
  89. moduleId: '6004',
  90. label: '销售入库',
  91. icon: '../../static/images/nav_car_apply.png'
  92. },
  93. {
  94. moduleId: '6004',
  95. label: '销售入库',
  96. icon: '../../static/images/nav_car_apply.png'
  97. }
  98. ]
  99. }, {
  100. id: 'item3',
  101. name: '进销存管理',
  102. moduleList: [{
  103. moduleId: '5001',
  104. label: '出差申请',
  105. icon: '../../static/logo.png'
  106. },
  107. {
  108. moduleId: '5002',
  109. label: '加班申请',
  110. icon: '../../static/images/nav_car_apply.png'
  111. },
  112. {
  113. moduleId: '5003',
  114. label: '请假申请',
  115. icon: '../../static/images/nav_car_apply.png'
  116. },
  117. {
  118. moduleId: '5004',
  119. label: '办公用品申请',
  120. icon: '../../static/images/nav_car_apply.png'
  121. }
  122. ]
  123. }, {
  124. id: 'item4',
  125. name: '供应商管理',
  126. moduleList: [{
  127. moduleId: '6001',
  128. label: '生产',
  129. icon: '../../static/logo.png'
  130. },
  131. {
  132. moduleId: '6002',
  133. label: '领料',
  134. icon: '../../static/images/nav_car_apply.png'
  135. },
  136. {
  137. moduleId: '6003',
  138. label: '销售出库',
  139. icon: '../../static/images/nav_car_apply.png'
  140. },
  141. {
  142. moduleId: '6004',
  143. label: '销售入库',
  144. icon: '../../static/images/nav_car_apply.png'
  145. },
  146. {
  147. moduleId: '6004',
  148. label: '销售入库',
  149. icon: '../../static/images/nav_car_apply.png'
  150. }
  151. ]
  152. }, {
  153. id: 'item5',
  154. name: '实验室管理',
  155. moduleList: [{
  156. moduleId: '6001',
  157. label: '生产',
  158. icon: '../../static/logo.png'
  159. },
  160. {
  161. moduleId: '6002',
  162. label: '领料',
  163. icon: '../../static/images/nav_car_apply.png'
  164. },
  165. {
  166. moduleId: '6003',
  167. label: '销售出库',
  168. icon: '../../static/images/nav_car_apply.png'
  169. },
  170. {
  171. moduleId: '6004',
  172. label: '销售入库',
  173. icon: '../../static/images/nav_car_apply.png'
  174. },
  175. {
  176. moduleId: '6004',
  177. label: '销售入库',
  178. icon: '../../static/images/nav_car_apply.png'
  179. }
  180. ]
  181. }, {
  182. id: 'item6',
  183. name: '生产管理',
  184. moduleList: [{
  185. moduleId: '6001',
  186. label: '生产',
  187. icon: '../../static/logo.png'
  188. },
  189. {
  190. moduleId: '6002',
  191. label: '领料',
  192. icon: '../../static/images/nav_car_apply.png'
  193. },
  194. {
  195. moduleId: '6003',
  196. label: '销售出库',
  197. icon: '../../static/images/nav_car_apply.png'
  198. },
  199. {
  200. moduleId: '6004',
  201. label: '销售入库',
  202. icon: '../../static/images/nav_car_apply.png'
  203. },
  204. {
  205. moduleId: '6004',
  206. label: '销售入库',
  207. icon: '../../static/images/nav_car_apply.png'
  208. }
  209. ]
  210. }])
  211. let toView = ref('')
  212. // 锚点
  213. function change(index) {
  214. // var id = event.currentTarget.dataset.id;
  215. var id = 'item' + (index + 1)
  216. toView = id;
  217. uni.createSelectorQuery().select('#' + toView).boundingClientRect(data => { //目标位置的节点:类或者id
  218. uni.createSelectorQuery().select(".x-p-titleList").boundingClientRect(
  219. res => { //最外层盒子的节点:类或者id
  220. uni.pageScrollTo({
  221. duration: 100, //过渡时间
  222. // scrollTop: data.top - res.top - 10 //到达距离顶部的top
  223. scrollTop: data.top - res.top + 45 //到达距离顶部的top
  224. })
  225. }).exec()
  226. }).exec();
  227. }
  228. let isAdd = ref(true)
  229. // --------------------------------------
  230. let distanceArr = reactive([]) // 每一个ID对应的scrollTop值
  231. // 获取所有元素在当前页面所处的位置信息
  232. function getDistanceArr() {
  233. dataList.map(el => {
  234. uni.createSelectorQuery().select('#' + el.id).boundingClientRect(data => { //目标位置的节点:类或者id
  235. // 获取当前ID距离顶部的top
  236. distanceArr.push(data.top)
  237. }).exec();
  238. })
  239. }
  240. // 生命周期
  241. onMounted(() => {
  242. getDistanceArr()
  243. })
  244. return {
  245. keyword,
  246. current,
  247. dataList,
  248. toView,
  249. change,
  250. isAdd,
  251. distanceArr,
  252. getDistanceArr
  253. }
  254. },
  255. // onShow() {
  256. // this.getDistanceArr()
  257. // },
  258. // 监听页面滚动
  259. onPageScroll(event) {
  260. const _this = this
  261. if (this.isTabChange) {
  262. return
  263. }
  264. const {
  265. scrollTop
  266. } = event;
  267. const skewY =100 // 偏移量,由于吸顶的tab、头部的显示信息也有高度,素以做了偏移量
  268. if (scrollTop >= skewY) {
  269. if (!this.showTabs && this.current <= 0) { // 在未显示tab并且 current <= 0时,防止uview ui抖动bug,设置默认复位值
  270. this.current = 0
  271. }
  272. this.showTabs = true
  273. this.$nextTick(() => {
  274. const length = this.distanceArr.length
  275. const index = this.distanceArr.findIndex(el => el - skewY - scrollTop > 0)
  276. //index == -1 的时候,实际当前滚动的距离超出了最大值,也就是在最后一个tab显示的内容
  277. //index > 0 的时候,说明能在当前的scrollTop值找到,即index的前一位
  278. // this.current = index > 0 ? index - 1 : length - 1
  279. this.current = index > 0 ? index - 1 : 0
  280. })
  281. }
  282. // else {
  283. // this.showTabs = false
  284. // }
  285. }
  286. }
  287. </script>
  288. <style lang="scss">
  289. .main {
  290. padding: 20rpx;
  291. }
  292. .all-menu {
  293. padding: 10rpx;
  294. .title {
  295. font-size: 16px;
  296. // font-weight: bold;
  297. }
  298. }
  299. // --------------------
  300. .list-cell {
  301. display: flex;
  302. box-sizing: border-box;
  303. width: 100%;
  304. padding: 10px 24rpx;
  305. color: #323233;
  306. font-size: 14px;
  307. line-height: 24px;
  308. background-color: #fff;
  309. }
  310. .listItem-dtl {
  311. height: 100rpx;
  312. image {
  313. height: 80rpx;
  314. width: 80rpx;
  315. margin-right: 16rpx;
  316. }
  317. }
  318. .search {
  319. position: fixed;
  320. }
  321. .scroller {
  322. box-sizing: border-box;
  323. padding: 0 15rpx;
  324. }
  325. </style>

调用接口使用过程中的问题及解决

1.使用vue3赋值问题:

let dataList=reactive([])改成let obj=reactive({dataList:[]})

html部分修改:obj.dataList

  1. <u-tabs :list="obj.dataList" :is-scroll="true" v-model="current" @change="change">
  2. </u-tabs>
  3. <view class="x-p-listItem" v-for="(item,idxBlock) in obj.dataList" :key="item.menuId"
  4. :id="'item'+idxBlock">

2.js

  1. import {
  2. ref,
  3. reactive,
  4. onMounted,
  5. nextTick
  6. } from 'vue'
  7. export default {
  8. setup() {
  9. let obj = reactive({
  10. dataList: []
  11. })
  12. // 获取全部菜单列表
  13. function getAllMenuList() {
  14. listMenu(queryParams).then(res => {
  15. let data = res.data.data.map(s => {
  16. s.visible = false
  17. return s
  18. })
  19. let arr = handleTree(data, 'menuId')
  20. let newArr = []
  21. arr.forEach(item => {
  22. item.name = item.menuName
  23. item.id = item.menuId
  24. if (item.menuType != 'C') {
  25. newArr.push(item)
  26. }
  27. })
  28. obj.dataList = newArr
  29. // 记录每个模块节点位置,请求到数据挂在完成后执行,去掉原来的getDistanceArr方法
  30. nextTick(() => {
  31. obj.dataList.map((el, index) => {
  32. uni.createSelectorQuery().select('#item' + index).boundingClientRect(
  33. data => { //目标位置的节点:类或者id
  34. // 获取当前ID距离顶部的top
  35. distanceArr.push(data.top)
  36. }).exec();
  37. })
  38. })
  39. })
  40. }
  41. // 生命周期
  42. onMounted(() => {
  43. getAllMenuList()
  44. // getDistanceArr()
  45. })
  46. return {
  47. keyword,
  48. current,
  49. obj,
  50. toView,
  51. change,
  52. isAdd,
  53. distanceArr,
  54. addOrCancelMenu,
  55. }
  56. },

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/429306
推荐阅读
相关标签
  

闽ICP备14008679号