2018-09-17

小程序

1 创建项目

  • 我们需要通过开发者工具,来完成小程序创建和代码编辑。
  • 开发者工具安装完成后,打开并使用微信扫码登录。选择创建“项目”,填入上文获取到的 AppID ,设置一个本地项目的名称(非小程序名称),比如“我的第一个项目”,并选择一个本地的文件夹作为代码存储的目录,点击“新建项目”就可以了。
  • 为方便初学者了解微信小程序的基本代码结构,在创建过程中,如果选择的本地文件夹是个空文件夹,开发者工具会提示,是否需要创建一个 quick start 项目。选择“是”,开发者工具会帮助我们在开发目录里生成一个简单的 demo。

2 代码编写

  • 点击开发者工具左侧导航的“编辑”,我们可以看到这个项目,已经初始化并包含了一些简单的代码文件。最关键也是必不可少的,是 app.js、app.json、app.wxss 这三个。其中,.js后缀的是脚本文件,.json后缀的文件是配置文件,.wxss后缀的是样式表文件。微信小程序会读取这些文件,并生成小程序实例。
  • app.js是小程序的脚本代码。我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。调用框架提供的丰富的 API,如本例的同步存储及同步读取本地数据。想了解更多可用 API,可参考 API 文档。
//app.js
App({
  onLaunch: function () {
    //调用API从本地缓存中获取数据
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  getUserInfo:function(cb){
    var that = this;
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //调用登录接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo;
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        }
      });
    }
  },
  globalData:{
    userInfo:null
  }
})
  • app.json 是对整个小程序的全局配置。我们可以在这个文件中配置小程序是由哪些页面组成,配置小程序的窗口背景色,配置导航条样式,配置默认标题。注意该文件不可添加任何注释。更多可配置项可参考配置详解。
{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"black"
  }
}
  • app.wxss 是整个小程序的公共样式表。我们可以在页面组件的 class 属性上直接使用 app.wxss 中声明的样式规则。
/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
}
  • 每一个小程序页面是由同路径下同名的四个不同后缀文件的组成,如:index.js、index.wxml、index.wxss、index.json。.js后缀的文件是脚本文件,.json后缀的文件是配置文件,.wxss后缀的是样式表文件,.wxml后缀的文件是页面结构文件

3 项目目录

|- components  组件目录
|- assets  静态资源目录
  |- images
  ... ...
|- pages  小程序页面
  |- index  
    |- index.js
    |- index.json
    |- index.wxml
    |- index.wxss
  |- login
    |- login.js
    |- login.json
    |- login.wxml
    |- login.wxss
   ......
|- utils 公共方法目录
  |- util.js
  ......
|- app.js 小程序主入口
|- app.json 全局配置文件
|- app.wxss 全局样式文件

4 生命周期

4.1 App

  • App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。
App({
  onLaunch: function(options) {
    // Do something initial when launch.
  },
  onShow: function(options) {
      // Do something when show.
  },
  onHide: function() {
      // Do something when hide.
  },
  onError: function(msg) {
    console.log(msg)
  },
  globalData: 'I am global data'
})
  • getApp()
  • 我们提供了全局的 getApp() 函数,可以获取到小程序实例。
// other.js
var appInstance = getApp()
console.log(appInstance.globalData) // I am global data

注意:

  • App() 必须在 app.js 中注册,且不能注册多个。

  • 不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例。

  • 不要在 onLaunch 的时候调用 getCurrentPage(),此时 page 还没有生成。

  • 通过 getApp() 获取实例之后,不要私自调用生命周期函数。

4.2 Page

  • Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。
Page({
  data: {
    text: "This is page data."
  },
  onLoad: function(options) {
    // Do some initialize when page load.
  },
  onReady: function() {
    // Do something when page ready.
  },
  onShow: function() {
    // Do something when page show.
  },
  onHide: function() {
    // Do something when page hide.
  },
  onUnload: function() {
    // Do something when page close.
  },
  onPullDownRefresh: function() {
    // Do something when pull down.
  },
  onReachBottom: function() {
    // Do something when page reach bottom.
  },
  onShareAppMessage: function () {
   // return custom share data when user share.
  },
  // Event handler.
  viewTap: function() {
    this.setData({
      text: 'Set some data for updating view.'
    })
  },
  customData: {
    hi: 'MINA'
  }
})
生命周期函数
  • onLoad: 页面加载
    • 一个页面只会调用一次,可以在 onLoad 中获取打开当前页面所调用的 query 参数。
  • onShow: 页面显示
    • 每次打开页面都会调用一次。
  • onReady: 页面初次渲染完成
    • 一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
    • 对界面的设置如wx.setNavigationBarTitle请在onReady之后设置。详见生命周期
  • onHide: 页面隐藏
    • 当navigateTo或底部tab切换时调用。
  • onUnload: 页面卸载
    • 当redirectTo或navigateBack的时候调用。
