微信小程序学习

Last updated on a year ago

基础配置与介绍

注册开发者账号

微信公众平台中,点击”立即注册“,账号类型选择”小程序“。完成后登录即可。

接着在”设置“-”开发设置“中查看AppID。每个小程序账号只有一个AppID,每个账号只能开发一个小程序,如果需要发布多个,则需要注册多个账号。

安装微信开发者工具

在微信公众平台上可以找到下载地址,下载安装即可。

开发者工具部分功能介绍

模拟器

用于模拟手机环境,查看不同型号手机的运行效果。

调试器

  • console:控制台
  • sources: 源代码
  • newwork:网络,用于记录网络请求信息,根据它可进行网络性能优化
  • security:安全,用于调试页面的安全和认证等信息,如https
  • appdata:app数据,可以查看或编辑当前小程序运行时的数据
  • audites:审计,用于对小程序进行体验评分
  • sensor:传感器,用于模拟地理位置、重力感应
  • storage:存储,用于查看和管理本地数据缓存
  • trace:跟踪,用于真机调试时跟踪调试信息
  • wxml:用于查看和体哦啊是wxml和wxss

目录结构

路径 说明
project.config.json 项目配置文件
app.js 应用程序的逻辑文件
app.json 应用程序的配置文件
app.wxss 应用程序的公共样式文件
pages/ 存放页面文件的目录
pages/index/ 存放index页面的目录
pages/index/index.js index页面的逻辑文件
pages/index/index.wxml index页面的结构文件
pages/index/index.wxss index页面的样式文件
pages/logs/ 存放logs 页面的目录
pages/logs/logs.js logs页面的逻辑文件
pages/logs/logs.json logs页面的配置文件
pages/logs/logs.wxml logs 页面的结构文件
pages/logs/logs.wxss logs页面的样式文件
utils/ 存放公共脚本文件的目录
utils/utils.js 公共脚本文件,保存一些工具代码

开发基础

新增页面

新增页面需要创建app.json,并在该文件中编写

1
2
3
4
5
{
"pages":[
"pages/index/index"
]
}

保存之后,开发者工具就会自动生成index.js、index.json、index.wxml、index.wxss四个文件

页面组件

小程序使用WXML(WeiXin Markup Language)来实现页面的结构(类似HTML),比如其中的<view>相当于HTML的div,常用的有

标签 功能
view 视图容器
text 文本域
button 按钮
image 图片
form 表单
icon 图标文件
checkbox 复选框
radio 单选框
input 输入框
progress 进度条

书写方式和HTML类似

1
2
3
4
<view>
<text>输入数字</text>
<input type="number" />
</view>

input标签会根据type的不同而弹出不同的键盘,方便用户输入,它支持以下类型

属性值 说明
text 文本输入键盘(默认)
number 数字输入键盘(不带小数点)
idcard 身份证输入键盘(0-9和X)
digit 带小数点的数字键盘

之后点击编译,就可以看到运行状况了,而如果想要看见弹出的键盘,可以使用真机调试,用手机扫码之后就可以在手机山操作了,而且电脑同时还可以进行调试。

页面样式

WXSS(WeiXin Style Sheets)用于描述WXML的组件样式,它具有CSS大部分特性,并做了一些扩展和修改。

  1. 选择器

    WXSS选择器和CSS用法基本相同

  2. 尺寸单位

    在使用CSS做移动端网页开发的时候,为了适配不同屏幕需要对像素单位进行换算,而WXSS为了简化这一流程,加入了新得尺寸rpx

    rpx单位规定任何手机屏幕得宽度都为**750rpx(逻辑像素)**,所以设计图需要按照750px的宽度进行绘制,然后在小程序中使用rpx,不再需要担心宽度问题了。下表是rpx在不同设备中与px的换算关系

    设备 屏幕宽度(px) rpx换算px(屏幕宽度/750) px换算rpx(750/屏幕宽度)
    iPhone 5 320 1rpx 约等于 0.42px 1px 约等于 2.34rpx
    iPhone 6 375 1rpx = 0.5px 1px = 2rpx
    iPhone 6 plus 414 1rpx = 0.552rpx 1px 约等于 1.81rpx
  3. 样式导入

    在WXSS中可以使用@import导入外部样式表(和less有点像),语法如下

    1
    @import "index.wxss"
  4. 全局样式

    如果多个页面经常有通用的样式,可以在项目根目录下创建全局样式app.wxss,当页面样式和全局样式发生冲突时,页面样式的优先级更高

