icodingicoding
主页
JavaScript
Vue
React
TypeScript
Node
bug
笔记
时间线
主页
JavaScript
Vue
React
TypeScript
Node
bug
笔记
时间线
  • Markdown 语法
  • 插件
  • Vue
  • 组件设计
  • Element-Ui
  • WebSocket
  • CSS
  • Uniapp
  • 进阶
  • 扫码枪
  • Nginx
  • Nuxt.js
  • Vue 时钟
  • Learning
  • Linux
  • 打包优化
  • 大屏可视化
  • Jenkins
  • SVN
  • JsDocs
  • 代码规范

Uniapp

UI组件库

  • 推荐,组件功能比较齐全 wot-ui
  • uView Next
  • vue3+ts uviewpro
  • vue2 uviewui
  • tuniao-ui
  • tuniao-ui 第三方组件

微信小程序自定义 tabbar

  • pages.json文件配置 tabBar,"custom": true,list 字段也需要配置,这样可以使用 uni.switchTab 来切换 tabbar 路由,并且在切换 tabbar 时不闪烁(每个 tabbar 第一次加载时会闪一下,加载后,在进到该 tabbar 不会再次加载,也就不会闪)
"tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#399d9e",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "custom": false,
    "list": [
      {
        "pagePath": "pages/home/home",
        "text": "首页",
        "iconPath": "static/tabBar/home_off.png",
        "selectedIconPath": "static/tabBar/home_on.png"
      },
      {
        "pagePath": "pages/scheduling/scheduling",
        "text": "排班",
        "iconPath": "static/tabBar/scheduling_off.png",
        "selectedIconPath": "static/tabBar/scheduling_on.png"
      },
      {
        "pagePath": "pages/report/report",
        "text": "报表",
        "iconPath": "static/tabBar/report_off.png",
        "selectedIconPath": "static/tabBar/report_on.png"
      },
      {
        "pagePath": "pages/waitdo/waitdo",
        "text": "待办",
        "iconPath": "static/tabBar/waitdo_off.png",
        "selectedIconPath": "static/tabBar/waitdo_on.png"
      },
      {
        "pagePath": "pages/mine/mine",
        "text": "我的",
        "iconPath": "static/tabBar/mine_off.png",
        "selectedIconPath": "static/tabBar/mine_on.png"
      },
      {
        "pagePath": "pages/layout/layout",
        "text": "layout",
        "iconPath": "static/tabBar/mine_off.png",
        "selectedIconPath": "static/tabBar/mine_on.png"
      }
    ]
  }

注意

uni.reLaunch 可以跳转到 tabbar 页面

  • "custom": true,list 的 item 可以配置超过5个,并且在微信开发者工具中也不会报错
  • "custom": false,list 的 item 配置不可超过5个,微信开发者工具会报错:[ app.json 文件内容错误] app.json: ["tabBar"]["list"] 不能超过 5 项(env: Windows,mp,1.06.2405020; lib: 3.5.3)

img

  • 开发 tabbar 组件,components/tabbar
<template>
  <view class="rtc-tabbar">
    <view
      class="tabbar-item"
      v-for="item in tablist"
      :key="item.name"
      @click.stop="onClick(item)"
    >
      <image
        class="tab-icon"
        :src="isActive(item) ? item.selectedIconPath : item.iconPath"
        mode="scaleToFill"
      />
      <view :class="['label', { 'is-active': isActive(item) }]">
        {{ item.text }}
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, ref, watch } from "vue";

interface Props {
  value: string;
}
const props = withDefaults(defineProps<Props>(), {
  value: "",
});

type TabItem = {
  pagePath: string;
  name: string;
  text: string;
  iconPath: string;
  selectedIconPath: string;
};

