微信小程序开发(组件、API) 入门

微信小程序开发

微信小程序是纯前端应用,所需技术栈是JSCSSHTMLNode.js之类的前端技术栈。


(一)注册小程序

  • 选择“小程序”,按要求填写资料,然后验证邮箱,就可以成功注册

  • 注册成功后会跳转到管理页面

值得注意的是如果某个邮箱注册了服务号或者订阅号,就不能再注册小程序,并且个人主体每个自然人只允许注册5个小程序(令人窒息 - - |||)


(二)微信开发者工具

  • 首先下载对应的微信小程序开发者工具,安装后扫码登录

  • 点击页面下方的“+”,即可创建一个小程序工程

  • 如果没有注册AppID,可以点击“测试号”

  • 开发者工具由模拟器、编辑器、调试器三部分组成


1.模拟器

支持对不同手机型号、分辨率、网络的模拟,除此之外还有编译、切后台、清缓存等一些列调试工具


2.调试器

封装好的Chrome DevTools,即F12,所有输出信息、网络信息、报错信息、存储信息都会出现在这个调试器中


3.编辑器

(1)文件类型

  • .js:逻辑文件,即JavaScript代码文件,用于声明变量和事件
  • .wxml:页面文件,配置布局与UI,相当于HTML
  • .wxss:样式文件,配置样式,相当于CSS非必需

app.wxss总样式文件,如果单个页面中定义了自己的.wxss,将会覆盖总样式文件。

  • .json:页面JSON配置文件,非必需

app.json总配置文件,如果单个页面中定义了自己的.json,将会覆盖总配置文件。
app.json总配置文件中声明一个页面,保存后将自动创建该页面的.wxml.wxss.js文件


(2)目录结构

1
2
3
4
5
6
7
8
9
10
11
12
pages     : 页面目录
|-index : 首页
| |-index.js : JS文件
| |-index.wxml : HTML文件,配置布局与UI
| |-index.wxss : CSS文件,配置样式
|-logs
utils
app.js : 完成页面初始化工作
app.json : 总配置文件
【pages】 —— 页面路径;
【window】
app.wxss : 总样式文件


(3)Hello World

  1. index.wxml中添加一个块,绑定一个单击事件,代码如下:

1
2
3
<!--.wxml中的view标签,相当于HTML中的div标签,都是用于定义块对象-->
<!--bindtap用于绑定单击事件,事件的定义是在.js文件中-->
<view bindtap='bindMyViewTap'>点我跳转</view>

  1. index.js中定义单击事件:

1
2
3
4
5
6
7
8
//bindViewTap: function () {},
bindMyViewTap: function () {
//wx.navigateTo() :用于跳转的API
wx.navigateTo({
url: '../hello/helloWorld',
})
},
//onLoad: function () {}

  1. app.json中定义hello/helloWorld页面,自动生成其.wxml.wxss.js文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/hello/helloWorld"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json"
}

  1. helloWorld.js中定义变量helloWorldData

1
2
3
data: {
helloWorldData: 'Hello World!'
},

  1. helloWorld.wxml中定义文本块,通过如下语法获取helloWorld.js中定义的变量,进行数据绑定

  1. 运行:


(三)事件:【定义在.js中,在.wxml中绑定】

1.类别

(1)冒泡事件:触发子组件事件会触发父组件事件

  • 点击事件:tap
  • 长按事件:longtap
  • 触摸事件:touchstart开始、touchend结束、touchmove移动、touchcancel取消

touchend是正常停止触摸;
touchcancel触摸异常终止。比如:正在触摸时,来电话覆盖了小程序页面

Demo:多个<view>之间的点击冒泡事件
  1. app.json中新增页面"pages/bubbleBind/bubble",保存后自动生成bubble.wxmlbubble.wxssbubble.js
  2. bubble.wxml中定义三个<view>,绑定样式和对应事件:

1
2
3
4
5
6
7
8
9
<view class="view1" bindtap="view1click">
view1
<view class="view2" bindtap="view2click">
view2
<view class="view3" bindtap="view3click">
view3
</view>
</view>
</view>

  1. bubble.wxss中定义样式.view1.view2.view3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.view1{
height: 500rpx;
width: 100%;
background-color: rebeccapurple;
}
.view2{
height: 400rpx;
width: 80%;
background-color: red;
}
.view3{
height: 300rpx;
width: 60%;
background-color: saddlebrown;
}

  1. bubble.js中定义点击事件view1clickview2clickview3click