配置文件

每个页面均可以使用json文件对页面的效果进行配置,页面配置分为页面级应用级app.json应用级配置文件

  1. 页面级配置文件

    可以用来配置更改页面的导航样式,控制页面是否允许上下移动等,下面是常用的配置

    属性 说明
    navigationBarBackgroundColor 导航栏背景颜色,默认#000
    navgationBarTextStyle 导航栏标题文字内容
    navgationBarTitleStyle 导航栏标题颜色,仅支持block、white(默认)
    backgroundColor 窗口的背景颜色,默认#fff
    backgroundTextStyle 下拉loading的样式,仅支持dark(默认)、light
    enablePullDownRefresh 是否开启全局下拉刷新,默认false
    onReachBottomDisatance 页面上拉触底事件时距页面底部距离(单位px),默认50
    disableScroll 默认false,设为true时,页面不能上下滚动

    当页面非常长时,为了加快加载速度,会先加载一部分,当用户快到底部时,立即加载后面的内容,而onReachBottomDistance值越大,加载的时机就越提前,当到达了给定的值,就会触发上拉触底事件,onReachBottom,在对应的js文件下,可以找到该事件的处理函数。

  2. 应用级配置文件

    项目根目录下的app.json就是应用级配置文件,常用配置如下

    属性 说明
    pages 页面的路径
    window 全局的默认窗口表现
    tabBar 底部tab栏的表现
    networkTimeout 网络超时时间
    debug 是否开启调试模式,默认为false
    requireBackgroundModes 需要在后台使用的能力,如音乐播放等
    plugins 使用到的插件

    window的值是一个对象,可以将上面说过的页面级配置写在window中,作为应用级配置使用,从而设置多个页面。

    newworkTimeout可以设置网络请求过程中的超时时间

    属性 类型 说明
    request Number wx.request()的超时时间(ms),默认60000
    connectSocket Number wx.connectSocket()的超时时间(ms),默认60000
    uploadFile Number wx.uoloadFile()的超时时间(ms),默认60000
    downloadFile Number wx.downloadFile()的超时时间(ms),默认60000

页面逻辑

js文件用于编写页面逻辑,打开文件可以看到自带的一些代码,这些是开发者工具自动生成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// pages/test/test.js
Page({

/**
* 页面的初始数据
*/
data: {

},

/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {

},

/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {

},

/**
* 生命周期函数--监听页面显示
*/
onShow() {

},

/**
* 生命周期函数--监听页面隐藏
*/
onHide() {

},

/**
* 生命周期函数--监听页面卸载
*/
onUnload() {

},

/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {

},

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {

},

/**
* 用户点击右上角分享
*/
onShareAppMessage() {

}


})

在上述代码中,Page()函数用于注册一个页面,该函数的参数是一个对象,通过该对象可以指定页面的初始数据、生命周期函数、事件处理函数等(有点像vue)

