Radio单选框作为表单基础组件,在uni-app开发中常被简单用于性别选择等基础场景。但当面对中后台管理系统、动态配置页等复杂业务时,开发者往往需要更深入的解决方案。本文将突破基础教程限制,通过三个典型实战场景,展示如何充分发挥radio-group的潜力。
在大型表单应用中,单选框的状态管理常成为痛点。假设我们正在开发一个电商平台的运费模板配置页,其中包含多组互相关联的配送方式选项:
javascript复制// store/modules/shipping.js
export default {
state: () => ({
expressOptions: [
{ id: 'standard', label: '标准快递', disabled: false },
{ id: 'express', label: '特快专递', disabled: true },
{ id: 'pickup', label: '门店自提', disabled: false }
],
selectedExpress: ''
}),
mutations: {
UPDATE_SHIPPING_METHOD(state, payload) {
state.selectedExpress = payload
}
}
}
关键实现步骤:
mapState将状态映射到组件@change事件触发状态更新html复制<radio-group
@change="handleChange"
:value="selectedExpress">
<radio
v-for="item in expressOptions"
:key="item.id"
:value="item.id"
:disabled="item.disabled">
{{ item.label }}
</radio>
</radio-group>
常见问题解决方案:
| 问题类型 | 解决方案 | 代码示例 |
|---|---|---|
| 选项动态禁用 | 结合computed过滤 | :disabled="!isAvailable(item)" |
| 跨组件同步 | 使用store的getter | store.getters.currentShipping |
| 持久化存储 | 配合uni.setStorage | uni.setStorageSync('shipping', value) |
提示:在H5端使用Pinia时,注意处理SSR场景下的状态序列化问题,避免hydration不匹配
从后端API获取选项数据是常见需求,但不当实现会导致性能问题。以用户权限管理系统为例,我们需要渲染数百个权限选项:
javascript复制// 低效实现示例(不推荐)
<radio-group>
<radio
v-for="permission in permissions"
:key="permission.id"
:value="permission.code">
{{ permission.name }}
</radio>
</radio-group>
优化方案对比表:
| 优化手段 | 实施方法 | 收益点 |
|---|---|---|
| 分页加载 | 滚动触底加载 | 减少DOM节点 |
| 虚拟列表 | 使用uni-list组件 | 内存优化 |
| 数据分片 | 按模块分组加载 | 响应速度提升 |
| 本地缓存 | 持久化选项数据 | 减少请求 |
推荐实现代码:
javascript复制// 高效实现示例
export default {
data() {
return {
visiblePermissions: [], // 当前可见权限
allPermissions: [] // 全部权限数据
}
},
async created() {
// 分片加载数据
await this.loadPermissionChunk(0, 50)
},
methods: {
async loadPermissionChunk(start, size) {
const chunk = await api.getPermissions(start, size)
this.visiblePermissions = [...this.visiblePermissions, ...chunk]
}
}
}
key值设计原则:
在复杂配置场景中,单选框组间常存在联动关系。以保险产品配置器为例,选择保险类型后,对应的保额选项应动态变化:
html复制<!-- 主险类型选择 -->
<radio-group v-model="mainProductType" @change="updateSubOptions">
<radio value="health">健康险</radio>
<radio value="life">寿险</radio>
<radio value="accident">意外险</radio>
</radio-group>
<!-- 动态保额选项 -->
<radio-group v-model="selectedAmount">
<radio
v-for="amount in availableAmounts"
:key="amount"
:value="amount"
:disabled="amount > maxAmount">
{{ amount }}万元
</radio>
</radio-group>
联动逻辑实现:
javascript复制// 保额选项计算逻辑
computed: {
availableAmounts() {
const amountMap = {
health: [10, 20, 30],
life: [50, 100, 200],
accident: [5, 10, 15]
}
return amountMap[this.mainProductType] || []
},
maxAmount() {
return this.userLevel === 'vip' ? Infinity : 50
}
}
典型业务场景扩展:
javascript复制// 条件禁用示例
watch: {
selectedProduct(newVal) {
this.products.forEach(p => {
p.disabled = p.category !== newVal.category
})
}
}
uni-app默认的Radio样式可能不符合设计需求,通过CSS定制可以提升用户体验:
css复制/* 自定义Radio样式 */
.radio-custom {
transform: scale(1.2);
margin-right: 8px;
}
.radio-custom .uni-radio-input {
border-color: #2b9939;
}
.radio-custom .uni-radio-input.uni-radio-input-checked {
background-color: #2b9939;
}
交互增强技巧:
html复制<radio-group class="enhanced-radio">
<label class="radio-item" v-for="item in items">
<radio :value="item.value" />
<text class="label-text">{{ item.label }}</text>
<text class="hint-text">{{ item.hint }}</text>
</label>
</radio-group>
跨平台样式适配方案:
| 平台 | 适配要点 | 解决方案 |
|---|---|---|
| 微信小程序 | 默认绿色图标 | 重写radio样式 |
| H5 | 点击延迟 | 添加active伪类 |
| App | 原生组件层级 | 使用nvue重构 |
在实际项目中,我们发现合理使用CSS变量可以简化多主题适配:
css复制:root {
--radio-active-color: #2b9939;
--radio-disabled-color: #cccccc;
}
.uni-radio-input.uni-radio-input-checked {
background-color: var(--radio-active-color);
}