1
2
3
4
5
6
7
8
9
view1click : function(){
console.log("view1click")
},
view2click : function(){
console.log("view2click")
},
view3click : function(){
console.log("view3click")
},

  1. 点击view3view2view1的点击事件也会被触发,控制台打印:

1
2
3
view3click
view2click
view1click

  1. 点击view2view1的点击事件也会被触发,控制台打印:

1
2
view2click
view1click


(2)非冒泡事件:触发子组件事件不会触发父组件事件

  • submit
  • input

2.绑定

  1. bind:如bindtap
  2. catch:如catchtap

通过catch进行绑定的事件不会触发冒泡事件


3.事件的对象

  • type:类型
  • timeStamp:时间戳
  • target:事件源组件,即直接触发事件的组件
  • currentTarget:当前组件

比如说在第一节的Demo中,点击view3触发了view1的事件,
那么此时view1:currentTarget=view1target=view3

  • touches:触摸点数

(四)UI组件:【定义在.wxml中】

《官方文档:组件》

1.数据绑定

在页面的.wxml文件中,通过可以绑定.js中定义的data.varName变量。

Demo:点击按钮后改变文本内容

  1. app.json中新增页面"pages/firstPage/first",保存后自动生成first.wxmlfirst.wxssfirst.js
  2. first.wxml中定义一个文本块和一个按钮:

1
2
3
4
5
<!--定义按钮,绑定单击事件-->
<button type="primary" bindtap="btnClick">点击按钮改变文本</button>

<!--数据绑定-->
<text>{{text}}</text>

  1. first.js中定义变量text和点击事件btnClick

1
2
3
4
5
6
7
8
9
data: {
text: '初始文本'
},

//单击事件:点击按钮改变文本
btnClick : function (){
console.log("点击按钮")
this.setData({text:"文本已被修改!"})
}

  1. 运行:


2.标签渲染

(1)条件标签:wx:if=""/wx:else

1
2
3
4
<!--在.js中定义data.show,如果show=true显示标签,show=false则不显示-->
<view wx:if="{{show}}">内容</view>
<!--wx:else需要和wx:if搭配,当wx:if="{{true}}"时,wx:else="{{false}}"-->
<view wx:else>互补内容</view>

(2)循环标签:wx:for=""

1
2
3
<!--在.js中定义data.arrays数组:arrays=['aaa','bbb','ccc']-->
<view wx:for="{{arrays}}">第{{index}}条:{{item}}</view>
<!--通过arrays.shift()可以删除数组第一条-->


3.模板使用

(1)布局文件.wxml<include src="" />

  1. 新建pages/templates目录,创建header.wxml文件,作为头部的模板文件。
  2. 如果在pages/firstPage/first.wxml中想要使用模板,通过<include src="../templates/header" />导入即可。

(2)模板<template><import src="" /><template is="" />

  1. 新建pages/templates目录,创建footer.wxml文件,通过<template>标签定义模板:

1
2
3
4
5
6
<template name="footer1">
底部内容1
</template>
<template name="footer2">
{{footerData}}
</template>

  1. 如果在pages/firstPage/first.wxml中想要使用模板,通过<import src="" />导入,通过<template is="" />指定模板即可:

1
2
3
4
<!--导入模板文件-->
<import src="../templates/footer" />
<!--选择具体模板,通过data={{varName:''}}配置变量属性-->
<template is="footer2" data="{{footerData:'传入的底部内容2'}}" />


4.常用组件

(1)表单组件

①滑动选择器:slider

详见《官方文档 - 组件 - slider》

属性类型默认值必填说明
show-valuebooleanfalse是否显示当前值

1
<slider name="diySlider" show-value></slider>

②输入框:input

详见《官方文档 - 组件 - input》

属性类型默认值必填说明
placeholderstring输入框为空时的占位符
passwordbooleanfalse是否为密码类型