页面相关事件处理函数
  • onPullDownRefresh: 下拉刷新
    • 监听用户下拉刷新事件。
    • 需要在config的window选项中开启enablePullDownRefresh。
    • 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。
  • onShareAppMessage: 用户分享
    • 只有定义了此事件处理函数,右上角菜单才会显示“分享”按钮
    • 用户点击分享按钮的时候会调用
    • 此事件需要 return 一个 Object,用于自定义分享内容
Page({
  onShareAppMessage: function () {
    return {
      title: '自定义分享标题',
      path: '/page/user?id=123'
    }
  }
})

5 路由跳转

  • wx.navigateTo(OBJECT)
wx.navigateTo({
  url: 'test?id=1'
})
Page({
  onLoad: function(option){
    console.log(option)
  }
})
  • wx.redirectTo(OBJECT)
    关闭当前页面,跳转到应用内的某个页面。

  • wx.reLaunch(OBJECT)
    关闭所有页面,打开到应用内的某个页面。

  • wx.switchTab(OBJECT)
    跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

{
  "tabBar": {
    "list": [{
      "pagePath": "index",
      "text": "首页"
    },{
      "pagePath": "other",
      "text": "其他"
    }]
  }
}
wx.switchTab({
  url: '/index'
})
  • wx.navigateBack(OBJECT)
    关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages()) 获取当前的页面栈,决定需要返回几层。
// 注意:调用 navigateTo 跳转时,调用该方法的页面会被加入堆栈,而 redirectTo 方法则不会。见下方示例代码

// 此处是A页面
wx.navigateTo({
  url: 'B?id=1'
})

// 此处是B页面
wx.navigateTo({
  url: 'C?id=1'
})

// 在C页面内 navigateBack,将返回A页面
wx.navigateBack({
  delta: 2
})

tip: wx.navigateTo 和 wx.redirectTo 不允许跳转到 tabbar 页面,只能用 wx.switchTab 跳转到 tabbar 页面

6 发起请求

  • wx.request(OBJECT)
    wx.request发起的是 HTTPS 请求。
wx.request({
  url: 'test.php', //仅为示例,并非真实的接口地址
  data: {
     x: '' ,
     y: ''
  },
  header: {
      'content-type': 'application/json'
  },
  success: function(res) {
    console.log(res.data)
  }
})
  1. tip: content-type 默认为 'application/json'
  2. bug: 开发者工具 0.10.102800 版本,header 的 content-type 设置异常;
  3. tip: 客户端的 HTTPS TLS 版本为1.2,但 Android 的部分机型还未支持 TLS 1.2,所以请确保 HTTPS 服务器的 TLS 版本支持1.2及以下版本;
  4. tip: 要注意 method 的 value 必须为大写(例如:GET);
  5. tip: url 中不能有端口;
  6. tip: request 的默认超时时间和最大超时时间都是 60s
  7. tip: request 的最大并发数是 5
  8. tip: 网络请求的 referer 是不可以设置的,格式固定为 https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 为小程序的 appid,{version} 为小程序的版本号,版本号为 0 表示为开发版。

7 WXSS

  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

8 模板

  • WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。

    定义模板

  • 使用name属性,作为模板的名字。然后在 < template/>内定义代码片段

<template name="postItem">
  <view class="post-container">
    <view class="post-author-date">
      <image class="post-author" src="{{avatar}}"></image>
      <text class="post-date">{{date}}</text>
    </view>
    <text class="post-title">{{title}}</text>
    <image class="post-image" src="{{imgSrc}}"></image>
    <text class="post-content">{{content}}
    </text>
    <view class="post-like">
      <image class="post-like-image" src="/images/icon/chat.png"></image>
      <text class="post-like-font">{{collection}}</text>
      <image class="post-like-image" src="/images/icon/view.png"></image>
      <text class="post-like-font">{{reading}}</text>
    </view>
  </view>
</template>

使用模板

  • 使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入。
<import src="post-item/post-item-template.wxml" />

<template is="postItem" data="{{...item}}" />

item 是模板所需要的数据。模板中不能写js,只是数据展示。

9 配置

  • 我们使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/logs",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true
}

pages

  • 接受一个数组,每一项都是字符串,来指定小程序由哪些页面组成。每一项代表对应页面的【路径+文件名】信息,数组的第一项代表小程序的初始页面。小程序中新增/减少页面,都需要对 pages 数组进行修改。

window

  • 用于设置小程序的状态栏、导航条、标题、窗口背景色。

tabBar

  • 如果我们的小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),那么我们可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。

Tip: 通过页面跳转(wx.navigateTo)或者页面重定向(wx.redirectTo)所到达的页面,即使它是定义在 tabBar 配置中的页面,也不会显示底部的 tab 栏。

