uni-app 系列(三):组件、easycom、rpx 与条件编译
2026年8月3日 · 17 分钟
一、内置组件:为什么是 view / text
uni-app 提供一套跨端抽象组件,编译时翻译成各端真实组件。最常用的一批:
| 组件 | 作用 | 类比 HTML |
|---|---|---|
<view> | 容器 | <div> |
<text> | 文本(只有它能包纯文字) | <span> |
<image> | 图片(注意有默认尺寸) | <img> |
<scroll-view> | 可滚动容器 | 滚动 div |
<swiper> | 轮播 | — |
<input>/<textarea> | 表单输入 | 同名 |
<button> | 按钮(小程序里还能触发开放能力) | <button> |
<navigator> | 声明式跳转 | <a> |
两个新手最常踩的坑:
- 纯文字必须包在
<text>里。<view>你好</view>在 App/小程序端可能有兼容问题或不能选中,规范写法是<view><text>你好</text></view>。 <image>有默认宽高(如 320×240),且默认mode不裁剪,实际用几乎都要显式设宽高 +mode="aspectFill"。
二、easycom:组件免注册自动引入
传统 Vue 里用组件要 import + 注册。uni-app 的 easycom 让你啥都不用写,直接用——只要组件放在约定目录、且文件名符合规范。
规则:组件放在 components/组件名/组件名.vue,就能在任意页面直接用 <组件名 />,无需 import、无需 components 注册。
components/
goods-card/
goods-card.vue ← 目录名与文件名一致
<template>
<!-- 不用 import,直接用! -->
<goods-card :item="data" />
</template>
好处:① 少写样板代码;② 按需编译——没用到的组件不会打进包里,对小程序包体积友好。自定义 easycom 匹配规则可在 pages.json 的 easycom 字段配置(常用于引入 UI 库组件)。
三、rpx:一套尺寸走遍所有屏幕
rpx(responsive pixel)是 uni-app 的响应式长度单位,核心规则:
无论什么设备,屏幕宽度恒定视为 750rpx。
所以如果设计稿宽 750px,稿子上标注多少 px,你就写多少 rpx,1:1 照搬。运行时按 设备实际宽度 / 750 的比例换算成物理像素,自动适配大小屏。
.card {
width: 750rpx; /* 满屏宽 */
padding: 24rpx;
font-size: 28rpx;
}
换算记忆:在 375pt 逻辑宽的手机上,750rpx = 375pt,即 2rpx = 1pt。
什么时候还用 px? 需要"绝对不随屏幕缩放"的场景,比如 1px 的细边框(用 rpx 在大屏会变粗)。可结合媒体查询或直接写 1px。
四、条件编译:uni-app 的杀手锏
多端难免有差异——某段代码只想在微信小程序跑、某个功能 App 才有。uni-app 用条件编译优雅解决:用特殊注释包裹,编译到指定平台时才保留。
语法(三种文件通用)
// #ifdef 平台 → 满足才编译
// #ifndef 平台 → 不满足才编译
// #endif → 结束
不同文件用不同注释符:
// JS 里
// #ifdef MP-WEIXIN
uni.login({ provider: "weixin" });
// #endif
<!-- 模板里 -->
<!-- #ifdef APP-PLUS -->
<view>只有 App 显示</view>
<!-- #endif -->
/* 样式里 */
/* #ifdef H5 */
.box { cursor: pointer; }
/* #endif */
常用平台标识
| 标识 | 含义 |
|---|---|
APP-PLUS | App(uni-app) / APP(uni-app x) |
H5 | H5 |
MP-WEIXIN | 微信小程序 |
MP-ALIPAY | 支付宝小程序 |
MP-TOUTIAO | 抖音小程序 |
MP | 所有小程序 |
典型用法:抹平多端登录
export function login() {
// #ifdef MP-WEIXIN
return uni.login({ provider: "weixin" });
// #endif
// #ifdef MP-ALIPAY
return uni.getAuthCode();
// #endif
// #ifdef H5
return phoneLogin();
// #endif
}
条件编译是"编译期裁剪"——不满足条件的代码根本不会进入产物,不是运行时 if 判断。所以微信包里不会包含支付宝的登录代码,既安全又减小体积。
五、样式的跨端注意点
- 不是所有 CSS 都支持:小程序/App 端对 CSS 支持有限,复杂选择器(如
*、属性选择器、部分伪类)在小程序可能失效。 - App 端(nvue)用的是原生排版,flex 是默认布局,部分 CSS 属性名不同,写法更接近 RN。
- scoped 默认生效:
.vue组件样式默认作用域隔离。 - 全局样式写在
App.vue的<style>;全局 SCSS 变量放uni.scss(自动注入,无需 import)。
六、本阶段必须掌握的知识点
- 内置组件用
<view>/<text>/<image>等;纯文字必须包<text>,<image>要显式设宽高与mode。 - easycom:组件按
components/名/名.vue放置即可免注册直接用,且按需打包。 - rpx:屏幕恒为 750rpx,设计稿 1:1 照搬,自动适配多屏;细边框等场景仍用 px。
- 条件编译:
#ifdef / #ifndef / #endif+ 平台标识,编译期裁剪多端差异代码。 - 样式跨端差异:小程序 CSS 支持有限、nvue 走原生排版、scoped 默认开启、uni.scss 全局变量。
七、高频面试题
Q1:什么是 easycom?它有什么好处?
A:easycom 是 uni-app 的组件自动引入机制。只要组件放在 components/组件名/组件名.vue(目录名与文件名一致),在任何页面无需 import、无需在 components 里注册就能直接使用。好处有二:① 省去重复的引入/注册样板;② 按需编译,未被使用的组件不会打进最终包,对小程序体积敏感场景很友好。也可在 pages.json 的 easycom.custom 里自定义匹配规则来接入第三方 UI 库。
追问:easycom 会不会把所有组件都打包进去导致包变大?
A:不会。easycom 是按使用情况引入的——它在编译时扫描模板里实际用到的标签,只编译打包被引用的组件,没用到的不会进包。所以它对包体积是正向优化,而非负担。
Q2:rpx 是什么?和 px、%、vw 有什么区别?
A:rpx 是 uni-app 的响应式单位,把任何设备的屏幕宽度都视为 750rpx,按设备实际宽度等比换算成物理像素,因此能用一套数值适配所有屏宽,且可与设计稿(750 宽)1:1 对应。区别:px 是固定物理/逻辑像素,不随屏宽缩放;% 相对父元素;vw 相对视口宽度(1vw=1% 视口宽,和 rpx 思路接近但基准不同,rpx 基准恒为 750)。做整体等比布局用 rpx,需要固定不缩放(如 1px 边框)用 px。
追问:为什么有时候 1rpx 的边框在某些手机上不显示或显示为 0?
A:因为 rpx 换算到高分屏时可能不足 1 物理像素,被渲染引擎抹掉。细线场景建议用 1px,或用 transform: scale(0.5) 的 0.5px 边框方案,保证在各 DPR 设备上稳定显示。
Q3:条件编译是什么?和运行时的 if (平台) 判断有何本质区别?
A:条件编译用 // #ifdef 平台 ... // #endif 注释包裹代码,在编译阶段根据目标平台决定该段代码是否进入产物。与运行时 if 的本质区别在于:条件编译是编译期裁剪——不满足条件的代码根本不存在于最终包里,因此更安全(微信包不含支付宝逻辑)、更省体积、也不会有运行时判断开销;而运行时 if 是所有代码都打包进去、运行时再判断,无法裁剪掉无关平台代码,还可能因调用了目标端不存在的 API 而报错。
追问:条件编译能用在哪些地方?
A:模板、脚本、样式、甚至 pages.json/manifest.json 以及静态资源目录都支持。JS/TS 用 // #ifdef,模板用 <!-- #ifdef -->,CSS 用 /* #ifdef */。还能用 APP-PLUS、MP-WEIXIN、MP(所有小程序)、H5 等标识,以及它们的组合。
Q4:为什么 uni-app 里 <view>你好</view> 不推荐,要写成 <view><text>你好</text></view>?
A:因为在小程序和 App 端,<view> 是容器组件,直接放文本节点在部分端存在兼容问题(如文字无法长按选中、样式表现不一致)。<text> 是专门承载文本的组件,纯文字应放入 <text>,才能保证跨端一致的显示与交互(如可选中、user-select)。这也是 uni-app 组件抽象的规范约束。