属性 类型 说明
data Object 页面的初始数据
onLoad Function 生命周期回调函数,监听页面加载
onReady Function 生命周期回调函数,监听页面初次渲染完成
onShow Function 生命周期回调函数,监听页面显示
onHide Function 生命周期回调函数,监听页面隐藏
onUnload Function 生命周期回调函数,监听页面卸载
onPullDownRefresh Function 页面事件处理函数,监听用户下拉动作
onReachBottom Function 页面事件处理函数,页面上拉触底
onShareAppMessage Function 页面事件处理函数,用户单机右上角分享按钮
onPageScroll 无法解析符号 ‘key’ 页面事件处理函数,页面滚动会连续触发
其他 Any 开发者可以添加任意的函数或数据,在页面的函数中可以通过this.*来访问
  1. 生命周期函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    onload: function (options) {
    console.log('页面加载')
    }
    onReady: function () {
    console.log('页面初次渲染完成')
    }
    onShow: function () {
    console.log('页面显示')
    }
    • *onLoad:*页面加载时触发。一个页面只会调用一次,通过参数options,可以获取打开当前页面路径中的参数
    • *onReady:*页面初次渲染完成时调用。一个页面只会调用一次,代表页面已经准备妥当,此时可以与视图层进行交互
    • *onShow:*当页面显示时触发,如:从后台切入前台时触发
    • *onHide:*当页面隐藏时触发,如:从前台切入到后台时触发
    • *onUnload:*页面卸载时触发。例如使用路由API中的wx.redirectTo()或wx.navigateBack()跳转其他页面时。
  2. 页面事件处理函数

    以onPullDownRefresh、onReachBottom、onPageScroll为例演示。其中onPullDownRefresh需要在配置文件中将enablePullDownRefresh设为true才有效。而onPageScroll不会自动生成,需要自己写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    onPullDownRefresh: function () {
    console.log('此时用户下拉触底')
    },
    onReachBottom: function () {
    console.log('此时用户上拉触底')
    },
    onPageScroll: function (options) {
    console.log('此时用户正在滚动页面')
    console.log('滚动距离:' + options.scrollTop)
    }
  3. 组件事件处理函数

    组件事件处理函数用于为组件绑定事件,如:

    1
    <button bindtap="compare">比较</button>

    bindtap表示绑定tap点击事件,事件处理函数为compare

    1
    2
    3
    4
    compare: function (e) {
    console.log('比较按钮被点击了')
    console.log(e)
    }

    其中参数表示事件对象,输出结果为:

    1
    {type: "tap", timeStamp: 320371, target: {…}, currentTarget: {…}, mark: {…}, …}

    通过事件对象可以获取type(事件类型)、timestamp(事件生成时的时间戳)、target(触发事件的组件中一些属性集合)、currenTarget(当前组件的一些属性值集合)、detail(额外的信息)等信息

    下面是一些细节

    1. e.targete.currentTarget的区别

      1
      2
      3
      4
      5
      6
      <view id="outer" bind:tap="viewTap">
      outer
      <view id="inner">
      inner
      </view>
      </view>
      1
      2
      3
      viewTap: function(e) {
      console.log(e.target.id + '-' + e.currentTarget.id)
      }

      由于inner在outer中,所以我们点击outer或inner都能触发viewTap事件,当我们点击outer会出现”outer-outer“,点击inner会出现”inner-outer”,由此可见,target获取到的是子元素的属性值集合(当前元素?),currentTarget是父元素的属性值集合

    2. 常用冒泡事件

      事件类型 触发条件
      touchstart 手指触摸动作开始
      touchmove 手指触摸后移动
      touchcancel 手指触摸动作被打断,如来电提醒、弹窗
      touchend 手指触摸动作结束
      tap 手指触摸后马上离开
      longpress 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发这个事件,tap事件将不被触发

      上述都属于冒泡事件,冒泡事件是指当一个组件上的事件被触发后,事件会向父节点传递,而非冒泡事件则不会向父节点传递。另外,一些组件还拥有一些专门的事件,如:form的submit事件。

    3. 事件绑定和冒泡

      组件绑定事件有bind事件类型catch事件类型bind不会阻止冒泡事件向上冒泡,而catch可以阻止事件向上冒泡

注册程序

若要在小程序启动、显示、隐藏时执行某些操作,可以通过App()函数来实现。它用于注册小程序,接收一个对象参数,通过参数指定小程序的生命周期回调等。App()函数必须在app.js中调用,且只能调用一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
App( {
//生命周期回调——监听小程序初始化
//小程序初始化完成时触发(全局只触发一次)
onLauch: function(options) {
console.log('onLauch执行')
console.log(options)
},
//生命周期回调——监听小程序显示
//小程序启动,或从后台进入前台时显示
onShow: function(options) {
console.log('onShow执行')
console.log('options')
},
//生命周期回调——监听小程序隐藏
//从前台进入后台时触发
onHide: function(options) {
console.log('onHide执行')
console.log(options)
},
//错误监听函数
//小程序发生脚本错误,或API调用失败时触发
onError: function(error) {
consle.log('onError执行')
console.log(error)
},
//页面不存在 监听函数
//小程序要打开的页面不存在时触发
onPageNotFound: function(options) {
console.log('onPageNotFound')
console.log(options)
}
})

其中options会输出类似以下内容

