@langlibaitiao
2017-07-06T06:24:57.000000Z
字数 15643
阅读 1169
小程序
一 获取小程序的AppId
1 注册微信公众平台账号,登录:https://mp.weixin.qq.com,就可以在网站的“设置”-“开发者设置”中,查看到微信小程序的 AppID 。
注意:如果要以非管理员微信号在手机上体验该小程序,那么我们还需要操作“绑定开发者”。即在“用户身份”-“开发者”模块,绑定上需要体验该小程序的微信号。本文档默认注册帐号、体验都是使用管理员微信号。
二 微信开发者工具
1 我们需要通过开发者工具,来完成小程序创建和代码编辑。开发者工具集成了开发调试、代码编辑及程序发布等功能。
链接:开发者工具下载地址
三 创建项目
1 开发者工具安装完成后:
(1) 打开并使用微信扫码登录,
(2) 选择创建“项目”,填入上文获取到的AppID,
(3) 设置一个本地项目的名称(非小程序名称),比如“小程序demo”,并选择一个本地的文件夹作为代码存储的目录,
(4) 点击“新建项目”就可以了。
2 在创建过程中:
如果选择的本地文件夹是个空文件夹,开发者工具会提示,是否需要创建一个 quick start 项目。选择“是”,开发者工具会帮助我们在开发目录里生成一个简单的 demo。其中初始化了文件结构并包含了一些简单的文件。
3 项目创建成功后:
我们就可以点击该项目,进入并看到完整的开发者工具界面,点击左侧导航,在“编辑”里可以查看和编辑我们的代码,在“调试”里可以测试代码并模拟小程序在微信客户端效果,在“项目”里可以发送到手机里预览实际效果。
四 小程序文件目录结构介绍
在项目中我们可以看到四种文件类型:
(1) .js后缀的文件是脚本文件,页面的交互等代码在这里实现;
(2) .json后缀的文件是配置文件,主要是json数据格式存放,用于设置程序的配置效果;
(3) .wxss后缀的是样式表文件,类似于前端中的css,用于对界面进行美化;
(4) .wxml后缀的文件是页面结构文件,用于构建页面,在页面上增加控件。
1 该文件主要存放小程序的页面文件
2 注意:
(1) 小程序每个页面必须有.wxml和.js文件,其他两种类型的文件可以不需要。
(2) 文件名称必须与页面的文件夹名称相同,如index文件夹,文件只能是index.wxml、index.wxss、index.js和index.json.
(1) 该文件夹主要用于存放全局的一些.js文件,公共用到的一些事件处理代码文件可以放到该文件夹下,用于全局调用。
(2) 对于允许外部调用的方法,用module.exports进行声明,才能在其他js文件中用一下代码引入
function formatTime(date) {var year = date.getFullYear()var month = date.getMonth() + 1var day = date.getDate()var hour = date.getHours()var minute = date.getMinutes()var second = date.getSeconds()return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')}function formatNumber(n) {n = n.toString()return n[1] ? n : '0' + n}//发送请求 post方式var rootDocment = 'https://api.orangelife.com.cn/'; //正式// var rootDocment = 'http://eastapi.swao.cn/'; //测试function req(url, data, cb) {wx.request({url: rootDocment + url,data: data,method: 'POST',header: { 'Content-Type': 'application/json' },success: function (res) {console.log(res)return typeof cb == "function" && cb(res.data)},fail: function () {return typeof cb == "function" && cb(false)}})}//发送请求 get方式function getReq(url, data, cb) {wx.request({url: rootDocment + url,data: data,method: 'GET',header: { 'Content-Type': 'application/x-www-form-urlencoded' },success: function (res) {return typeof cb == "function" && cb(res.data)},fail: function () {return typeof cb == "function" && cb(false)}})}// 去前后空格function trim(str) {return str.replace(/(^\s*)|(\s*$)/g, "");}// 提示错误信息function isError(msg, that) {that.setData({showTopTips: true,errorMsg: msg})}// 清空错误信息function clearError(that) {that.setData({showTopTips: false,errorMsg: ""})}//上传文件function uploadFile(url, filePath, name, formData, cb) {console.log('a=' + filePath, formData)wx.uploadFile({url: rootDocment + url,filePath: filePath,name: name,header: {'content-type': 'multipart/form-data'}, // 设置请求的 headerformData: formData, // HTTP 请求中其他额外的 form datasuccess: function (res) {console.log(res)console.log(res.head_image)if (res.statusCode == 200 && !res.data.result_code) {return typeof cb == "function" && cb(res.head_image)} else {return typeof cb == "function" && cb(false)}},fail: function () {return typeof cb == "function" && cb(false)}})}//用module.exports对外暴露接口module.exports = {formatTime: formatTime,req: req,getReq: getReq,trim: trim,isError: isError,clearError: clearError,uploadFile: uploadFile}
//在需要使用这些模块的文件中,使用 require(path) 将公共代码引入var util = require('../../utils/util.js')
4.1 app.js :
1 小程序的脚本代码
我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。调用框架提供的丰富的 API,想了解更多可用 API,可参考 [API文档]
2 小程序注册
App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。
//app.jsApp({onLaunch: function () {//调用API从本地缓存中获取数据var logs = wx.getStorageSync('logs') || []logs.unshift(Date.now())wx.setStorageSync('logs', logs)},getUserInfo:function(cb){var that = thisif(this.globalData.userInfo){typeof cb == "function" && cb(this.globalData.userInfo)}else{//调用登录接口wx.login({success: function () {wx.getUserInfo({success: function (res) {that.globalData.userInfo = res.userInfotypeof cb == "function" && cb(that.globalData.userInfo)}})}})}},//全局参数,可以在其他页面通过接口获取到,全局使用的参数可以在这里进行声明globalData:{userInfo:null}})
//全局参数可以在其他页面通过下面方法获取到var app = getApp();console.log(app. globalData);
4.2 app.json :
是对整个小程序的全局配置。我们可以在这个文件中配置小程序是由哪些页面组成,配置小程序的窗口背景色,配置导航条样式,配置默认标题。注意该文件不可添加任何注释。更多可配置项可参考[配置详解]
部分配置解释:
(1) 此处tabBar下的list为底部列表栏配置;注意:tabBar如果设置,最少要两个,最多不能超过五个。
(2) networkTimeout和debug可以设置各种网络请求的超时时间
(3) debug:可以在开发者工具中开启debug模式,在开发者工具的控制台面板,调用信息以info的形式给出,其信息有page注册、页面路由、数据更新和时间触发,可以帮开发者快速定位一些常见信息。
/**app.json**/{"pages": ["pages/index/index","pages/mall/list/list","pages/login/login","pages/user/user","pages/mall/detail/detail","pages/location/location"],"window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": "pink","navigationBarTitleText": "智橙生活","navigationBarTextStyle": "black"},"tabBar": {"list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "images/tabBar/index.png","selectedIconPath": "images/tabBar/index-select.png"},{"pagePath": "pages/mall/list/list","text": "商城","iconPath": "images/tabBar/market.png","selectedIconPath": "images/tabBar/market-select.png"},{"pagePath": "pages/user/user","text": "个人中心","iconPath": "images/tabBar/setting.png","selectedIconPath": "images/tabBar/setting-select.png"}],"color": "#000","backgroundColor": "pink","selectedColor": "#f60","borderStyle": "#ccc"},"networkTimeout": {"request": 20000,"connectSocket": 20000,"uploadFile": 20000,"downloadFile": 20000},"debug": true}
4.3 app.wxss :
全局的界面美化代码
/**app.wxss**/@import "dist/style/weui.wxss";.container {height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: space-between;padding: 200rpx 0;box-sizing: border-box;}
1 注册一个页面
// detail.jsvar app = getApp();var util = require('../../../utils/util.js');Page({//页面数据配置data: {msgDetail: {},imgUrls:[],autoplay: true,indicatorDots: true,interval: 4000,duration: 1000},onLoad: function (options) {console.log(options)var that = this;util.req('mall/getItemDetailV4', {//请求接口// id: options.iditemId: options.itemId,activityId: options.activityId}, function (res) {that.setData({// 改变信息msgDetail: res.data.itemDetail,imgUrls: res.data.itemDetail.pics})});},onReady: function () {// 页面渲染完成},onShow: function () {// 页面显示},onHide: function () {// 页面隐藏},onUnload: function () {// 页面关闭}})
Page({}),注册一个页面,中间的代码为声明周期函数,可以不实现,但是Page({})结构必须创建。
注意:只有在data中声明的数据才能够正常使用
五 本demo中的一些方法与属性
整个系统分为两块视图层(View)和逻辑层(App Service)
框架可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
通过这个简单的例子来看:
index.wxml文件下:
<!--index.wxml--><view class="container"><view bindtap="bindViewTap" class="userinfo"><image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image><text class="userinfo-nickname">{{userInfo.nickName}}</text></view><view class="usermotto"><text class="user-motto">{{motto}}</text></view><button bindtap="changeName">{{clickData}}</button></view>
index.js文件如下:
//index.js//获取应用实例var app = getApp()Page({data: {motto: '综合服务生活平台',clickData: '点我试试',userInfo: {}},changeName: function (e) {this.setData({motto: "智橙生活",clickData: '试试就试试',})},onLoad: function () {var that = this//调用应用实例的方法获取全局数据app.getUserInfo(function(userInfo){//更新数据that.setData({userInfo:userInfo})})}})
开发者通过框架将逻辑层数据中的 moto 与视图层的 moto 进行了绑定,所以在页面一打开的时候会显示 点我试试
当点击按钮的时候,视图层会发送 changeName 的事件给逻辑层,逻辑层找到对应的事件处理函数
逻辑层执行了 setData 的操作,将 moto 从 点我试试 变为 试试就试试,因为该数据和视图层已经绑定了,从而视图层会自动改变为 试试就试试。
路由:页面跳转
调用 API wx.navigateTo 或使用组件 < navigator open-type="navigateTo" />
(1) 上拉加载,下拉刷新, 分页
// 下拉刷新数据pullDownRefresh: function () {var that = this;pageNum = 0;//tab0var objBuy0 = that.data.isBuying;objBuy0.msgList = [];//tab1var objBuy1 = that.data.isBuying;objBuy1.msgList = [];that.setData({isBuying: objBuy0,futureBuying: objBuy1,scrollTop: 0});loadMsgData0(that);},// 上拉加载数据pullUpLoad: function () {var that = this;if (!that.data.isLastPage) {loadMsgData0(that);}},
(2) 页面跳转
调用 API wx.navigateTo 或使用组件 <navigator open-type="navigateTo"/>
pages/mall/list/list.js
var util = require('../../../utils/util.js');var app = getApp();// 加载数据var loadMsgData0 = function (that) {//初始化隐藏列表var objBuy0 = that.data.isBuying;objBuy0.hidden = false;that.setData({isBuying: objBuy0});var allMsg = objBuy0.msgList;util.req('mall/getPanicBuyItemList', {"index": objBuy0.pageNum,"size": objBuy0.pageSize,"flag": "current"}, function (res) {//生成新的商品信息数组allMsg = allMsg.concat(res.page.content);objBuy0.hidden = true,objBuy0.msgList = allMsg,objBuy0.isLastPage = res.page.last,that.setData({isBuying: objBuy0});objBuy0.pageNum++;if (!!res.page.last){objBuy0.nomore = false;that.setData({isBuying: objBuy0});}});};var loadMsgData1 = function(that){//初始化隐藏列表var objBuy1 = that.data.futureBuying;objBuy1.hidden = false;that.setData({futureBuying: objBuy1});var allMsg = objBuy1.msgList;util.req('squareDance/getSquareDanceVideoPage', {"index": objBuy1.pageNum,"size": objBuy1.pageSize}, function (res) {console.log(res)//生成新的商品信息数组allMsg = allMsg.concat(res.content);objBuy1.hidden = true,objBuy1.msgList = allMsg,objBuy1.isLastPage = res.last,that.setData({futureBuying: objBuy1});objBuy1.pageNum++;if (!!res.last) {objBuy1.nomore = false;that.setData({futureBuying: objBuy1});}});};var loadMsgData2 = function (that) {//初始化隐藏列表var objBuy2 = that.data.futureBuying1;objBuy2.hidden = false;that.setData({futureBuying1: objBuy2});var allMsg = objBuy2.msgList;util.req('mall/getPanicBuyItemList', {"index": objBuy2.pageNum,"size": objBuy2.pageSize,"flag": "wait"}, function (res) {//生成新的商品信息数组allMsg = allMsg.concat(res.page.content);objBuy2.hidden = true,objBuy2.msgList = allMsg,objBuy2.isLastPage = res.page.last,that.setData({futureBuying1: objBuy2});objBuy2.pageNum++;if (!!res.page.last) {objBuy2.nomore = false;that.setData({futureBuying1: objBuy2});}});};//页面数据配置Page({data: {scrollTop: 0,scrollHeight: 0,//tab栏的下标pageTab: {curHdIndex: 0,curBdIndex: 0},isBuying: {hidden: true,isLastPage: false,nomore: true,pageNum: 0,pageSize: 7,msgList: []},futureBuying: {hidden: true,isLastPage: false,nomore: true,pageNum: 0,pageSize: 7,msgList: []},futureBuying1: {hidden: true,isLastPage: false,nomore: true,pageNum: 0,pageSize: 7,msgList: []}},pageHdtap: function (e) {var that = this;console.log(e)//点击子元素var _datasetId = e.target.dataset.id;var _leftObj = {};_leftObj.curHdIndex = _datasetId;_leftObj.curBdIndex = _datasetId;that.setData({scrollTop: 0,pageTab: _leftObj,isBuying: {hidden: true,isLastPage: false,nomore: true,pageNum: 0,pageSize: 7,msgList: []},futureBuying: {hidden: true,isLastPage: false,nomore: true,pageNum: 0,pageSize: 7,msgList: []}});if (_datasetId == 0) {//初始化第0页数据loadMsgData0(that);} else if (_datasetId == 1){//初始化第1页数据loadMsgData1(that);}else{//初始化第2页数据loadMsgData2(that);}},onLoad: function (options) {// 页面初始化 options为页面跳转所带来的参数var that = this;wx.getSystemInfo({success: function (res) {that.setData({windowHeight: res.windowHeight,windowWidth: res.windowWidth})}});loadMsgData0(that);},onReady: function () {// 页面渲染完成},onShow: function () {// 页面显示},// 下拉刷新数据pullDownRefresh: function () {var that = this;//0var objBuy0 = that.data.isBuying;objBuy0.pageNum = 0;objBuy0.msgList = [];//1var objBuy1 = that.data.futureBuying;objBuy1.pageNum = 0;objBuy1.msgList = [];var objBuy2 = that.data.futureBuying1;objBuy2.pageNum = 0;objBuy2.msgList = [];that.setData({isBuying: objBuy0,futureBuying: objBuy1,futureBuying1: objBuy2,scrollTop: 0});loadMsgData0(that);loadMsgData1(that);loadMsgData2(that);},// 上拉加载数据pullUpLoad: function () {var that = this;if (!that.data.isBuying.isLastPage) {loadMsgData0(that)}if (!that.data.futureBuying.isLastPage) {loadMsgData1(that)}if (!that.data.futureBuying1.isLastPage) {loadMsgData2(that)}},// 定位数据scroll: function (event) {var that = this;that.setData({scrollTop: event.detail.scrollTop});},onHide: function () {// 页面隐藏},onUnload: function () {// 页面关闭}})
pages/mall/list/list.json
{"navigationBarTitleText": "商品列表",//当前页面的标题}
pages/mall/list/list.wxml
<view class="page"><view class="page__bd"><!--用name 定义模版--><template name="msgTemp"><view class="weui-panel__bd"><!--页面路由跳转 --><navigator url="../detail/detail?itemId={{itemId}}&activityId={{activityId}}" class="weui-media-box weui-media-box_appmsg" hover-class="weui-cell_active"><view class="weui-media-box__hd weui-media-box__hd_in-appmsg"><image class="weui-media-box__thumb" src="{{coverPic}}" style="width: 60px; height: 60px;"/></view><view class="weui-media-box__bd weui-media-box__bd_in-appmsg"><view class="">{{name}}</view><view class="weui-media-box__desc">{{discountPrice}}</view></view></navigator></view></template><view class="top" catchtap="pageHdtap"><view class="tab01 {{pageTab.curHdIndex==0? 'active': ''}}" data-id="0">正在抢购</view><view class="tab02 {{pageTab.curHdIndex==1? 'active': ''}}" data-id="1">即将开抢</view></view><view class="tab-bd" style="height: 100%;"><!--tab1 start--><!--三目运算符 --><view class="tab-bd01 {{pageTab.curBdIndex==0? 'show': 'hide'}}" style="height: 100%;"><scroll-view scroll-top="{{scrollTop}}" style="height: {{windowHeight}}px; width: {{windowWidth}}px;" scroll-y="true" bindscrolltoupper="pullDownRefresh" bindscroll="scroll" bindscrolltolower="pullUpLoad" class="weui-panel weui-panel_access"><view wx:for-items="{{isBuying.msgList}}" wx:key="{{item.itemId}}"><view class="kind-list__item"><!--用is 使用模版--><template is="msgTemp" data="{{...item}}"/></view></view><view hidden="{{isBuying.nomore}}" class="noMore-content">没有更多了</view></scroll-view><view><loading hidden="{{isBuying.hidden}}" bindchange="loadingChange">加载中...</loading></view></view><!--tab1 end--><!--tab2 start--><view class="tab-bd02 {{pageTab.curBdIndex==1? 'show': 'hide'}}" style="height: 100%;"><scroll-view scroll-top="{{scrollTop}}" style="height: {{windowHeight}}px; width: {{windowWidth}}px;" scroll-y="true" bindscrolltoupper="pullDownRefresh" bindscroll="scroll" bindscrolltolower="pullUpLoad" class="weui-panel weui-panel_access"><view wx:for-items="{{futureBuying.msgList}}" wx:key="{{item.itemId}}"><view class="kind-list__item"><!--用is 使用模版--><template is="msgTemp" data="{{...item}}"/></view></view><view hidden="{{futureBuying.nomore}}" class="noMore-content">没有更多了</view></scroll-view><view><loading hidden="{{futureBuying.hidden}}" bindchange="loadingChange">加载中...</loading></view></view><!--tab2 end--></view></view><view class="page__ft"></view></view>
//detail.wxml<swiper class="detail-swiper" indicator-dots="{{indicatorDots}}" circular = "true"autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"><block wx:for="{{imgUrls}}"><swiper-item><image src="{{item}}" class="slide-image" width="355" height="250"/></swiper-item></block></swiper>// detail.jsvar app = getApp();var util = require('../../../utils/util.js');Page({data: {msgDetail: {},imgUrls:[],autoplay: true,indicatorDots: true,interval: 4000,duration: 1000},onLoad: function (options) {console.log(options)var that = this;util.req('mall/getItemDetailV4', {// id: options.iditemId: options.itemId,activityId: options.activityId}, function (res) {that.setData({msgDetail: res.data.itemDetail,imgUrls: res.data.itemDetail.pics})});},onReady: function () {// 页面渲染完成},onShow: function () {// 页面显示},onHide: function () {// 页面隐藏},onUnload: function () {// 页面关闭}})
(1) 获取位置
wx.getLocation(OBJECT) 获取当前的地理位置、速度。
wx.getLocation({type: 'gcj02', // 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标success: function (res) {that.setData({hasLocation: true,location: {longitude: res.longitude,latitude: res.latitude}})}})
(2)wx.openLocation(OBJECT) 使用微信内置地图查看位置
openLocation: function (e) {var value = e.detail.valuewx.openLocation({longitude:value.longitude,latitude: value.latitude,scale: 28})}
formSubmit: function (e) {var account = e.detail.value.account;var password = e.detail.value.password;var that = this;wx.login({success: function(res){if (res.code){wx.getUserInfo({success: function (res1) {//获取userinfo成功wx.request({url: 'https://api.orangelife.com.cn/loginV4',data: {appCode: null,mobile: account,password: password,captcha_code: '',captcha_token: ''},method: 'POST',// header: {}, // 设置请求的 header 默认是application/jsonsuccess: function (res) {console.log(res)// 操作json数据if (res.statusCode == 200) {wx.showModal({title: '登陆状态',content: '登陆成功',success: function (res) {console.log(res)if (res.confirm) {// 点击确定后跳转页面并关闭当前页面wx.switchTab({url: '../user/user'})}}})}},fail: function () {// fail},complete: function () {// complete}})},fail: function () {// 调用微信弹窗接口wx.showModal({title: '警告',content: '您点击了拒绝授权,将无法正常使用***的功能体验。请10分钟后再次点击授权,或者删除小程序重新进入。',success: function (res) {if (res.confirm) {console.log('用户点击确定')}}})}})}else{console.log('获取用户登录态失败!' + res.errMsg)}}})}
更多信息
[微信公众平台开发者社区]
[框架、组件、API、工具]
[微信小程序联盟]