1
2
<input name="username" placeholder="输入用户名"></input>
<input name="passwd" placeholder="输入密码" password="true"></input>

③按钮:button

详见《官方文档 - 组件 - button》

属性类型默认值必填说明
typestringdefault按钮的样式类型。
hover-classstrngbutton-hover指定按钮按下去的样式类。当hover-class="none",没有点击态效果
form-typestrng用于form组件,点击分别触发submit/reset事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 白色按钮:type="default" -->
<button type="default" hover-class="other-button-hover">按钮文本</button>

<!-- 绿色按钮:type="primary" -->
<button type="primary">绿色按钮文本</button>

<!-- 红色按钮:type="warn" -->
<button type="warn">警告文本</button>

<!-- 提交按钮 -->
<button form-type="submit">提交按钮</button>

<!-- 重置按钮 -->
<button form-type="reset">重置按钮</button>

④表单:form

详见《官方文档 - 组件 - form》

属性类型默认值必填说明
bindsubmiteventhandle携带form中的数据触发submit事件,event.detail = {value : {'name': 'value'} , formId: ''}
bindreseteventhandle表单重置时会触发reset事件

1
2
3
4
5
6
7
8
9
10
11
12
<form bindsubmit="formSubmit" bindreset="formReset">
<switch name="switch"></switch>

<slider name="slider" show-value></slider>

<input name="username" placeholder="输入用户名"></input>
<input name="passwd" placeholder="输入密码" password="true"></input>

<button type="warn" form-type="submit">提交表单</button>
<button type="default" form-type="reset">重置</button>

</form>

对应的js代码:

1
2
3
4
5
6
7
8
9
10
formSubmit : function(e) {
console.log(e)
console.log(e.detail.value.switch)
console.log(e.detail.value.slider)
console.log(e.detail.value.username)
console.log(e.detail.value.passwd)
},
formReset: function() {
console.log("form reset")
}


(2)导航:navigator

详见《官方文档 - 组件 - navigator》

属性类型默认值说明
urlstring当前小程序内的跳转链接
open-typestringnavigate跳转方式:包括navigate/redirect/switchTab/reLaunch/navigateBack/exit

(3)视图容器

①滑块视图容器(幻灯片):swiper

详见《官方文档 - 组件 - swiper》

属性类型默认值说明
indicator-dotsbooleanfalse是否显示面板指示点(即图片下方的黑色小点
autoplaybooleanfalse是否自动切换
intervalnumber5000自动切换时间间隔,单位ms
durationnumber500滑动动画时长,单位ms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 如果是横向的幻灯片,需要通过style设置swiper的宽度,否则无法显示 -->
<swiper indicator-dots="{{true}}" autoplay="{{true}}" interval="2000" duration="1000" style="width:300px">
<swiper-item>
<image src="https://cdn.jsdelivr.net/gh/DragonBaby308/cdn@1.4.2/img/bg/bg2.jpg"></image>
</swiper-item>

<swiper-item>
<image src="https://cdn.jsdelivr.net/gh/DragonBaby308/cdn@1.4.2/img/bg/bg1.jpg"></image>
</swiper-item>

<swiper-item>
<image src="https://cdn.jsdelivr.net/gh/DragonBaby308/cdn@1.4.2/img/bg/bg3.jpg"></image>
</swiper-item>
</swiper>


②可滚动视图区域:scroll-view

详见《官方文档 - 组件 - scroll-view》

属性类型默认值说明
scroll-xbooleanfalse允许横向滚动
scroll-ybooleanfalse允许竖向滚动

1
2
3
4
5
6
7
<!-- 如果是竖向的可滚动视图区域,需要通过style设置每个视图的高度,否则无法显示 -->
<scroll-view scroll-y="{{true}}" style="height: 200px;">
<view id="green" style="height: 100px;background-color: green;"></view>
<view id="yellow" style="height: 100px;background-color: yellow;"></view>
<view id="red" style="height: 100px;background-color: red;"></view>
<view id="blue" style="height: 100px;background-color: blue;"></view>
</scroll-view>


(五)API

《官方文档:API》

1.路由

(1)wx.navigateTo(Object obj)

  • 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack()可以返回原页面。
  • 小程序中页面栈最多10
属性类型必填说明
urlstring需要跳转的应用内非tabBar的页面路径,路径后可以带参数,参数与路径用?分隔,参数键与参数值用=连接不同参数用&分隔,如:'path?key=value&key2=value2'
eventsObject页面间通信接口,用于监听被打开页面发送到当前页面的数据
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束(无论成功/失败)的回调函数

(2)wx.redirectTo(Object obj)

  • 关闭当前页面,跳转到应用内的某个页面,但不允许跳转到tabBar页面。
  • wx.redirectTo()wx.navigateTo()的不同点就在于不能跳转回原页面
属性类型必填说明
urlstring需要跳转的应用内非tabBar的页面路径,路径后可以带参数,参数与路径用?分隔,参数键与参数值用=连接不同参数用&分隔,如:'path?key=value&key2=value2'
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束(无论成功/失败)的回调函数

2.发起请求:RequestTask wx.request(Object obj)

属性类型必填默认值说明
urlstring开发者服务器接口地址(注意并不是所有url都可以
datastring/object/ArrayBuffer请求的参数
methodstringGETHTTP请求方法,包括:GET/POST/PUT/DELETE/OPTIONS/HEAD/TRACE/CONNECT
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束(无论成功/失败)的回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
success(res) {
console.log(res.data)
},
fail() {
console.log("fail!")
}
})


