微信小程序开发日记

Xiaoma 学习记录 2021-02-19

小程序开发和安卓开发很像,同样也有生命周期的概念,而且函数也是on*()之类的,所以相似度极高。
小程序由渲染层和逻辑层组成,渲染层主要由WXML(WeiXin Markup Language)和WXSS(WeiXin Style Sheets)负责,逻辑层由js(javascript)负责,相关配置文件则由JSON负责。

代码风格方面,无论是WXML、WXSS还是JSON,写法和格式都十分相像,为了区分,可通过以下例子加以区别理解
首先展示JavaScript的实例代码:

// pages/wxml/index.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    time:(new Date()).toString(),
    item:{
      index:0,
      msg:'this is a template',
      time:(new Date()).toString
    },
    length:5,
    array:[{
      message:'foo'
    },{
      message:'bar'
    }],
    objectArray:[
      {id:0,unique:'unique_0'},
      {id:1,unique:'unique_1'},
      {id:2,unique:'unique_2'},
      {id:3,unique:'unique_3'},
      {id:4,unique:'unique_4'}
    ]
  },
  switch_1:function(e){
    const length=this.data.objectArray.length
    for(let i=0;i<length;++i){
      const x = Math.floor(Math.random()*length)
      const y = Math.floor(Math.random()*length)
      const temp = this.data.objectArray[x]
      this.data.objectArray[x]=this.data.objectArray[y]
      this.data.objectArray[y]=temp
    }
    this.setData({
      objectArray:this.data.objectArray
    })
  },
  addToFront: function(e) {
    const length = this.data.objectArray.length
    this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
    this.setData({
      objectArray: this.data.objectArray
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
  }
})

然后是WXML的示例代码,与Html类似

!--pages/wxml/index.wxml-->
<text>pages/wxml/index.wxml</text>
<!--image class="userinfo-avator" src="./image/a.png"></image-->
<text>当前时间:{{time}}</text>      <!--time是个变量名,通过{{x}}的方式使用变量x-->
<block wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
<!--使用block相当于创造了一个局部环境-->
<view>{{idx}}:{{itemName.message}}</view>  <!--array数组里有很多个item,每个item里面有很多key-value,其中message就是一个key
<view>{{idx}}</view>
</block>
<block wx:if="{{length>1}}">
  <view>{{length}}</view>
</block>
<switch wx:for="{{objectArray}}" wx:key="unique">{{item.id}}</switch>
<button bindtap="switch_1">Switch</button>    <!--bindtap表示绑定事件函数,其中函数在js中定义-->
<button bindtap="addToFront"> Add to the front</button>
<template name="msgItem">   <!--定义模板-->
  <view>
    <text>{{index}}:{{msg}}</text>
<!--此时的index,msg一般是传给模板的数据中的参数,在未使用data="xx"的情况下不会直接使用js中data下的内容-->
    <text>Time:{{time}}</text>
  </view>
</template>
<!--调用模板,注意此时不是name="xxx"而是is="xxx"-->
<template is="msgItem" data="{{...item}}"></template>   <!--...表示传递参数给模板-->

接着再是Wxss的示例代码,功能和写法上与css差不多

/app.wxss/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
}

最后是JSON部分的示例,和一般的JSON一样