const activeTab = ref<string>();
watch(
  () => props.value,
  (nv) => {
    activeTab.value = nv;
  },
  {
    immediate: true,
  }
);
const isActive = computed(() => {
  return (item: TabItem) => {
    return activeTab.value === item.name;
  };
});
const tablist = ref<TabItem[]>([
  {
    name: "home",
    pagePath: "/pages/home/home",
    text: "首页",
    iconPath: "../../static/tabBar/home_off.png",
    selectedIconPath: "../../static/tabBar/home_on.png",
  },
  {
    name: "scheduling",
    pagePath: "/pages/scheduling/scheduling",
    text: "排班",
    iconPath: "../../static/tabBar/scheduling_off.png",
    selectedIconPath: "../../static/tabBar/scheduling_on.png",
  },
  // {
  //   name: "report",
  //   pagePath: "/pages/report/report",
  //   text: "报表",
  //   iconPath: "../../static/tabBar/report_off.png",
  //   selectedIconPath: "../../static/tabBar/report_on.png",
  // },
  // {
  //   name: "waitdo",
  //   pagePath: "/pages/waitdo/waitdo",
  //   text: "待办",
  //   iconPath: "../../static/tabBar/waitdo_off.png",
  //   selectedIconPath: "../../static/tabBar/waitdo_on.png",
  // },
  {
    name: "mine",
    pagePath: "/pages/mine/mine",
    text: "我的",
    iconPath: "../../static/tabBar/mine_off.png",
    selectedIconPath: "../../static/tabBar/mine_on.png",
  },
  // {
  //   name: "layout",
  //   pagePath: "/pages/layout/layout",
  //   text: "layout",
  //   iconPath: "../../static/tabBar/home_off.png",
  //   selectedIconPath: "../../static/tabBar/home_on.png",
  // },
]);

const onClick = (item: TabItem) => {
  if (activeTab.value === item.name) return;
  uni.switchTab({
    url: item.pagePath,
  });
};
</script>

<style scoped lang="scss">
.rtc-tabbar {
  height: calc(100rpx + env(safe-area-inset-bottom));
  background-color: #fff;
  border-top: 1rpx solid #e5e5e5;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: none;
  padding-bottom: env(safe-area-inset-bottom);

  .tabbar-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .tab-icon {
      width: 44rpx;
      height: 46rpx;
    }
    .label {
      display: flex;
      justify-content: center;
      font-size: $rt-font-size-md;
      color: #7a7e83;
      &.is-active {
        color: $rt-primary;
      }
    }
  }
}
</style>
  • 在 tabbar 页面分别导入
<template>
  <layout-page>
    <view class="rt-home page">
    </view>
  </layout-page>
  <tabbar value="home" />
</template>

<script setup lang="ts">
import tabbar from "@/components/tabbar/tabbar.vue";
</script>
</style>
  • custom: true下, tabBar.list < 5

img

  • custom: true下, tabBar.list > 5

img

注意

  • 我采用的方案是自定义 tabbar,但是并没有使用微信小程序官方的做法=》使用custom-tab-bar,因此在微信开发者工具下,会有警告:[代码依赖分析] 找到 1 个依赖异常情况,可能会导致对应文件无法加载,请检查。 Couldn't resolve the Component "custom-tab-bar/index" relative to "/app.json" 如需关闭依赖分析请在 project.config.json setting 字段中增加 "ignoreDevUnusedFiles": false 和 "ignoreUploadUnusedFiles": falseimg

消除警告有两种方式:

  1. project.config.json setting 字段中增加 "ignoreDevUnusedFiles": false 和 "ignoreUploadUnusedFiles": false
  2. 在 src 目录下新增 custom-tab-bar:index.js,index.json,index.wxml,index.wxss;

我采用第 2 种方式,因为警告在开发环境还是打开好,方便发现潜在问题

  • 我的做法和微信官网不同,因为我已经自己封装了 tabbar 组件,不需要使用 custom-tab-bar 来自定义 tabbar,所以使用 custom-tab-bar 只是为了消除警告:Couldn't resolve the Component "custom-tab-bar/index" relative to "/app.json"

imgimg

微信小程序自定义 tabbar-官网

我的 custom-tab-bar

  • index.js,必须要有,不能为空文件
Component({});
  • index.json,必须要有,不能为空文件
{
  "component": true
}
  • index.wxml,必须要有,可以什么都不写
<!--miniprogram/custom-tab-bar/index.wxml-->
  • index.wxss 非必须

主包使用子包组件

主包子组件使用子包组件,把主包子组件配置成页面(因为 uniapp 写的是 vue 组件,所以无法在子组件配置 json),配置 style 的 componentPlaceholder 和 usingComponents

  • componentPlaceholder 配置加载子包组件过程的占位组件
