微信小程序中实现自定义多选效果(完整实现及问题记录)

一、原有实现步骤,抛出问题:
  1. 需求:小程序中实现自定义多选效果 | 点击高亮 / 取消还原默认样式
  2. js层:用数组保存选中 ID,点击时增删数组
  3. wxml层:循环展示 + 判断是否选中来切换样式
  4. 问题:看似实现没问题,但是初始化选中和点击选中的样式效果,完全没有
二、解决问题(切换写法):

js层把数组换成对象的方式,来存储选中状态,模型wxml层,把 includes() 换成对象属性访问 [ ] ,就好了。

三、完整代码(涵盖从使用数组,到切换成对象的完整留痕)
javascript 复制代码
Page({
	data: {
		scenes: [{
				id: 'home',
				icon: '🏠',
				name: '家庭日常'
			},
			{
				id: 'park',
				icon: '🌳',
				name: '户外公园'
			},
			{
				id: 'call',
				icon: '📞',
				name: '接打电话'
			},
			{
				id: 'tv',
				icon: '📺',
				name: '电视/广播'
			},
			{
				id: 'restaurant',
				icon: '🍽️',
				name: '嘈杂餐厅'
			}
		],

		 // 第一种:初始化选中【数组方式】
		// selectedScenes: ['home'],

		// 第二种:初始化选中【对象方式】
		selectedScenes: {  
			home: true,
			park: false,
			call: false,
			tv: false,
			restaurant: false
		},
	},

	toggleScene_A_Method(e) {
		// 1. 获取点击的场景 ID(从 data-id 传过来)
		const sceneId = e.currentTarget.dataset.id

		// 2. 复制一份当前选中数组(不直接修改原数据)
		const selectedScenes = [...this.data.selectedScenes]

		// 3. 查找这个 ID 是否已经在选中数组里
		const index = selectedScenes.indexOf(sceneId)

		if (index > -1) {
			// 已选中 → 取消选中(删除)
			selectedScenes.splice(index, 1)
		} else {
			// 未选中 → 添加选中
			selectedScenes.push(sceneId)
		}
		console.warn("当前选中",this.data.selectedScenes);

		// 4. 更新到页面数据
		this.setData({
			selectedScenes
		})
	},

	toggleScene_B_Method(e) {
		const sceneId = e.currentTarget.dataset.id
		const selectedScenes = { ...this.data.selectedScenes }
		// 直接取反
		selectedScenes[sceneId] = !selectedScenes[sceneId]  
		this.setData({ selectedScenes })
	}

})
html 复制代码
<view class="scene-section">
	<text class="section-title">选择今日聆听的生活场景(多选)</text>
	<view class="scene-options">
		<block wx:for="{{scenes}}" wx:key="id">
			<!-- 第一种,对应使用includes()方式【导致初始选中和点击选中,样式完全失效】 : 
			 class="scene-item {{selectedScenes.includes(item.id) ? 'selected' : ''}}"
			-->
			<!-- 第二种, 使用对象属性访问【多选的初始选中和点击完全生效~】 -->
			<view class="scene-item {{selectedScenes[item.id] ? 'selected' : ''}}" bindtap="toggleScene_B_Method"
				data-id="{{item.id}}">
				<text>{{item.icon}} {{item.name}}</text>
			</view>
		</block>
	</view>
</view>
css 复制代码
.scene-section {
  padding: 30rpx;
}

.section-title {
  font-size: 28rpx;
  color: #333;
  margin-bottom: 20rpx;
}

.scene-options {
  display: flex;
  flex-wrap: wrap;
  gap: 20rpx;
}

.scene-item {
  flex-grow: 1;
  padding: 24rpx 40rpx;
  background: #f8fafc;
  border-radius: 20rpx;
  text-align: center;
  font-size: 28rpx;
  color: #64748b;
  border: 2rpx solid #e2e8f0;
}

.scene-item.selected {
  background: #e0f2fe;
  border-color: #0ea5e9;
  color: #0369a1;
}
四、总结(这是找到解释,原理我没有深究为什么小程序中不行)
  1. 初始化问题 :小程序中数组初始值有时不会被正确应用,而对象可以
  2. 模板兼容 : includes() 在 WXML 模板中兼容性不好,对象属性访问 [] 更稳定
  3. 更新效率 :对象直接修改属性比数组的 splice/push 更直接,视图更新更及时
相关推荐
独角鲸网络安全实验室16 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
fix一个write十个21 小时前
【uniApp开发】微信小程序 web-view 内嵌 H5 跳转支付踩坑实录
微信小程序·uni-app
棋宣1 天前
微信小程序onShareAppMessage 分享-生命周期函数 在vue3中 组合式函数 hooks中不生效
微信小程序·小程序
好赞科技2 天前
深度测评2026年精选美发预约小程序排行榜 革新预约新体验 修订
大数据·微信小程序
一颗无敌码农2 天前
多商户与多门店电商系统有什么区别?核心模式解析
微信小程序·php·用户运营·crmeb
hhzz2 天前
记录微信小程序tabbar不显示问题:uni-app Vue 3 自定义 tabBar 不渲染
vue.js·微信小程序·uni-app
Greg_Zhong2 天前
微信小程序中调用豆包【免费】模型,实现小程序版ai助手完整版
微信小程序·豆包模型·调用豆包模型封装ai助手
30763 天前
uni-app在微信小程序国际化分包方案:优雅解决主包体积超限问题
微信小程序
打瞌睡的朱尤3 天前
微信小程序50~75
微信小程序·小程序