微信小程序入门级实战开发指南

微信小程序入门级实战开发指南

概述

微信小程序,简称小程序,英文名Mini Program,是一种“不需要下载安装”即可使用的应用(实际上是需要下载安装的,只是整个过程被简化到可以让用户忽略的地步),它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。
小程序基于HTML5标记语言发展而来,微信团队将HTML、CSS、JS等语言的大量常用组件进行封装,形成了一套全新的开发语言。小程序已然形成了一个新的生态系统,官方公布了大量组件和开发API,如要系统的学习一遍必然费时费力,在实际的项目开发中,应该找出项目的基本要素,从这些基本要素入手,加快开发速度。比如最近公司有一个需求,写一个可以访问后台数据库数据的微信小程序,主要任务是用来浏览数据,基于安全原因写的操作只有在PC端才能执行。那么要实现这个一个主要是展示数据作用的小程序,对于从来没了解过小程序的小白来说,我总结了以下几点必然要实现的基本要素:

  • 开发者认证以及开发者工具
  • 小程序基本架构
  • 常用组件如 Text、Butoon
  • Page
  • 数据库交互

开发者认证以及开发者工具

要开发小程序,必须先进入小程序官网通注册成为小程序开发者,网址:
https://developers.weixin.qq.com/miniprogram/dev/
认证成功证明可以进行小程序的开发了,在菜单 “设置”-“开发设置” 看到小程序的 AppID。这个AppID非常重要,代表了一个开发者的ID,一个开发者只能有一个AppID,该开发者每发布、修改、升级一个小程序,都需要此APPID,见下图:
image

上图中还有一处配置服务器域名需要特别注意,任何与后台服务器的交互操作都需要经过微信的认证,比如我们公司的域名 http://www.action-prowave.com,我们在小程序中如果要对该域名的数据进行访问,则必须将该域名在上图地方进行申请,否则在访问中将会报错,提示“不信任的域名”。并且,小程序只支持https开头的域名,像我公司这种http开头的域名必须升级为https域名,否则也会报错
完成小程序开发者认证后,下载小程序官方推出的开发工具既可进行小程序的开发,下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html?t=18112122

小程序基本架构

新建一个小程序,输入上文中申请的AppID(如不输入AppID也可以开发,但是该程序最终无法发布上线),创建一个QuickStart项目既可。见下图:image

图中有四种格式的文件,分别是JSONWXMLWXSSJSpages文件夹包含indexlogs两个文件夹,pages表示页面,所有的页面都应该放到这里,比如indexlogs,是两个不同的页面。

JSON 文件

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 文件

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表示布局及控件的属性定义,比如布局的宽、高、颜色、大小等等。classWXSS文件中定义。bindtap表示绑定的事件,{{}}表示定义把一个变量绑定到界面上,也就是数据绑定,这些数据处理逻辑都在JS 文件中定义。

扫描二维码关注公众号,回复: 8537193 查看本文章

WXSS 文件

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中的样式。

JS 文件

wxml 定义了需要展示的控件,wxss 定义了布局该怎样展示,布局有了,还需要和用户的交互,这些逻辑处理都定义在 JS 文件中。
JSJavaScript,同样的,小程序中的 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控件赋值
    })
  },

Page

上文小程序目录结构图中可以看到根目录有一个 pages 的文件夹,该文件夹中又包含了indexlogs 文件夹,这分别代表两个不同的页面,都包含 wxmlwxssjs文件。其中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),并且对 JSONGSON 数据有很好的支持,大大方便了我们对数据库的增、删、改、查操作。

对数据库执行"增"操作

这里以销量统计后台服务器(以前做好的后台)作为案例讲解,插入一条数据到数据库代码示例,在 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, 并且登录小程序官网,在 开发设置-服务器域名 中配置好域名

上一篇 一键设置 DeviceAdmin/ProfileOwner/DeviceOwner 应用
下一篇 等待更新, 先来主页看看有什么是你要的?
发布了25 篇原创文章 · 获赞 31 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/visionliao/article/details/84944688
今日推荐