category.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <template>
  2. <view class="content">
  3. <!-- #ifdef MP -->
  4. <navigator url="/pages/product/search">
  5. <view class="input-box flex">
  6. <view class=" input-content flex">
  7. <view class="iconfont iconsearch"></view>
  8. <view class="input"><input disabled placeholder="请输入搜索内容" /></view>
  9. </view>
  10. <view class="input-button flex"><text>搜索</text></view>
  11. </view>
  12. </navigator>
  13. <!-- #endif -->
  14. <view class="content_row">
  15. <scroll-view scroll-y class="left-aside">
  16. <view v-for="item in flist" :key="item.id" class="f-item b-b" :class="{ active: item.id === currentId }" @click="tabtap(item)">{{ item.cate_name }}</view>
  17. </scroll-view>
  18. <scroll-view scroll-with-animation scroll-y class="right-aside" @scroll="asideScroll" :scroll-top="tabScrollTop">
  19. <view v-for="item in flist" :key="item.id" class="s-list" :id="'main-' + item.id">
  20. <text class="s-item">{{ item.cate_name }}</text>
  21. <view class="t-list ">
  22. <view @click="navToList(item.id, titem.id)" class="t-item" v-for="titem in item.children" :key="titem.id">
  23. <image :src="titem.pic" mode="scaleToFill" :lazy-load='true'></image>
  24. <text>{{ titem.cate_name }}</text>
  25. </view>
  26. </view>
  27. </view>
  28. </scroll-view>
  29. </view>
  30. </view>
  31. </template>
  32. <script>
  33. import { getList } from '@/api/category.js';
  34. export default {
  35. data() {
  36. return {
  37. sizeCalcState: false,
  38. tabScrollTop: 0,
  39. currentId: 1,
  40. flist: [],
  41. };
  42. },
  43. onLoad() {
  44. this.loadData();
  45. },
  46. // 监听导航栏输入框点击事件
  47. onNavigationBarSearchInputClicked(e) {
  48. uni.navigateTo({
  49. url: '/pages/product/search'
  50. });
  51. },
  52. methods: {
  53. // 载入数据
  54. async loadData() {
  55. let obj = this;
  56. getList({}).then(({ data }) => {
  57. console.log('-------',data);
  58. console.log(data.cate_name);
  59. obj.flist = data.map(function(s) {
  60. return s;
  61. });
  62. obj.flist.pop();
  63. obj.currentId = obj.flist[0].id;
  64. }).catch(err => {
  65. console.log(err);
  66. });
  67. },
  68. //一级分类点击
  69. tabtap(item) {
  70. console.log(item);
  71. // 判断有没有初始化页面高度对象数据
  72. if (!this.sizeCalcState) {
  73. this.calcSize();
  74. }
  75. // 获取当前点击的id
  76. this.currentId = item.id;
  77. this.tabScrollTop = item.top;
  78. },
  79. //右侧栏滚动
  80. asideScroll(e) {
  81. // 判断有没有初始化页面高度对象数据
  82. if (!this.sizeCalcState) {
  83. this.calcSize();
  84. }
  85. // 获取当前滚轮高度
  86. console.log(e,99999)
  87. let scrollTop = e.detail.scrollTop;
  88. let box = 0; //列表包裹框高度初始化
  89. let bottom = 10; //距离页面底部多少像素左侧列表切换到最后一个一级分类
  90. // 查询当前页面对象
  91. let view = uni.createSelectorQuery().select('.content');
  92. view.fields(
  93. {
  94. id: true,
  95. dataset: true,
  96. rect: true,
  97. size: true,
  98. scrollOffset: true
  99. },
  100. function(e) {
  101. // 保存包裹框高度
  102. box = e.height;
  103. }
  104. ).exec();
  105. // 获取所有距离顶部大于滚轮距离页面高度的所有分类
  106. let tabs = this.flist.filter(item => (item.top-10)<= scrollTop).reverse();
  107. if (tabs.length > 0) {
  108. // 判断是否已经到达滚轮底部
  109. if (box + scrollTop + bottom >= e.detail.scrollHeight) {
  110. this.currentId = this.flist[this.flist.length - 1].id;
  111. } else {
  112. this.currentId = tabs[0].id;
  113. }
  114. }
  115. },
  116. //计算右侧栏每个tab的高度等信息
  117. calcSize() {
  118. let h = 0;
  119. this.flist.forEach(item => {
  120. let view = uni.createSelectorQuery().select('#main-' + item.id);
  121. view.fields(
  122. {
  123. size: true
  124. },
  125. data => {
  126. item.top = h;
  127. h += data.height;
  128. item.bottom = h;
  129. }
  130. ).exec();
  131. });
  132. this.sizeCalcState = true;
  133. },
  134. navToList(sid, tid) {
  135. // 点击导航跳转到详细页面
  136. uni.navigateTo({
  137. url: '/pages/product/list?fid='+this.currentId+'&sid='+sid+'&tid='+tid
  138. });
  139. }
  140. }
  141. };
  142. </script>
  143. <style lang="scss">
  144. page,
  145. .content_row {
  146. height: 100%;
  147. background-color: #f8f8f8;
  148. }
  149. .content_row {
  150. display: flex;
  151. }
  152. /* #ifdef MP || APP-PLUS*/
  153. .input-box {
  154. padding: 25rpx;
  155. /* #ifdef APP-PLUS */
  156. margin-top: var(--status-bar-height);
  157. /* #endif */
  158. background-color: #ffffff;
  159. height: 44px;
  160. .iconsearch {
  161. font-size: 50rpx;
  162. }
  163. .input-content {
  164. border-radius: 99rpx;
  165. flex-grow: 1;
  166. padding: 5rpx 30rpx;
  167. background-color: rgba(231, 231, 231, 0.7);
  168. .input {
  169. flex-grow: 1;
  170. input {
  171. font-size: $font-base;
  172. }
  173. }
  174. }
  175. .input-button {
  176. padding-left: 20rpx;
  177. font-size: $font-base;
  178. height: 100%;
  179. }
  180. }
  181. /* #endif */
  182. .left-aside {
  183. flex-shrink: 0;
  184. width: 200rpx;
  185. height: 100%;
  186. background-color: #fff;
  187. }
  188. .f-item {
  189. display: flex;
  190. align-items: center;
  191. justify-content: center;
  192. width: 100%;
  193. height: 100rpx;
  194. font-size: 28rpx;
  195. color: $font-color-base;
  196. position: relative;
  197. &.active {
  198. color: $font-color-spec;
  199. background: #f8f8f8;
  200. &:before {
  201. content: '';
  202. position: absolute;
  203. left: 0;
  204. top: 50%;
  205. transform: translateY(-50%);
  206. height: 36rpx;
  207. width: 8rpx;
  208. background-color: $font-color-spec;
  209. border-radius: 0 4px 4px 0;
  210. opacity: 0.8;
  211. }
  212. }
  213. }
  214. .right-aside {
  215. flex: 1;
  216. overflow: hidden;
  217. padding-left: 20rpx;
  218. padding-right: 20rpx;
  219. }
  220. .s-item {
  221. display: flex;
  222. align-items: center;
  223. height: 70rpx;
  224. padding-top: 8rpx;
  225. font-size: 28rpx;
  226. color: $font-color-dark;
  227. }
  228. .t-list {
  229. display: flex;
  230. flex-wrap: wrap;
  231. border-radius: 15rpx;
  232. width: 100%;
  233. background: #fff;
  234. padding-top: 12rpx;
  235. &:after {
  236. content: '';
  237. flex: 99;
  238. height: 0;
  239. }
  240. }
  241. .t-item {
  242. flex-shrink: 0;
  243. display: flex;
  244. justify-content: center;
  245. align-items: center;
  246. flex-direction: column;
  247. width: 171rpx;
  248. font-size: 26rpx;
  249. color: #666;
  250. padding-bottom: 20rpx;
  251. image {
  252. width: 140rpx;
  253. height: 140rpx;
  254. }
  255. }
  256. </style>