以前做的程序主要是PC端网页,或者手机端H5页面,对于小程序开发还未接触过,今天抽点时间对小程序开发进行学习。
下面我将详细的记录从账号注册,设置,开发的每个步骤
1. 注册开发账号
打开微信开发者页面,选择小程序注册 https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token=
选择个人开发者
注册成功后登陆系统
2. 后台设置
2.1 新建一个小程序
注意 个人账号下,一个账号只能创建一个小程序,需要创建多个小程序就需要在去注册不同的账号
2.2 AppId和AppSecret
申请后这两个配置后续需要在程序中使用,一定要安全的保管
2.3 设置后台接口的域名
只有设置后,前台调用后台的api接口才能调通,并且该域名必须是备案通过的
3. 开发
3.1 下载小程序开发工具
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 下载自己电脑对应的版本
3.2 创建小程序前端项目
打开小程序开发工具,项目---》新建项目----》 小程序 ---》 填入AppID
3.3 小程序前端开发
下面我将以一个表单录入为例,展示小程序的开发,里面不涉及到微信的一些权限,只是一个表单的保存动作,后面我们将通过其他章节再来学习小程序的一些鉴权或者微信支付等
3.3.1 项目的结构
其中页面在index.wxml 中 ,逻辑在 index.js 中
3.3.2 页面 index.wxml
页面中使用了时间控件,下拉框控件,二级联动,单选按钮,以及选择控件
修改页面或者js后,直接在左边就可以进行调试
页面代码 index.wxml 如下
1 <!--引入时间控件页面--> 2 <import src="../picker/picker.wxss"/> 3 4 <view class="container"> 5 6 7 <view class="bg-fff p-lr30 border-t"> 8 9 10 <view class="tui-picker-content ipt-wrap border-b flex ai-center"> 11 <label for="" class="font14">日期</label> 12 <picker mode="date" value="{{dateSelectd}}" start="1975-01-01" end="2099-01-01" bindchange="changeDate"> 13 <view class="tui-picker-detail ml40 flex1"> 14 {{dateSelectd}} 15 </view> 16 </picker> 17 </view> 18 19 <view class="ipt-wrap border-b flex ai-center"> 20 <label for="" class="font14">部门</label> 21 <picker name="picker_hx" class="ml40 flex1 region" value="{{depts[dept_index].deptId}}" range="{{depts}}" range-key="{{'deptName'}}" 22 bindchange="bindPickerChange_hx"> 23 <view class="picker" > 24 {{depts[dept_index].deptName}} 25 </view> 26 </picker> 27 </view> 28 29 30 <view class="ipt-wrap border-b flex ai-center"> 31 <label for="" class="font14">姓名</label> 32 <picker name="picker_emp" class="ml40 flex1 region" value="{{emps[emp_index].empId}}" range="{{emps}}" range-key="{{'empName'}}" 33 bindchange="bindEmp" > 34 <view class="picker" > 35 {{emps[emp_index].empName}} 36 </view> 37 </picker> 38 </view> 39 40 41 42 43 </view> 44 <view class=" bg-fff p30 flex ai-center jc-sb mt20"> 45 <view class="flex ai-center"> 46 <label for="" class="font14">用餐时间</label> 47 </view> 48 <radio-group class="radio-group" bindchange="lunchOrDinerBind"> 49 <label class="radio" wx:for="{{lunchOrDiner}}"> 50 <radio value="{{item.name}}" checked="{{item.checked}}"/>{{item.name}} 51 </label> 52 </radio-group> 53 </view> 54 55 <view class=" bg-fff p30 flex ai-center jc-sb mt20"> 56 <view class="flex ai-center"> 57 <label for="" class="font14">饭菜类型</label> 58 </view> 59 <radio-group class="radio-group" bindchange="mealTypeBind"> 60 <label class="radio" wx:for="{{mealType}}"> 61 <radio value="{{item.name}}" checked="{{item.checked}}"/>{{item.name}} 62 </label> 63 </radio-group> 64 65 </view> 66 67 <view class=" bg-fff p30 flex ai-center jc-sb mt20"> 68 <view class="flex ai-center"> 69 <label for="" class="font14">是否用餐</label> 70 </view> 71 <view class="flex"> 72 <switch class="switch" bindchange="eatOrNotBind" color="#279efd" checked="checked"></switch> 73 </view> 74 </view> 75 76 <view class="combtn font16 color-fff _w100 bg-btn" data-url="../addNewAddress/addNewAddress" bindtap="saveNewAddress"> 77 保存 78 </view> 79 </view>
3.3.3 页面 index.js
页面控件的绑定数据,绑定时间,校验,从后台取数据都在改方法中
我们定义了一个eat.js 所有的对后台接口的操作都在改js中执行 ,在index.js 中对eat.js做了引入
3.3.3.1 index.js 代码
// const common = require('../../utils/common'); // const api = require('../../utils/api'); const eat = require("../../utils/eat.js"); const dateTimePicker = require('../../utils/dateTimePicker.js'); const app = getApp(); Page({ data: { dateSelectd:'', depts:[], dept_index: 0, deptId:0, emps:[], emp_index:0, lunchOrDiner: [{id:1,name:'午餐',checked:true},{id:2,name:'晚餐'}], lunchOrDinerValue:'午餐', mealType:[{id:1,name:'荤素',checked:true},{id:2,name:'纯素'}], mealTypeValue :"荤素", eatOrNot:'是', userID: 0 }, onLoad: function (){ let self = this; this.setData({ userID: app.globalData.userID }); let dateDefault = eat.getDate(); this.setData({ dateSelectd: dateDefault }); this.getDept() //获取部门信息 }, changeDate:function(e){ let dateSelectd = e.detail.value; this.setData({ dateSelectd:dateSelectd }); }, getDept: function() { eat.getDept().then(res => { this.setData({ depts:res }); if(res && res.length > 0){ eat.getEmp(res[0].deptId).then(res =>{ this.setEmp(res); }); } }) }, bindPickerChange_hx: function (e) { console.log('picker发送选择改变,下标为', e.detail.value); this.setData({ //给变量赋值 dept_index: e.detail.value, //每次选择了下拉列表的内容同时修改下标然后修改显示的内容,显示的内容和选择的内容一致 }); let deptId = this.data.depts[e.detail.value].deptId; console.log("deptId:"+deptId); eat.getEmp(deptId).then(res =>{ this.setEmp(res); }); }, setEmp:function(emps){ this.setData({ emps:emps }); }, bindEmp: function (e) { console.log('picker发送选择改变,下标为', e.detail.value); this.setData({ //给变量赋值 emp_index: e.detail.value, //每次选择了下拉列表的内容同时修改下标然后修改显示的内容,显示的内容和选择的内容一致 }); }, lunchOrDinerBind:function(e) { let lunchOrDinerValue = e.detail.value; console.log("lunchOrDinerValue:"+lunchOrDinerValue); this.setData({ lunchOrDinerValue: lunchOrDinerValue }); }, mealTypeBind:function (e) { this.setData({ mealTypeValue: e.detail.value, }); }, eatOrNotBind:function(event){ let checkedValue = event.detail.value; console.log("checkedValue:"+checkedValue); let eatOrNot; if(checkedValue){ eatOrNot ="是"; }else{ eatOrNot ="否"; } this.setData({ eatOrNot:eatOrNot, }); }, saveNewAddress: function () { let self = this; let dateStr = self.data.dateSelectd let deptId = self.data.depts[self.data.dept_index].deptId; let deptName = self.data.depts[self.data.dept_index].deptName; let empId = self.data.emps[self.data.emp_index].empId; let empName = self.data.emps[self.data.emp_index].empName; let lunchOrDinerValue = self.data.lunchOrDinerValue; let mealTypeValue = self.data.mealTypeValue; let eatOrNot = self.data.eatOrNot; let today = eat.getDateStr(0); let tommorrow = eat.getDateStr(1); if(dateStr !=today && dateStr != tommorrow){ this.alertError('只能定今天和明天的餐哦'); return; } if(dateStr == today){ let date=new Date(); let hour = date.getHours(); let minute = date.getMinutes(); if(lunchOrDinerValue == "晚餐"){ //晚餐时间必须在13:30-17:30 if(hour<13 || hour>17){ this.alertError('晚餐订购时间为13:30-17:30'); return; } if(hour == 13 && minute < 30 ){ this.alertError('晚餐订购时间为13:30-17:30'); return; } if(hour == 17 && minute>30){ this.alertError('晚餐订购时间为13:30-17:30'); return; } }else{ //午餐订购时间为09:00-11:30 if(hour <9 || hour > 11){ this.alertError('午餐订购时间为09:00-11:30'); return; } if(hour == 11 && minute >30){ this.alertError('午餐订购时间为09:00-11:30'); return; } } }; wx.showModal({ title: '提示', content: '确定订餐么', success: function(res) { if (res.confirm) { wx.showLoading({ title: '订餐中...', }); eat.save(deptId,deptName,empId,empName,dateStr,lunchOrDinerValue,eatOrNot,mealTypeValue).then(res =>{ wx.hideLoading(); console.log("result:"+res); if(res == 0){ self.alertError('已经定过了哦'); return; }else{ self.alertError('订餐成功'); return; } }); } else if (res.cancel) { this.alertError('用户撤销订餐'); } } }); }, alertSucess:function(msg){ wx.showToast({ title: msg+'', icon: 'success', duration: 2000 }) }, alertError:function(msg){ wx.showToast({ title: msg+'', icon: 'none', duration: 2000 }) } });
3.3.3.2 eat.js 代码
let backend_url = 'https://xxxx.com'; /** * 查询部门列表,数据格式如下 * [{"deptId":33,"deptName":"开发部"}] */ function getDept(){ return new Promise((resolve,reject) => { wx.request({ url: backend_url+'/eat/getDeptList', data: { }, header: { 'content-type': 'application/json' }, success: function(res) { resolve(res.data) } }) }) } /** * 查询部门下的员工,返回格式如下, * [{"empId":1,"empName":"devin","deptId":33},{"empId":2,"empName":"zbb","deptId":33}] */ function getEmp(deptId){ return new Promise((resolve,reject) => { wx.request({ url: backend_url+'/eat/getEmpList?deptId='+deptId, data: { }, header: { 'content-type': 'application/json' }, success: function(res) { resolve(res.data) } }) }) } /** * 保存数据 */ function save(dept,deptName,emp,empName,today,eatType,eatIf,eatMealType){ return new Promise((resolve,reject) => { wx.request({ url: backend_url+'/eat/save', data: { deptId: dept, deptName: deptName, empId: emp, empName: empName, eatDate: today, eatType: eatType, eatIf: eatIf, eatMealType : eatMealType }, header: { 'content-type': 'application/json' }, success: function(res) { resolve(res.data); } }) }) } /** * 获取当前时间 */ function getDate(){ var date = new Date(); var mon = date.getMonth() + 1; var day = date.getDate(); var nowDay = date.getFullYear() + "-" + (mon<10?"0"+mon:mon) + "-" +(day<10?"0"+day:day); return nowDay; } /** * 获取日期 * getDateStr(0) 今天 * getDateStr(-1) 昨天 * getDateStr(1) 明天 */ function getDateStr(addDayCount) { var dd = new Date(); dd.setDate(dd.getDate()+addDayCount);//获取addDayCount天后的日期 var y = dd.getFullYear(); var m = dd.getMonth()+1;//获取当前月份的日期 var d = dd.getDate(); var mStr = m>=10?m:'0'+m; return y+"-"+mStr+"-"+d; } module.exports = { getDate:getDate, getDateStr:getDateStr, getDept: getDept, getEmp:getEmp, save:save, }
后端代码不在此做展示,只需要返回正确格式的json即可
4. 发布
程序开发完成后,点击开发工具中的上传按钮,即可将代码上传到服务端,此时登录微信的后台管理端,就可以看到我们上传的前端程序,点击发布,待微信审核通过后,就可以在微信中使用小程序了。
5. 代码
完整的代码已经上传到github上了,有需要的小伙伴可以下载参考使用