1
{path: "pages/index/index", query: {}, scene: 1001, shareTicket: undefined, referrerInfo: {}, }
  • path:打开小程序的路径,一般时app.json中设置的第一个页面,也可以通过自定义编译条件指定启动页面
  • query:打开小程序的query,一般是空对象,也可以通过自定义编译条件指定启动参数
  • scene:打开小程序的场景值,一般时1001,也可以通过自定义编译条件指定进入场景
  • shaareTicket:当小程序被转发出去时,如果此转发卡片被其他用户打开,可以获取到shareTicket(如群的标识)。通常搭配wx.showShareMenu()使用,并且需要在该方法的参数对象中设置withShareTicket为true
  • referrerInfo:当场景从另一个小程序、公众号或APP打开时,可以通过它获取来源于小程序、公众号的AppId等,scene为1037时支持传递附加数据

同时,App()函数还可以保存一些在所有页面共享的数据:

1
2
3
4
5
6
App({
num: 123,
test: function() {
console.log('test')
}
})

然后在页面的js文件(比如index.js)的onReady中编写

1
2
3
4
5
onReady: function() {
var app = getApp()
console.log(app.num)
app.test()
},

绑定变量

可以通过{{}}在对应位置绑定一个变量或表达式,比如{{msg}}绑定了msg,会将js文件中data:{}中定义的msg显示出来。

修改msg的值有两种方式,通过this.data.msg = 重新赋值或this.data.setData()。两者的区别是,赋值不会刷新页面,msg修改之后页面依然显示原来的值,而通过setData()则可以。

setData()的参数是一个对象,输入this.data.setData({ msg: 1 }),表示将msg的值修改为1。

表单数据绑定

下面是一个表单绑定的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<form bindsubmit="submit">
<view>
<text>姓名</text>
<input name="name" value="{{name}}" />
</view>
<view>
<text>性别</text>
<radio-group name="gender">
<label wx:for="{{gender}}" wx:key="value">
<radio value="{{item.value}}" checked="{{item.checked}}" />
{{item.name}}
</label>
</radio-group>
</view>
<view>
<checkbox-group name="skills">
<text>技能:</text>
<label wx:for="{{skills}}" wx:key="value" >
<checkbox value="{{item.value}}" checked="{{item.checked}}"/>
{{item.name}}
</label>
</checkbox-group>
</view>
<button form-type="submit">提交</button>
</form>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
data: {
num1: 0,
num2: 0,
msg: 12 ,
name: '张三',
gender: [
{name: '男', value: '0', checked: true},
{name: '女', value: '1', checked: false}
],
skills: [
{name: 'CSS', value: 'CSS', checked: true},
{name: 'HTML', value: 'HTML', checked: true},
{name: 'VUE', value: 'VUE', checked: false},
{name: 'JS', value: 'JS', checked: false},
]
},
submit: function(e) {
console.log(e.detail.value)
wx.request({
method: 'post',
url: 'http://127.0.0.1:3000/',
data: e.detail.value,
success: function (res) {
console.log(res.data)
},
fail: function(err) {
console.log(err)
}
})
}

nodejs搭建本地服务器与发送请求

  1. 初始化项目,并自动创建package.json配置文件

    1
    npm init -y
  2. 安装Express框架,用于快速搭建HTTP服务器

    1
    npm install express --save
  3. 安装nodemon监控文件修改

    1
    npm install nodemon -g

    之后,在目录下创建index.js,代码编写如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const express = require('express')
    const bodyParser = require('body-parser')
    const app = express()
    app.use(bodyParser.json())
    //处理POST请求
    app.post('/', (req,res) => {
    console.log(req.body)
    res.json(req.body)
    })
    //监听端口
    app.listen(3000, () => {
    console.log('sercer running at http://127.0.0.1:3000')
    })
  4. 启动服务器

    1
    nodemon index.js
  5. 小程序发送请求

    发送请求使用wx.request()函数,参数是一个对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    submit: function(e) {
    wx.request ({
    method: 'post', //请求类型
    url: 'http://127.0.0.1:3000/', //接口地址
    data: e.detail.value, //请求内容
    header:{ //请求头
    'content-type': 'application/x-www-form-urlencoded'
    },
    success: function(res) { //请求成功后执行的函数
    console.log(res)
    },
    fail: function(error) { //请求失败后执行的函数
    console.log(error)
    }
    })}
    }

    在发送请求时候可能会出现错误:

    1
    request:fail url not in domain list

    这时需要到设置-项目设置-本地设置,将*不检验合法域名…*选中,就可以了。