"pages": [
    {
      "path": "components/report/department/sea",
      "style": {
        "componentPlaceholder": {
          "qiun-data-charts": "view"
        },
        "usingComponents": {
          "qiun-data-charts": "/sub-components/qiun-data-charts/qiun-data-charts"
        }
      }
    },
    {
      "path": "components/report/personal/performance",
      "style": {
        "componentPlaceholder": {
          "qiun-data-charts": "view"
        },
        "usingComponents": {
          "qiun-data-charts": "/sub-components/qiun-data-charts/qiun-data-charts"
        }
      }
    }
]

  • 导入子包组件并使用
<template>
  <view>
    <qiun-data-charts
      type="ring"
      :opts="opts"
      :chartData="chartData"
      :canvas2d="canvas2d"
      canvasId="stack"
    />
  </view>
</template>

<script setup lang="ts">
import qiunDataCharts from "@/sub-components/qiun-data-charts/qiun-data-charts.vue";

const { platform } = uni.getSystemInfoSync();
const canvas2d = ref(platform === "devtools" ? false : true);

const chartData = ref({});

const opts = reactive({
  duration: CHARTS_DURATION,
  color: ["#449EFD", "#01C883"],
  fontSize: 11,

  xAxis: {
    disableGrid: true,
    rotateLabel: true,
    rotateAngle: 20,
    fontSize: 11,
  },
  dataLabel: false,
  legend: {
    show: true,
    position: "top",
    containLabel: true,
    // lineHeight: 25,
  },
  padding: [15, 15, 15, 5],
  yAxis: {
    data: [
      {
        min: 0,
      },
    ],
  },
  extra: {
    column: {
      type: "group",
      width: 16,
      seriesGap: 5,
    },
  },
});
</script>

主包使用子包 js 文件

子包静态资源

  1. 目录结构

将子包专用的图片资源放在子包目录下的static文件夹中,而不是根目录的static。例如,假设你有一个子包名为pagesA,那么目录结构应该如下:

├── pages.json
├── static                 # 主包的静态资源
│   └── main-bg.png
└── pagesA                 # 子包A
    ├── pages
    │   └── index.vue
    └── static             # 子包A的静态资源
        └── sub-bg.png
  1. 配置分包

在pages.json中配置分包,确保子包的root指向正确的目录。例如:

{
  "pages": [
    // 主包页面
  ],
  "subPackages": [
    {
      "root": "pagesA",
      "pages": [
        // 子包A的页面
      ]
    }
  ]
}
  1. 开启分包优化

在manifest.json中对应平台的配置下开启分包优化,以微信小程序为例:

"mp-weixin": {
  "optimization": {
    "subPackages": true
  }
}

开启分包优化后,构建时会将子包下的静态资源(如图片)打包到子包中,而不是主包

  1. 引用子包图片

在子包的页面中引用图片时,使用相对路径或者以子包根目录为基准的绝对路径。例如在pagesA子包的页面中:

<template>
  <image src="./static/sub-bg.png"></image>
  <!-- 或者 -->
  <image src="/pagesA/static/sub-bg.png"></image>
</template>

重要注意事项

  • 资源隔离:放置在子包 static 目录下的图片,主包和其他子包无法直接引用。请确保图片只被其所在的子包使用。

  • 主包体积:所有子包共用的图片,仍然可以放在主包的 static 目录下。但请注意,这会增加主包的体积。

  • 图片优化:如果项目体积仍然很大,可以考虑将一些不常变动的大图托管到服务器上,使用网络地址进行引用,这是控制包体积最有效的方法之一。

  • 检查分包结果:上传或预览小程序时,务必使用开发者工具(如微信开发者工具)的“代码依赖分析”功能,查看主包和各个子包的具体大小,确认图片资源是否已按预期正确分配

目录结构

├── pages                # 主包页面目录
├── static               # 主包静态资源
├── subPackageA          # 子包A根目录
│   ├── pages            # 子包A页面
│   └── static           # ➕ 子包A的专属图片资源
│       └── icon.png
└── subPackageB          # 子包B根目录
    ├── pages
    └── static           # ➕ 子包B的专属图片资源
        └── avatar.jpg

总结

总的来说,让子包图片独立打包的关键操作就是:在子包目录下建立 static 文件夹存放专属图片,并在 manifest.json 中开启分包优化。这样做可以有效减轻主包的压力,优化小程序的启动速度。

最后编辑:
上一页
CSS
下一页
进阶