3.选择图片或拍照:wx.chooseImage(Object obj)

属性类型必填默认值说明
countnumber9最多可以选择的图片张数
sizeTypeArray<string>['original', 'compressed']所选图片的尺寸,默认包括原图和压缩图:original为原图,compressed为压缩图
sourceTypeArray<string>['album', 'camera']图片的来源,默认可以是相册和相机:album为相册,camera为相机
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束(无论成功/失败)的回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//var that = this
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success(res) {
// tempFilePath是一个数组,其中的单个元素可以作为img标签的src属性显示图片
//<img src="{{img}}">
const tempFilePaths = res.tempFilePaths
console.log(tempFilePaths)
//that.setData({img: tempFilePaths[0]})
//注意在回调函数中不能使用this,否则会报错,需要在回调函数外用一个变量存储this,再通过该变量使用
}
})


4.数据缓存与删除

(1)缓存K/Vwx.setStorage(Object obj)

  • K/V存储,相同的key,新value会覆盖旧value
  • 单个key最多1MB,所有key加起来不得超过10MB

1
2
3
4
5
6
7
8
9
10
wx.setStorage({
key: 'test_key',
data: 'test_value',
success(res) {
console.log("setStorage success!")
},
fail() {
console.log("setStorage fail!")
}
})

(2)删除单个keywx.removeStorage(Object obj)

1
2
3
4
5
6
7
8
9
wx.removeStorage({
key: 'test_key',
success(res) {
console.log("removeStorage success!")
},
fail() {
console.log("removeStorage fail!")
}
})

(3)清空缓存:wx.clearStorage(Object obj)

1
2
3
4
5
6
7
8
wx.clearStorage({
success(res) {
console.log("success!")
},
fail() {
console.log("fail!")
}
})

以上方法的同步版本分别是setStorageSyncremoveStorageSyncclearStorageSync并发安全


(六)配置【app.json

详见《官方文档 - 框架 - 小程序配置》

1.页面配置:pages数组

  • app.jsonpages数组中写入页面路径,会自动在对应目录下创建.wxml.wxss.js文件。
  • pages数组中的页面路径最后为页面名称(即文件名),不需要加文件类型
  • pages数组中第一个路径即为首页,即调试器中展示的页面

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


2.窗口配置:window

详见《官方文档 - 框架 - 小程序配置 - window》

如果在页面的.json中进行了window属性的配置,将会覆盖app.json中的配置

属性类型默认值描述
backgroundTextStylestringdark下拉 loading 的样式,仅支持 dark / light
navigationBarBackgroundColorHexColor#000000导航栏背景颜色,如"#ddd"
navigationBarTitleTextstring导航栏标题文字内容
navigationBarTextStylestringwhite导航栏标题颜色,仅支持 black / white

3.底部菜单配置:tabBar