{
  "pages":[
    "pages/wxml/index",
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "MniProgram",
    "navigationBarTextStyle":"black"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

上述代码分别是js,wxml,wxss,json中的某些片段,通过了解和比较,可以发现wxml的写法和html很像,wxss和css很像。值得说明的是,json中不允许使用注释,其中pages下的内容为所注册的页面文件(在工程中是一个文件夹,其文件夹中包括了js,wxml,wxss,也就是页面的组成内容文件)。
渲染层和逻辑层之间并不直接联系,而是通过一个宿主来进行间接联系的,这个宿主就是微信客户端(Native),这里直接引用微信公众平台开发文档中的插图
curve
整个模型主要是以数据作为驱动的,逻辑工作由js来负责,其中调用的API接口也是由Native来进行提供,所以小程序除了考虑是否兼容手机型号以外,还需要考虑兼容用户当前的微信版本,当用户当前版本的微信不能提供所需要的API时,应该及时提醒用户更新客户端。
对于小程序中的页面,当有多个页面时,存储这些的数据结构是栈,在此被称为页面栈。页面栈所容纳的页面不能超过10个,一般打开页面有两种方式:一种是创建一个新的空间并入栈,另一种是直接把栈顶的页面替换(就和浏览器是否在新标签页打开网站一样)。

我们采用这样的方式进行描述页面栈:[ pageA, pageB, pageC ],其中pageA在最底下,pageC在最顶上,也就是用户所看到的界面,需要注意在本书编写的时候,小程序宿主环境限制了这个页面栈的最大层级为10层 ,也就是当页面栈到达10层之后就没有办法再推入新的页面了。我们下面来通过上边这个页面栈描述以下几个和导航相关的API。 使用 wx.navigateTo({ url: 'pageD' }) 可以往当前页面栈多推入一个 pageD,此时页面栈变成 [ pageA, pageB, pageC, pageD ]。 使用 wx.navigateBack() 可以退出当前页面栈的最顶上页面,此时页面栈变成 [ pageA, pageB, pageC ]。 使用wx.redirectTo({ url: 'pageE' }) 是替换当前页变成pageE,此时页面栈变成 [ pageA, pageB, pageE ],当页面栈到达10层没法再新增的时候,往往就是使用redirectTo这个API进行页面跳转。 --微信公众平台开发文档

curve
值得说明的是,数据的回调不能直接通过赋值语句来进行,而是需要统一通过下列操作

this.setData({
   key:value
   //key:this.data.key  若改变了本身
})

在与用户的交互反馈方面,常见的有hover(触摸),Toast(信息提示),对话框以及界面滚动等等,例如触摸一个按钮但最终没有点击

.hover{
  background-color: gray;
}
<button hover-class="hover" bindtap="addToFront"> Add to the front</button>

按照以上代码执行,当按住按钮但不松手时,按钮的背景色会变成灰色。
curve
下面演示Toast的使用和效果

wx.showToast({
  title: '操作成功!',
  icon:'success',
  duration:2000   //显示时间
})

curve
对于滚动操作,例如下拉刷新,可以直接调用宿主(Native)的Refresh,实现如下

onPullDownRefresh:function(){
  //下拉后的操作
}

在json中,需要添加如下配置

"enablePullDownRefresh": true

curve
小程序向开发者服务器请求数据以及得到回包的示例如下

wx.request({
      url: 'https://test.com/getinfo',
      method:'POST',
      header:{
        'content-type':'application/json'
      },
      data:{},
      success(res){
        if(res.statusCode==200){  //表示请求已成功
          console.log(res.data)
        }
      },
      fail:function(res){
        wx.showToast({
          title: '系统错误'
        })
      },
      complete:function(res){
        wx.hideLoading()
        hasClick=false
      }
    })

下面重点介绍微信登录,这里先引用微信公众平台开发文档中的一幅插图
curve
可以看到,要将微信与业务账号绑定起来,在未绑定时,大致步骤为:

1.调用微信登录接口回调得到登录凭证Code
2.将Code和用户的业务账号密码通过request发送到服务器
3.通过Code来换取用户微信id得到用户身份,并进行与业务的绑定
4.生成登录凭证并返回给小程序,以便下次直接得到用户身份

绑定成功后,大致步骤为:

1.用户凭借登录凭证直接向开发者服务器请求登录
2.开发者服务器直接通过凭证得到用户的身份

具体操作有如下示例

tapLogin: function() {
    wx.login({
      success: function(res) {
        if (res.code) {
          wx.request({
            url: 'https://test.com/login',
            data: {
              username: 'zhangsan', // 用户输入的账号
              password: 'pwd123456', // 用户输入的密码
              code: res.code
            },
            success: function(res) {
              // 登录成功
              if (res.statusCode === 200) {
               console.log(res.data.sessionId)// 服务器回包内容
              }
            }
          })
        } else {
          console.log('获取用户登录态失败!' + res.errMsg)
        }
      }
    });
  }
PREV
Android开发笔记
NEXT
关于博客中部分文章内容错乱的问题

评论(0)

发布评论