赞
踩
微信小程序,简称小程序,英文名Mini Program,是一种“不需要下载安装”即可使用的应用(实际上是需要下载安装的,只是整个过程被简化到可以让用户忽略的地步),它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。
小程序基于HTML5标记语言发展而来,微信团队将HTML、CSS、JS等语言的大量常用组件进行封装,形成了一套全新的开发语言。小程序已然形成了一个新的生态系统,官方公布了大量组件和开发API,如要系统的学习一遍必然费时费力,在实际的项目开发中,应该找出项目的基本要素,从这些基本要素入手,加快开发速度。比如最近公司有一个需求,写一个可以访问后台数据库数据的微信小程序,主要任务是用来浏览数据,基于安全原因写的操作只有在PC端才能执行。那么要实现这个一个主要是展示数据作用的小程序,对于从来没了解过小程序的小白来说,我总结了以下几点必然要实现的基本要素:
- 开发者认证以及开发者工具
- 小程序基本架构
- 常用组件如 Text、Butoon
- Page
- 数据库交互
要开发小程序,必须先进入小程序官网通注册成为小程序开发者,网址:
https://developers.weixin.qq.com/miniprogram/dev/
认证成功证明可以进行小程序的开发了,在菜单 “设置”-“开发设置” 看到小程序的 AppID。这个AppID非常重要,代表了一个开发者的ID,一个开发者只能有一个AppID,该开发者每发布、修改、升级一个小程序,都需要此APPID,见下图:
上图中还有一处配置服务器域名需要特别注意,任何与后台服务器的交互操作都需要经过微信的认证,比如我们公司的域名 http://www.action-prowave.com,我们在小程序中如果要对该域名的数据进行访问,则必须将该域名在上图地方进行申请,否则在访问中将会报错,提示“不信任的域名”。并且,小程序只支持https开头的域名,像我公司这种http开头的域名必须升级为https域名,否则也会报错。
完成小程序开发者认证后,下载小程序官方推出的开发工具既可进行小程序的开发,下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html?t=18112122
新建一个小程序,输入上文中申请的AppID(如不输入AppID也可以开发,但是该程序最终无法发布上线),创建一个QuickStart项目既可。见下图:
图中有四种格式的文件,分别是JSON、WXML、WXSS、JS。pages文件夹包含index和logs两个文件夹,pages表示页面,所有的页面都应该放到这里,比如index和logs,是两个不同的页面。
JSON 文件为小程序配置文件,可以配置小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。最外层的app.json为全局配置文件,内容如下:
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
pages:用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录,当前示例小程序有两个页面,index和logs。
window:定义小程序所有页面的顶部背景颜色,文字颜色定义等。
具体页面中可以复写这些默认设置,比如logs页面的logs.json文件:
{
"navigationBarTitleText": "查看启动日志"
}
那么index界面显示的头部标题为默认的 WeChat,而logs界面显示的头部标题为 查看启动日志。
WXML 是小程序的布局文件,所有的控件都在这里申明、绑定事件(事件的处理逻辑在js中)。类似网页编程中的HTML文件,而wxml原本就是从HTML演化而来,只是WXML封装了很多HTML标签的用法,使得开发更加的简洁高效。
比如定义一个布局,包含一个button组件和一个text组件:
<view class="container">
<view class="userinfo">
<button bindtap='testButton'>我是一个按钮</button>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>
其中class表示布局及控件的属性定义,比如布局的宽、高、颜色、大小等等。class在WXSS文件中定义。bindtap表示绑定的事件,{{}}表示定义把一个变量绑定到界面上,也就是数据绑定,这些数据处理逻辑都在JS 文件中定义。
WXSS 样式文件由 CSS演化而来,WXSS 具有 CSS 大部分的特性,比如上文中的最外层布局 ,其定义在全局样式app.wxss文件中:
/**app.wxss**/
.container {
// 布局高度占满屏幕
height: 100%;
// 弹性布局
display: flex;
// 对不确定的宽和高,我们都可以让他垂直居中对齐
flex-direction: column;
align-items: center;
justify-content: space-between;
// 设置内边距,距离上边距200rpx,右边距0,下边距0,左边距0
padding: 200rpx 0;
// 允许以特定的方式定义匹配某个区域的特定元素
box-sizing: border-box;
}
也可以在当前所属页面的文件夹中(作用域)的wxss文件中的样式文件中定义.container样式,用以覆盖全局app.wxss中的样式。
wxml 定义了需要展示的控件,wxss 定义了布局该怎样展示,布局有了,还需要和用户的交互,这些逻辑处理都定义在 JS 文件中。
JS 即 JavaScript,同样的,小程序中的 JS 也对传统的 JS 进行了封装,但大致逻辑一致。例如:
展示一个 text 文本
WXML 文件
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
WXSS 文件
.usermotto {
margin-top: 10px; // 距离上边距间隔10px
}
JS 文件
Page({
data: {
motto: 'Hello World' // 在界面上显示Hello World这行文本
},
展示一个 button 控件的点击事件
WXML 文件 <view class="test-settext"> <button bindtap='setText'>点我设置文字</button> </view> <view class="usermotto"> <text class="user-motto">{{motto}}</text> </view> WXSS 文件 .test-settext { margin-top: 50px; // 距离上边框间隔50px color: rgb(194, 22, 22); // 颜色 } .usermotto { margin-top: 10px; // 距离上边距间隔10px } JS 文件 Page({ data: { motto: 'Hello World' // 在界面上显示Hello World这行文本,该值为默认文本 }, // button控件绑定的事件 setText: function (e) { this.setData({ motto: '改变了我' // 为motto这个text控件赋值 }) },
上文小程序目录结构图中可以看到根目录有一个 pages 的文件夹,该文件夹中又包含了index 和 logs 文件夹,这分别代表两个不同的页面,都包含 wxml、wxss、js文件。其中logs 里面还有一个 json 文件,json为项目配置文件,如非必要,可不必在每个 page 中都配置。
Page 相当于Android中的Activity,有其特有的生命周期函数。尝试创建一个 test 页面, 先在 pages 中创建一个文件夹 test , 然后在 test 中分别创建以下四个文件:
test.json 代码
{
"navigationBarTitleText": "测试页面"
}
test.wxml 代码
<!--pages/test/test.wxml-->
<view class="container-test">
<view class="show-ui">
<text bindtap='testReturn' class="test-return">{{test}}</text>
</view>
</view>
test.wxss 代码
/* pages/test/test.wxss */ .container-test { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; box-sizing: border-box; } /* text-align: center; line-height: 500px; 居中*/ .show-ui { width: 300px; height: 500px; border: solid 1px black; display: flex; align-items: center; justify-content: center; } .test-return { color: blue; }
test.js 代码
// pages/test/test.js Page({ /** * 页面的初始数据 */ data: { test: '展示界面,点击返回' }, /** * button点击事件,返回上一页 */ testReturn: function(e) { wx.navigateBack({ changed: true }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { console.log("test 生命周期函数--页面加载"); this.setData({ test: options.testKey + ',点击我返回上个界面' }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { console.log("test 生命周期函数--页面初次渲染完成"); }, /** * 生命周期函数--监听页面显示 */ onShow: function () { console.log("test 生命周期函数--页面显示"); }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { console.log("test 生命周期函数--页面隐藏"); }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { console.log("test 生命周期函数--页面卸载"); }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { console.log("test 页面用户下拉动作"); }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { console.log("test 页面上拉触底事件"); }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { console.log("test 頁面用户点击右上角分享"); } })
最后,在 app.json 中配置页面路径:
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/test/test"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
}
}
对于任何类型的程序,和数据库的交互几乎是不可或缺的,小程序作为基于 html5 的网页类型程序,必然会和数据库有很频繁的交互。小程序封装了访问数据库接口 wx.request(Object object),并且对 JSON、GSON 数据有很好的支持,大大方便了我们对数据库的增、删、改、查操作。
这里以销量统计后台服务器(以前做好的后台)作为案例讲解,插入一条数据到数据库代码示例,在 pages 文件夹下新建 addData 文件夹,然后在 addData 中创建以下三个文件:
addData.wxml
<!--pages/databases/addData.wxml--> <view class="container-test"> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='baseband' placeholder="基带版本号" bindinput='basebandInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='hwVer' placeholder="硬件版本号" bindinput='hwVerInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='location' placeholder="地址" bindinput='locationInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='macid' placeholder="MAC地址" bindinput='macidInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='manufacture' placeholder="生产厂商" bindinput='manufactureInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='meid' placeholder="MEID" bindinput='meidInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='model' placeholder="设备型号" bindinput='modelInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='operator' placeholder="运营商" bindinput='operatorInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='osVer' placeholder="OS版本" bindinput='osVerInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='pName' placeholder="P-NAME" bindinput='pNameInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='sn' placeholder="SN" bindinput='snInput'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='sn2' placeholder="SN2" bindinput='sn2Input'></input> <input type='text' placeholder-style="color:#e2e2e2;" class='input-css' name='swVer' placeholder="软件版本号" bindinput='swVerInput'></input> <view class="add"> <button class='add-css' bindtap='addData'>添加数据</button> </view> </view>
addData.wxss
/* pages/databases/addData.wxss */ .container-test { height: 100%; width: 100%; box-sizing: border-box; } .input-css { margin: 5px; width: 100%; border: solid 1px #e2e2e2; } .add { margin-top: 10px; }
addData.js
// pages/databases/addData.js Page({ /** * 页面的初始数据 */ data: { baseband: '', hwVer: '', location: '', macid: '', manufacture: '', meid: '', model: '', operator: '', osVer: '', pName: '', sn: '', sn2: '', swVer: '' }, basebandInput: function(e) { this.setData({ baseband: e.detail.value }) }, hwVerInput: function (e) { this.setData({ hwVer: e.detail.value }) }, locationInput: function (e) { this.setData({ location: e.detail.value }) }, macidInput: function (e) { this.setData({ macid: e.detail.value }) }, manufactureInput: function (e) { this.setData({ manufacture: e.detail.value }) }, meidInput: function (e) { this.setData({ meid: e.detail.value }) }, modelInput: function (e) { this.setData({ model: e.detail.value }) }, operatorInput: function (e) { this.setData({ operator: e.detail.value }) }, osVerInput: function (e) { this.setData({ osVer: e.detail.value }) }, pNameInput: function (e) { this.setData({ pName: e.detail.value }) }, snInput: function (e) { this.setData({ sn: e.detail.value }) }, sn2Input: function (e) { this.setData({ sn2: e.detail.value }) }, swVerInput: function (e) { this.setData({ swVer: e.detail.value }) }, addData: function (e) { let params; params = '{"_id":0' + ',"baseband":' +'"' + this.data.baseband + '"' + ',"hwVer":' + '"' + this.data.hwVer + '"' + ',"location":' + '"' + this.data.location + '"' + ',"macId":' + '"' + this.data.macid + '"' + ',"manufacture":' + '"' + this.data.manufacture + '"' + ',"meid":' + '"' + this.data.meid + '"' + ',"model":' + '"' + this.data.model + '"' + ',"operator":' + '"' + this.data.operator + '"' + ',"osVer":' + '"' + this.data.osVer + '"' + ',"pName":' + '"' + this.data.pName + '"' + ',"sn":' + '"' + this.data.sn + '"' + ',"sn2":' + '"' + this.data.sn2 + '"' + ',"swVer":' + '"' + this.data.swVer + '"' + '}'; console.log("input value: " + params); wx.request({ url: 'http://www.action-prowave.com:端口号/服务器访问入口地址', header: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST", data: { json_params: params }, success: function(res) { console.log("success: " + res.data + ", result code: " + res.statusCode); }, fail: function(res) { console.log("fail: " + res.errMsg + ", result code: " + res.statusCode); } }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } })
最后还需要配置在app.json文件中配置页面路径:
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/test/test",
"pages/databases/addData"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
}
}
可以看到,采用POST的方式请求,服务端插入一条数据的请求地址为 http://www.action-prowave.com:端口号/(省略), 所带的参数为用户在界面输入的值,测试可成功插入数据到后台服务器。
还是以销量统计后台服务器(以前写好的后台)作为案例讲解,查询出数据库中所有的数据。在 pages 文件夹下新建 queryData 文件夹,然后在 queryData 中创建以下三个文件:
queryData.wxml
<!--pages/databases/queryData.wxml-->
<import src="../cataTemp/listItem.wxml"/>
<view class="main">
<view class="device-view">
<text class="device-info">{{deviceInfo}}</text>
</view>
</view>
queryData.wxss
/* pages/databases/queryData.wxss */
.device-info {
margin-left: 10px;
margin-right: 10px;
}
queryData.js
// pages/databases/queryData.js Page({ /** * 页面的初始数据 */ data: { deviceInfo: '所有设备数据' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var self = this; wx.request({ url: 'http://www.action-prowave.com:端口号/访问服务器入口地址', data: { }, header: { 'content-type': 'application/json' // 默认为json格式 }, method: 'POST', success: function(res) { console.log("success: " + JSON.stringify(res.data)); if (res.statusCode == 200) { self.setData({ deviceInfo: JSON.stringify(res.data) // 由于我的后台数据设计的就是gson数据格式,这里将将获取到的gson数据转换成String类型,以便显示 }) } }, fail: function(res) { console.log("fail: " + res.errMsg); } }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } })
最后在app.json文件中配置页面路径:
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/test/test",
"pages/databases/addData",
"pages/databases/queryData"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
}
}
服务器读取所有数据访问地址为 http://www.action-prowave.com:端口号/(省略), 也是采用POST方式请求,并且,服务器端的数据格式当初设计的是一个数据集合,返回一个List,并转换成了 GSON 格式数据返回,这种类型的数据不能直接显示。小程序为 JSON、GSON 格式数据提供了很好的支持,只需要调用 JSON.stringify(Object obj) 既可将格式化的集合类型数据转换成字符串。 当然也可以将字符串转换成 JSON 数据,也可以和 Map 等数据格式的集合类型数据进行互相转换。
由于我有一点网页编程的基础,这个小需求最终在1.5天搞定。针对一个全新领域的开发,实战是最好的老师。在需求下来后,切忌盲目折腾,提前制定好针对性的目标也很重要。
http 开头的域名不能在小程序服务器中声明认证,该域名只有在测试的时候可临时访问,真正发布上线版本后没有在小程序服务器中认证的域名将无法访问,必须将服务器域名升级为 https, 并且登录小程序官网,在 开发设置-服务器域名 中配置好域名。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。