详见《官方文档 - 框架 - 小程序配置 - tabBar》

注意:tabBar中配置的页面必须有一个是首页(即pages数组中的第一个路径),否则无法显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/logs/logs",
"text": "日志"
}
]
}
}


4.网络超时配置:networkTimeout

属性类型默认值描述
requestnumber60000wx.request的超时时间,单位:毫秒。
connectSocketnumber60000wx.connectSocket的超时时间,单位:毫秒。
uploadFilenumber60000wx.uploadFile的超时时间,单位:毫秒。
downloadFilenumber60000wx.downloadFile的超时时间,单位:毫秒。

5.调试模式:开启/关闭

  • 开启:"debug": true
  • 关闭:"debug": false

(七).js相关

1.app.js#App()

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
//app.js
var config = {
onLaunch: function () {
console.log("-----onLaunch-----")
// 展示本地存储能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)

// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo

// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},

onShow: function () {
console.log("-----onShow-----")
},

onHide: function () {
console.log("-----onHide-----")
},

globalData: {
userInfo: null
}
}

//调用App()方法
App(config)


(1)小程序的生命周期

  1. onLaunch:小程序启动
  2. onShow:小程序展示,即小程序页面处于最上层(onLaunch -> onShow/onHide -> onShow
  3. onHide:小程序隐藏(比如手机来电中断了小程序)

(2)全局变量、全局方法

app.jsApp()方法中定义的变量和方法都是全局的,在其他文件中可以通过const app = getApp()对象进行获取:

  • app.globalData.userInfo
  • app.globalFunction(),或者直接通过方法名调用globalFunction()

2..js#Page()

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
69
70
//index.js
//获取应用实例
const app = getApp()

Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
//事件处理函数
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},

onLoad: function () {
console.log("-----Index Page onLoad-----")
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse){
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
},

onShow: function () {
console.log("-----Index Page onShow-----")
},

onReady: function () {
console.log("-----Index Page onReady-----")
},

onHide: function () {
console.log("-----Index Page onHide-----")
},

//全局函数
getUserInfo: function(e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
})


(1)页面生命周期

  1. onLoad:加载数据
  2. onShow:绑定数据
  3. onReady:显示完成
  4. onHide:页面隐藏(比如手机来电中断了小程序)
  5. onUnload页面被卸载

通过wx.navigateTo(),从page1跳转到page2,再从page2返回page1时,就会触发page2onUnload


(2)参数传递:onLoad(Object)Object.key

wx.navigateTo(url)/wx.redirectTo(url)API
  1. index.js中通过wx.navigateTo()跳转时,url写成路径?参数key=value

1
2
3
wx.navigateTo({
url: '../article/article?id=1'
})

  1. article.js#Page()onLoad(Object)中,通过Object.key获取参数:

1
2
3
4
5
6
onLoad: function (options) {
console.log(options)
//打印:Object {id: "1"}
console.log(options.id)
//打印:1
}

  1. 通过this.setData()将传入的参数保存到一个变量中,就可以通过该变量使用传递的参数了

<navigator>组件
  1. 如果觉得在UI组件上通过bindtap绑定事件,然后在.js中使用wx.navigateTo()/wx.redirectTo()太复杂,你也可以将需要触发路由事件的UI组件封装在<navigator></navigator>中,这样不需要使用代码,也可以实现路由的功能

1
2
3
4
5
6
7
<!-- 相当于wx.redirectTo() -->
<!-- <navigator url="../article/article?id=2&title=标题" redirect> -->

<!-- 相当于wx.navigateTo() -->
<navigator url="../article/article?id=2&title=标题">
<view>文章1</view>
</navigator>

  1. article.js#Page()onLoad(Object)中,通过Object.key同样可以获取参数
-------------本文结束感谢您的阅读-------------

本文标题:微信小程序开发(组件、API) 入门

文章作者:DragonBaby308

发布时间:2020年01月03日 - 11:56

最后更新:2020年02月14日 - 15:09

原始链接:http://www.dragonbaby308.com/wxapplet/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

急事可以使用右下角的DaoVoice,我绑定了微信会立即回复,否则还是推荐Valine留言喔( ఠൠఠ )ノ
0%