Jacob
2026-10-12 52016ced7c4fb9c0d864e845d9252f3d8de77f0a
pages/goods_cate/goods_cate.vue
....@@ -13,7 +13,7 @@
1313 <scroll-view scroll-y="true" scroll-with-animation='true'
1414 :style="{height: (height-280/750*windowWidth) + 'px'}" :scroll-into-view="'menu_item'+navActive">
1515 <view class='item acea-row row-center-wrapper menu_item' :id="'menu_item'+index"
16
- :class='index==navActive?"on":""' v-for="(item,index) in categoryList" :key="item._key"
16
+ :class='index==navActive?"on":""' v-for="(item,index) in categoryList" :key="index"
1717 @click='tap(index,"b"+index)'>
1818 <image v-if="item.extra" class="img" :src="item.extra" mode="aspectFill"></image>
1919 <view class="text">{{item.name}}</view>
....@@ -25,7 +25,7 @@
2525 <scroll-view :scroll-into-view="'subMenu_item'+subActive" scroll-x="true" scroll-with-animation='true'
2626 style="width: 100%;">
2727 <view class="subMenu_wrapper">
28
- <block v-for="(itemn,indexn) in categoryList[navActive].child" :key="itemn._key"><text
28
+ <block v-for="(itemn,indexn) in categoryList[navActive].child" :key="indexn"><text
2929 class="subMenu_item" :id="'subMenu_item'+indexn" :class='indexn==subActive?"on":""'
3030 @click='tapSub(indexn)'>{{itemn.name}}</text></block>
3131 </view>
....@@ -35,15 +35,15 @@
3535 :style="{top: (categoryList[navActive].show2Category==0?0:118) + 'rpx',height: (height-(categoryList[navActive].show2Category==0?0:(122/750*windowWidth))) + 'px'}">
3636 <scroll-view :scroll-top="scrollTop" class="goodlistScroll" scroll-y="true" style="height:100%;"
3737 :scroll-into-view="scrollIntoView" @scroll="handleScroll" :throttle="false">
38
- <block v-for="(aitem,aindex) in categoryList" :key="aitem._key">
39
- <view class="list" v-if="aitem.child.length>0" v-for="(sitem,sindex) in aitem.child" :key="sitem._key"
38
+ <block v-for="(aitem,aindex) in categoryList" :key="aindex">
39
+ <view class="list" v-if="aitem.child.length>0" v-for="sitem,sindex in aitem.child" :key="sindex"
4040 :style="(aindex==categoryList.length-1&&sindex==aitem.child.length-1)?('min-height:'+(height-370/750*windowWidth)+'px'):''"
4141 :id="'list'+aindex+'_'+sindex">
4242 <view class="list_title">{{sitem.name}}</view>
4343 <view class="list_wrapper cf">
4444 <view class="list_column cfl">
4545 <block style="float:left" v-if="sitem.productArr.length>0"
46
- v-for="(gitem,gindex) in sitem.productArr" :key="gitem._key">
46
+ v-for="(gitem,gindex) in sitem.productArr" :key="gindex">
4747 <GoodBlock v-if="gindex%2==0" :size="'small'" :pageName="'分类'"
4848 :moduleName="'分类商品列表'" :careBeanRate="careBeanRate" :goodsInfo="gitem">
4949 </GoodBlock>
....@@ -51,7 +51,7 @@
5151 </view>
5252 <view class="list_column cfr">
5353 <block style="float:left" v-if="sitem.productArr.length>0"
54
- v-for="(gitem,gindex) in sitem.productArr" :key="gitem._key">
54
+ v-for="(gitem,gindex) in sitem.productArr" :key="gindex">
5555 <GoodBlock v-if="gindex%2==1" :size="'small'" :pageName="'分类'"
5656 :moduleName="'分类商品列表'" :careBeanRate="careBeanRate" :goodsInfo="gitem">
5757 </GoodBlock>
....@@ -66,14 +66,14 @@
6666 <view class="list_wrapper cf">
6767 <view class="list_column cfl">
6868 <block v-if="aitem.productArr.length>0" v-for="(gitem,gindex) in aitem.productArr"
69
- :key="gitem._key">
69
+ :key="gindex">
7070 <GoodBlock v-if="gindex%2==0" :pageName="'分类'" :moduleName="'分类商品列表'"
7171 :careBeanRate="careBeanRate" :goodsInfo="gitem"></GoodBlock>
7272 </block>
7373 </view>
7474 <view class="list_column cfr">
7575 <block v-if="aitem.productArr.length>0" v-for="(gitem,gindex) in aitem.productArr"
76
- :key="gitem._key">
76
+ :key="gindex">
7777 <GoodBlock v-if="gindex%2==1" :pageName="'分类'" :moduleName="'分类商品列表'"
7878 :careBeanRate="careBeanRate" :goodsInfo="gitem"></GoodBlock>
7979 </block>
....@@ -399,8 +399,6 @@
399399 uni.showLoading();
400400 getCategoryList().then(res => {
401401 that.categoryList = res.data;
402
- // [P0-优化] 装配阶段为所有分类节点打 _key,供模板 :key 使用
403
- that.ensureCategoryKey(that.categoryList);
404402 // 重置计数,避免重复进入页面时累积
405403 that.totalGetNum = 0;
406404 that.finishNum = 0;
....@@ -445,83 +443,19 @@
445443 that.getAllProductList(false, index);
446444 }
447445 };
448
- // [P0-优化] 首屏分类(当前navActive):立即并发发起,不走任何队列,最大限度缩短首屏 loading 时长
449
- loadCate(that.navActive);
450
- // [P0-优化] 其余分类:构建任务列表,走下方并发限流池,避免一次性占满 wx.request queue 拖慢首屏
451
- let otherTasks = [];
452
- that.categoryList.forEach((it, idx) => {
453
- if (idx !== that.navActive) otherTasks.push({ index: idx });
454
- });
455
- that.runCategoryTasksWithLimit(otherTasks, 4);
446
+ // 当前分类优先请求,保证首屏数据最先返回
447
+ loadCate(that.navActive);
448
+ that.categoryList.forEach((item, index) => {
449
+ if (index != that.navActive) {
450
+ loadCate(index);
451
+ }
452
+ })
456453
457454
458
- })
459
- },
460
- // [P0-优化] 并发限流工具:除首屏分类外,其余分类的请求经由此处发起
461
- runCategoryTasksWithLimit(tasks, limit) {
462
- let that = this;
463
- if (!tasks || !tasks.length) return Promise.resolve();
464
- const queue = tasks.slice();
465
- const executing = [];
466
- const launch = () => {
467
- while (queue.length && executing.length < limit) {
468
- const task = queue.shift();
469
- const item = that.categoryList[task.index];
470
- if (!item) continue;
471
- let promise;
472
- if (item.child && item.child.length > 0) {
473
- const subPromises = [];
474
- item.child.forEach((sub, subIdx) => {
475
- subPromises.push(that.getAllProductList('isSub', task.index, subIdx));
476
- });
477
- promise = Promise.all(subPromises);
478
- } else {
479
- promise = that.getAllProductList(false, task.index);
480
- }
481
- // 用 .catch 包一层避免单个失败拖垮整池
482
- const tracked = promise.catch(() => {});
483
- tracked.finally(() => {
484
- const idx = executing.indexOf(tracked);
485
- if (idx >= 0) executing.splice(idx, 1);
486
- }).catch(() => {});
487
- executing.push(tracked);
488
- }
489
- };
490
- const next = () => {
491
- launch();
492
- if (executing.length === 0) return Promise.resolve();
493
- return Promise.race(executing).then(next, next);
494
- };
495
- return next();
496
- },
497
- // [P0-优化] 为分类节点打 _key:非 H5 平台的 v-for :key 必须为简单变量,
498
- // 故在数据装配阶段预先在 item 上加 _key,模板用 :key="item._key" 引用
499
- ensureCategoryKey: function(list) {
500
- if (!Array.isArray(list)) return;
501
- list.forEach((item, i) => {
502
- if (!item) return;
503
- if (item.id != null) item._key = 'c-' + item.id;
504
- else if (!item._key) item._key = 'c0-' + i;
505
- if (item.child && item.child.length) {
506
- item.child.forEach((sub, j) => {
507
- if (!sub) return;
508
- if (sub.id != null) sub._key = 's-' + sub.id;
509
- else if (!sub._key) sub._key = 's0-' + i + '-' + j;
510
- });
511
- }
512
- });
513
- },
514
- // [P0-优化] 为商品节点打 _key
515
- ensureProductKey: function(list) {
516
- if (!Array.isArray(list)) return;
517
- list.forEach((g, k) => {
518
- if (!g) return;
519
- if (g.id != null && !g._key) g._key = 'p-' + g.id;
520
- else if (!g._key) g._key = 'pk-' + k;
521
- });
522
- },
523
- // 当前分类数据全部就绪后立即关闭全屏loading,不必等待所有分类
524
- checkFirstScreen(index1) {
455
+ })
456
+ },
457
+ // 当前分类数据全部就绪后立即关闭全屏loading,不必等待所有分类
458
+ checkFirstScreen(index1) {
525459 let that = this;
526460 if (that.firstScreenReady || index1 != that.navActive) return;
527461 if ((that.catePending[index1] || 0) <= 0) {
....@@ -631,8 +565,6 @@
631565 cid: isSub ? that.categoryList[index1].child[index2].id : that.categoryList[index1].id,
632566 }).then(res => {
633567 let list = res.data.list;
634
- // [P0-优化] 装配阶段为商品节点打 _key,供模板 :key 使用
635
- that.ensureProductKey(list);
636568 // 当前浏览分类即时渲染;其余分类进入缓冲队列批量渲染,
637569 // 避免几十次$set各自触发一次全量列表渲染
638570 if (index1 == that.navActive && !that.firstScreenReady) {