tabBar 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。

tabBar的样式是固定的。上边为图标,下边为文字说明。

10 常用组件

11 搜索小程序

  • 小程序又增新流量入口,支持自定义关键词搜索。6月3日凌晨3点多,微信小程序后台新增推广功能,支持开发者添加与业务相关的自定义关键词,搜索策略将于6月9日正式生效。开发者可在小程序后台的 “推广” 模块中,配置与小程序业务相关的关键词

值得注意的是,小程序可配置最多10个与业务相关的关键词,关键词在审核通过后,会和小程序的服务质量、用户使用情况等因素,共同影响搜索结果。每30天可以修改3次。

关键词设置 可配置最多10个与业务相关的关键词,关键词在审核通过后,会和小程序的服务质量、用户使用情况等因素,共同影响搜索结果。

相关链接

12 wx.login(OBJECT)

  • 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)。用户数据的加解密通讯需要依赖会话密钥完成。
//app.js
App({
  onLaunch: function() {
    wx.login({
      success: function(res) {
        if (res.code) {
          //发起网络请求
          wx.request({
            url: 'https://test.com/onLogin',
            data: {
              code: res.code
            }
          })
        } else {
          console.log('获取用户登录态失败!' + res.errMsg)
        }
      }
    });
  }
})

code 换取 session_key

​ 这是一个 HTTPS 接口,开发者服务器使用登录凭证 code 获取 session_key 和 openid。其中 session_key 是对用户数据进行加密签名的密钥。为了自身应用安全,session_key 不应该在网络上传输。

接口地址:

//正常返回的JSON数据包
{
      "openid": "OPENID",
      "session_key": "SESSIONKEY"
}
//错误时返回JSON数据包(示例为Code无效)
{
    "errcode": 40029,
    "errmsg": "invalid code"
}

13 微信小程序支付

要先到微信公众平台开通微信支付,绑定微信支付商户号

步骤

A:小程序向服务端发送商品详情、金额、openid

B:服务端向微信统一下单

C:服务器收到返回信息二次签名发回给小程序

D:小程序发起支付

E:服务端收到回调

小程序向服务端发送商品详情、金额、openid

  wx.request({
    url:'test.php',
    data:{
      openid:'',     //openid
      tatal_free:'', //商品金额
      wx_body:''     //商品描述
    }
  })

然后服务端接收小程序发来的信息后 会发起统一下单

服务器下单完成后会返回签名参数

{
  'timeStamp': '',
  'nonceStr': '',
  'package': '',
  'signType': 'MD5',
  'paySign': ''
}

前端拿到签名参数后发起支付

wx.requestPayment({
  'timeStamp': '',
  'nonceStr': '',
  'package': '',
  'signType': 'MD5',
  'paySign': '',
  'success':function(res){
    wx.showToast({
      title: '支付成功'
    })
  },
  'fail':function(res){},
  'complete':function(res){}
})

几点注意

  • 如果有需要,建议只在项目目录中放置少量icon类的小图片,其他大图片可以上传到自己的服务器或者网盘中,然后在src中设置图片的网络资源地址。

  • wx.request(object)中method的请求方式默认为GET。有效值: OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT。经过测试,若使用小写,在安卓中会导致无法发起请求,而在开发者工具和ios中则正常。

  • 小程序执行wx.request(object)发送请求并收到success(成功)的消息后,会自动收到这样的回调参数:

  {
    data:'服务器返回的数据',
    errMsg:'错误信息',
    statusCode:HTTP状态码
  }

特别注意,在开发者工具和ios中,res.statusCode的数据类型是一个数值,而在Android中的数据类型是一个字符串,所以在判断res.statusCode时不能直接使用===操作符,而应该使用==操作符。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 小程序 基本知识 项目文件 JSON 配置 小程序配置 app.json app.json 是对当前小程序的全局配...
    勇敢的_心_阅读 1,335评论 0 6
  • 转载链接 注:本文转载知乎上的回答 作者:初雪 链接:https://www.zhihu.com/question...
    pengshuangta阅读 28,476评论 9 295
  • 文/骑马上岸的人 当黎明露出雪白的牙齿 妇人家的房顶升起炊烟 未熟的面汤冒着热气 染红了陶碗 星罗密布的粮食 也被...
    骑马上岸的人阅读 421评论 2 2
  • 东北的冬天很寒冷,惊吓三十摄氏度的气温,滴水成冰。 儿时我臭美,常喜欢穿漂亮的雪地靴,然而往往越是漂亮...
    稚气未脱A阅读 221评论 1 1
  • 松树 不争春 春己到 不争艳 素在雅中俏 不居高 低中风不疾 不为艳 芬芳伴春晓 问花不语百花闹 素面清颜迎春笑 ...
    松树_0909阅读 213评论 0 5