制作微信投票小程序的5步关键流程与实战技巧
说到制作投票微信小程序,第一反应是去搜“微信小程序投票模板”或者“第三方投票工具”。这些方法要么功能受限,要么有广告,要么数据不在自己手里。真正想要一个干净、灵活、能长期用的投票小程序,动手自己做一个反而更靠谱。下面我会从零开始,像一步步教朋友那样,带你走通整个流程。
一、投票小程序到底能做什么?先想清楚需求
很多教程一上来就教你怎么写代码,但忽略了最重要的一步:想清楚你的投票是用来干什么的。投票小程序不是只能“选A或B”,它其实可以分几类:
单选投票:比如“你最喜欢的颜色是?”这种只能选一个的。适合决策类场景,比如团队聚餐选餐厅。
多选投票:比如“你用过以下哪些手机品牌?”可以选多个。适合调研类场景,比如收集用户偏好。
匿名投票:谁投了票其他人看不到。适合敏感话题,比如员工满意度调查。
带图片/视频的投票:比如“哪个设计方案更好?”直接展示图片。适合设计评审、产品选型。
我见过一个真实的案例:一个创业团队用简单的投票小程序做“内部创意评比”,每个成员上传自己的方案图片,全员匿名投票,几分钟就定下来,比开会讨论高效得多。所以先想清楚你的投票类型,后面开发会少走弯路。
二、准备工作:注册小程序账号 + 安装开发工具这一步觉得繁琐,但其实只要按顺序来,10分钟就能搞定。
第一步:注册微信小程序账号
去微信公众平台(mp.weixin.qq.com)点击“立即注册”,选择“小程序”。注意:邮箱要没注册过微信公众平台,一个邮箱只能绑定一个小程序。注册成功后,你会得到一个 AppID(在“开发”->“开发设置”里),这个后面要用。
第二步:下载开发者工具
到微信官方文档下载“微信开发者工具”,安装后打开,用刚才注册的账号扫码登录。新建项目时,勾选“不使用云服务”(除非你想用云开发,后面会讲),填入 AppID,项目名称随便取,比如“投票小程序”。
这里有个小技巧:新建项目后直接开始写代码,但其实可以先看看官方给的“demo”模板。在新建项目时选择“使用 JavaScript - 基础模板”,它会生成一个简单的页面,你可以先跑起来看看效果,再在此基础上改。
三、核心功能实现:从页面设计到逻辑代码投票小程序的核心就三个页面:投票列表页(展示所有投票)、投票详情页(展示具体选项和投票按钮)、结果页(展示投票结果)。我拿一个“单选投票”举例,一步步拆解。
1. 投票列表页(pages/index/index)
这个页面要显示所有投票的标题、状态(进行中/已结束)、参与人数。代码结构如下:
wxml(页面结构)
<view class="container">
<view wx:for="{{voteList}}" wx:key="id" class="vote-item" bindtap="goToDetail" data-id="{{item.id}}">
<text class="title">{{item.title}}</text>
<text class="status">{{item.status == 1 ? '进行中' : '已结束'}}</text>
<text class="count">{{item.voteCount}}人参与</text>
</view>
</view>
js(逻辑代码)
这里要注意:不要直接把数据写死在代码里。实际开发中,数据要从后端获取。但为了演示,我们先模拟数据:
Page({
data: {
voteList: [
{ id: 1, title: '周末团建去哪里?', status: 1, voteCount: 23 },
{ id: 2, title: '新Logo哪个更好?', status: 0, voteCount: 56 }
]
},
goToDetail(e) {
const id = e.currentTarget.dataset.id;
wx.navigateTo({
url: '/pages/detail/detail?id=' + id
});
}
})
这里有个坑:用 wx.navigateTo 跳转时,发现页面白屏。检查一下路径是否写对了,以及 app.json 里是否注册了 detail 页面。
2. 投票详情页(pages/detail/detail)
这个页面展示投票标题、选项列表、投票按钮。关键点在于:如何防止重复投票?
最简单的方法是用本地缓存记录用户的投票记录。但这样不够严谨,因为用户换个手机或者清除缓存就能再投。更靠谱的是用微信的 openid 做唯一标识,配合后端数据库记录。这里我讲一个折中方案:用云开发数据库。
如果你用微信云开发(在开发者工具里点击“云开发”开通),可以直接用云数据库存储投票记录。每个用户投票时,先查数据库里有没有这个用户对当前投票的记录,有就提示“已投票”,没有就写入记录。
代码示例(detail.js):
const db = wx.cloud.database();
Page({
data: {
vote: null,
selectedOption: null,
voted: false
},
onLoad(options) {
const id = options.id;
// 从数据库获取投票数据
db.collection('votes').doc(id).get().then(res => {
this.setData({ vote: res.data });
});
// 检查当前用户是否已投票
this.checkVoted(id);
},
checkVoted(voteId) {
const openid = wx.getStorageSync('openid'); // 或从云函数获取
db.collection('vote_records').where({
voteId: voteId,
userId: openid
}).get().then(res => {
if (res.data.length > 0) {
this.setData({ voted: true });
}
});
},
selectOption(e) {
const index = e.currentTarget.dataset.index;
this.setData({ selectedOption: index });
},
submitVote() {
if (this.data.voted) {
wx.showToast({ title: '你已经投过票了', icon: 'none' });
return;
}
if (this.data.selectedOption === null) {
wx.showToast({ title: '请选择一个选项', icon: 'none' });
return;
}
// 提交投票到数据库
const db = wx.cloud.database();
const voteId = this.data.vote._id;
const optionIndex = this.data.selectedOption;
db.collection('votes').doc(voteId).update({
data: {
[`options.${optionIndex}.count`]: db.command.inc(1)
}
}).then(() => {
// 记录用户已投票
db.collection('vote_records').add({
data: {
voteId: voteId,
userId: wx.getStorageSync('openid'),
optionIndex: optionIndex
}
}).then(() => {
this.setData({ voted: true });
wx.showToast({ title: '投票成功' });
});
});
}
})
这里有个细节:直接用 wx.getUserInfo 获取 openid,但微信已经调整了接口。正确的做法是用 wx.cloud.callFunction 调用云函数获取 openid。云函数代码很简单:
// 云函数 getOpenid
exports.main = async (event, context) => {
return {
openid: wx.cloud.getWXContext().OPENID
};
};
然后在页面里调用:
wx.cloud.callFunction({
name: 'getOpenid'
}).then(res => {
wx.setStorageSync('openid', res.result.openid);
});
这样就能确保每个用户的唯一性,防止刷票。
四、进阶优化:让投票小程序更好用基础功能做完后,有几个点可以大大提升体验:
1. 实时更新结果
很多投票小程序投完票后需要手动刷新才能看到结果。可以用微信的 WebSocket 或者云开发的 watch 方法实现实时更新。比如用云开发 watch:
const watcher = db.collection('votes').doc(voteId).watch({
onChange: function(snapshot) {
// snapshot.docs 包含最新数据
this.setData({ vote: snapshot.docs[0] });
},
onError: function(err) {
console.error(err);
}
});
这样用户投完票,结果页的数字会自动变化,体验像直播一样。
2. 投票截止时间
在数据库里加一个 endTime 字段,页面加载时判断当前时间是否超过 endTime,超过则禁用投票按钮。代码:
const now = new Date();
const endTime = new Date(this.data.vote.endTime);
if (now > endTime) {
this.setData({ expired: true });
}
3. 分享投票给好友
在 detail 页面添加 onShareAppMessage 方法:
onShareAppMessage() {
return {
title: this.data.vote.title,
path: '/pages/detail/detail?id=' + this.data.vote._id
};
}
这样好友点击分享卡片就能直接进入投票页面,传播效率很高。
五、避坑指南:常见问题与解决方案开发过程中我踩过不少坑,分享几个典型的:
问题1:数据更新后页面不刷新
用 setData 更新数据,但发现界面没变。检查一下:setData 的 key 是否正确?如果是数组里的某个元素,要用 `data.vote.options[0].count` 这种路径,而不是直接 `data.vote.options[0].count`。另外,setData 是异步的,如果需要在更新后做操作,要放在回调里。
问题2:云开发数据库权限
默认情况下,云数据库只允许创建者读写。你需要去云开发控制台设置权限。比如投票记录表,可以设置为“所有用户可读,仅创建者可写”,但投票记录表需要“所有用户可写”。具体设置:在云开发控制台 -> 数据库 -> 选择集合 -> 权限设置,改成“自定义规则”。
问题3:用户授权问题
现在微信小程序不能直接弹窗获取用户信息了。如果非要用到用户头像昵称,可以用 wx.getUserProfile(但微信也在逐步收紧)。更推荐的做法是:让用户自己填写昵称,或者直接用 openid 做标识,不展示用户信息。投票场景下,匿名反而更受欢迎。
六、扩展思路:投票小程序还能怎么玩?投票小程序不止是“选一个选项”这么简单。我见过一些

