微信小程序
相关地址
前言
这是小程序入门基础篇,要学习一门新的技术首先要对它整体有一个简单的了解。微信小程序是寄生在微信App里面,微信拥有的功能大部分对小程序是开放的,可以在小程序里面任意调用微信原生API。开发者工具的使用以及安装请参考官方文档进行安装。
如果你想快速掌握小程序,下面你就应该走走心了!我主要从下面几个方面介绍。
一、小程序的文件结构:
小程序主要由三个构造器函数生成,App()
函数用来注册小程序、Page()
函数用来注册页面、Component()
函可用来定义组件。一个小程序只需要有一个 App()
函数,可以有一个或者多个 Page()
和 Component()
函数。
二、一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下:
app.js
小程序主逻辑生命周期、首次授权验证、app.json
小程序公共设置、app.wxss
小程序公共样式表。
三、一个小程序页面由四个文件组成,分别是:
.js
页面逻辑、.wxml
页面结构、.wxss
页面样式表、.json
页面配置。
这里我已经把小程序里面主要文件以及组成罗列出来了,下面我们就对应各类型的文件来详细讲解。
配置
app.json配置信息
app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"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 设置页面路径
window 设置默认页面的窗口表现
tabBar 设置底部 tab 的表现
networkTimeout 设置网络超时时间
debug 设置是否开启 debug 模式
注意: 上面是小程序的全局配置信息,该配置也可以用在各页面的.json文件内配置局部信息
逻辑层
注册程序App()
App()
函数用来注册一个小程序。接受一个 object
参数,其指定小程序的生命周期函数等。(app.js文件)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18App({
//生命周期函数--监听小程序初始化
onLaunch: function(options) {
// 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
},
//生命周期函数--监听小程序显示
onShow: function(options) {
// 当小程序启动,或从后台进入前台显示,会触发 onShow
},
//生命周期函数--监听小程序隐藏
onHide: function() {
// 当小程序从前台进入后台,会触发 onHide
},
onError: function(msg) {
// 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
},
globalData: 'I am global data'
})
注意: 小程序应用生命周期有三个:初始化、显示、隐藏
注册页面Page()
Page()
函数用来注册一个页面。接受一个 object
参数,其指定页面的初始数据、生命周期函数、事件处理函数等(index.js文件)
1 | //index.js |
一、页面生命周期
onLoad
: 页面加载
一个页面只会调用一次,可以在 onLoad 中获取打开当前页面所调用的 query 参数。onShow
: 页面显示
每次打开页面都会调用一次。onReady
: 页面初次渲染完成
一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。对界面的设置如wx.setNavigationBarTitle请在onReady之后设置。详见生命周期onHide
: 页面隐藏
当navigateTo或底部tab切换时调用。onUnload
: 页面卸载
当redirectTo或navigateBack的时候调用。
二、页面相关事件处理函数
onPullDownRefresh
: 下拉刷新
监听用户下拉刷新事件。需要在app.json的window选项中或页面配置中开启enablePullDownRefresh。当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。onReachBottom
: 上拉触底
监听用户上拉触底事件。可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance。在触发距离内滑动期间,本事件只会被触发一次。onPageScroll
: 页面滚动
监听用户滑动页面事件。参数为 Object,包含以下字段:onShareAppMessage
: 用户转发
只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮。用户点击转发按钮的时候会调用,此事件需要 return 一个 Object,用于自定义转发内容{title:”转发标题”, path:”转发路径”}
转发示例代码1
2
3
4
5
6
7
8Page({
onShareAppMessage: function () {
return {
title: '自定义转发标题',
path: '/page/user?id=123'
}
}
})
事件处理函数
1 | <view bindtap="viewTap">click me</view> |
1 | Page({ |
数据绑定1
<view>{{text}}</view>
1 | Page({ |
getApp()
全局的 getApp()
函数可以用来获取到小程序实例。
1 | // other.js |
注册自定义组件Component()
从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
自定义组件的创建与使用
类似于 Page()
页面,一个自定义组件由 .json、.wxml、.wxss、.js 4个文件组成,下面我们看下.js文件内容
Component
构造器可用于定义组件,调用 Component
构造器时可以指定组件的属性、数据、方法等。
1 | Component({ |
1). 要编写一个自定义组件,首先需要在新组件.json文件中进行自定义组件声明将 component
字段设为 true
1
2
3{
"component": true
}
2). 编写自定义组件的 wxml
模板和 wxss
样式1
2
3
4
5
6
7
8
9
10<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
{{innerText}}
</view>
<!-- 占位符可以不写,暂时用不上 -->
<slot></slot>
/* 这里的样式只应用于这个自定义组件 */
.inner {
color: red;
}
3). 编写自定义组件的js部分内容,需要使用 Component()
实例来注册
1 | Component({ |
4). 使用自定义组件
使用已注册的自定义组件,首先要在[使用页]json文件中引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:1
2
3
4
5
6{
"usingComponents": {
<!-- 组件的名称标签名 : 组件的路径 -->
"component-tag-name": "/components/Banner/banner"
}
}
现在可以在使用的页面 wxml
中就可以像使用基础组件一样使用自定义组件了。1
2
3
4<view>
<!-- 以下是对一个自定义组件的引用 [inner-text='some text'] 属性不写的时候默认展示组件js中properties的value值-->
<component-tag-name inner-text="Some text"></component-tag-name>
</view>
组件的模板和样式
1.组件模板
在组件模板中可以提供一个 1
2
3
4
5<!-- 组件模板 -->
<view class="wrapper">
<view>这里是组件的内部节点</view>
<slot></slot>
</view>
1 | <!-- 引用组件的页面模版 --> |
组件 wxml
的 slot
使用
在组件的 wxml
中可以包含 slot
节点,用于承载组件使用者提供的 wxml
结构。
默认情况下,一个组件的wxml中只能有一个 slot
需要使用多 slot
时,可以在组件js中声明启用。1
2
3
4
5
6
7Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
此时,可以在这个组件的 wxml
中使用多个 slot
以不同的 name
来区分。1
2
3
4
5
6<!-- 组件模板 -->
<view class="wrapper">
<slot name="before"></slot>
<view>这里是组件的内部细节</view>
<slot name="after"></slot>
</view>
使用时,用 slot
属性来将节点插入到不同的 slot
上。1
2
3
4
5
6
7
8
9<!-- 引用组件的页面模版 -->
<view>
<component-tag-name>
<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
<view slot="before">这里是插入到组件slot name="before"中的内容</view>
<!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
<view slot="after">这里是插入到组件slot name="after"中的内容</view>
</component-tag-name>
</view>
2.组件的样式
外部样式类(注意:1.9.90以上版本才支持)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/* 组件页面 custom-component.js */
Component({
externalClasses: ['my-class']
})
<!-- 组件 custom-component.wxml -->
<custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>
<!-- 引用页面的 WXML -->
<custom-component my-class="red-text" />
/* 引用页面的样式 */
.red-text {
color: red;
}
组件事件
事件系统是组件间交互的主要形式。自定义组件可以出发任意事件,引用组件的页面可以监听这些事件。1
2
3
4<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
<!-- 或者可以写成 -->
<component-tag-name bind:myevent="onMyEvent" />
1
2
3
4
5
6
<!-- 当前引用页面 -->
Page({
onMyEvent: function(e){
console.log(e.detail); // 自定义组件触发事件时提供的detail对象
}
})
自定义组件触发事件时,需要使用 triggerEvent
方法,指定事件名 detail
对象和事件选项:
1 | <!-- 在自定义组件中 --> |
1 | Component({ |
页面路由
getCurrentPages()
函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出。
第一个元素为首页,最后一个元素为当前页面
路由的方式
打开新页面调用 wx.navigateTo 或使用组件 <navigator open-tpe=’navigateTo’ />
页面重定向调用 wx.redirectTo 或使用组件 <navigator open-type=’redirectTo’ />
页面返回调用 wx.navigateBack 或使用组件 <navigator open-type=’navigateBack’> 或者左上角返回按钮
Tab切换调用 wx.switchTab 或使用组件 <navigator open-type=’switchTab’/>
重启动调用 wx.relaunch 或使用组件 <navigator open-type=’relaunch’ />
模块化
可以将一些公共的代码抽离成为一个单独的js文件,作为一个模块。模块只有通过 module.export
或者 export
才能对外暴露接口。
1 | //comm.js |
在需要使用这些模块的文件中,使用 require(path)
将公共代码引入1
2
3
4
5
6
7
8
9var comm = require('comm.js') //注:path暂不支持绝对路径
Page({
helloMINA:function(){
comm.sayHello('MINA')
},
goodbyeMINA:function(){
comm.sayGoodbye('MINA')
}
})
小程序API
小程序提供丰富的微信原生API,可以方便调起微信提供的能力,用户信息、本地存储、支付功能、网络请求( 只有你想不到的,没有它做不到的。)
需要参考官方API文档微信小程序官方API
视图层
WXML
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
数据绑定
1 | <!--wxml--> |
1 | //page.js |
列表渲染1
2<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
1 | // page.js |
条件渲染1
2
3
4<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
1 | // page.js |
模板1
2
3
4
5
6
7
8
9
10<!--wxml-->
<template name="staffName">
<view>
FirstName: {{firstName}}, LastName: {{lastName}}
</view>
</template>
<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
1 | // page.js |
事件
1 | <!--wxml--> |
WXS
WXSS
WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
尺寸单位
如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
样式导入
使用 @import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;表示语句结束。1
2
3
4/** common.wxss **/
.small-p {
padding:5px;
}
1 | /** app.wxss **/ |
内联样式
框架组件上支持使用 style
、class
属性来控制组件的样式。1
2
3
4
5/** style请尽量避免将静态的样式写进 style 中,以免影响渲染速度。 **/
<view style="color:{{color}};" />
/** class 使用要遵守命名规范 **/
<view class="normal_view" />
定义在 app.wxss
中的样式为全局样式,作用于每一个页面。在 page
的 wxss
文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss
中相同的选择器。
插件
2018/3/13推送插件启用,目前只是企业账号才可以使用。
实战常用的功能
小程序登陆授权验证
首先登陆授权主要是获取openid,这个值可以在前端获取也可以在后台获取,官方推荐的方式是后台获取,不对外提供。
后台获取:
1.小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器
2.开发者服务器以code换取和appid + appsecret用户唯一标识openid 和 会话密钥session_key。
或者是
1.获取code(登录凭证,用来换取openid及session_key等)1
2
3
4
5
6
7
8
9wx.login({
success: function(res){
if(res.code){
that.getEncData(res.code);
}else{
console.log('获取用户登录态失败!'+res.errMsg);
}
}
})
2.获取加密数据和加密算法初始向量1
2
3
4
5
6
7
8getEncData: function(code){
wx.getUserInfo({
withCredentials: true,
success: function(res){
that.getNeededUserInfo( code, res.encryptedData, res.encryptedData );
}
})
}
- 获取用户信息(利用wx.login返回的code获取用户的信息)
1 | getNeededUserInfo: function(code, enc, iv){ |
前端获取:
1.首先你需要取微信小程序的后台配置请求的地址https://api.weixin.qq.com
2.之后去微信小程序后台开发设置里面拿到AppID 和 AppSecret
注释:AppSecret这个小程序密钥不会轻易出现在前端页面,所以官方不推荐前端获取openid的方式。
1 | wx.login({ |
授权登陆官方文档
博客介绍
2018年5月10日 星期四 23:02 《获取用户信息接口优化调整》
此次优化调整,wx.getUserInfo 无法调起微信授权弹框,如果需要调起弹框需要使用button组件拉起,已经上线的项目暂不受影响。
禁止屏幕上下滑动以及下拉上拉执行的方法
具体页面的.json文件:1
2
3
4{
"enablePullDownRefresh": true //页面下拉是否触发滑动事件
"onReachBottomDistance":Number //页面上拉与页面底部的距离
}
app.json文件1
2
3"window": {
"enablePullDownRefresh": true
}
下拉刷新回调接口1
2
3onPullDownRefresh: function () {
// do somthing matter
},
上拉加载回调接口1
2
3onReachBottom: function () {
// do somthing matter
},
固定屏幕
只显示一屏内容,不可上下滑动,值允许在 page.json
中设置,无法在 app.json
中设置1
2
3{
"disableScroll":true
}
实现点击复制指定内容
1 | clone(){ |
实现双击
1 | clickBtn(e){ |
调用客服API
第一种实现方式:
1 | <view class='myView'>第一种方式实现:</view> |
第二种实现方式:1
2
3
4<view class='myView'>第二种方式实现:</view>
<button class="cs_button" open-type="contact" session-from="weapp">
<image class="cs_image" src="../images/cs.png"></image>
</button>
用户授权拒绝
需求:
1).当用户首次进入小程序点击允许可以继续访问页面,点击拒绝直接退出小程序1
2
3
4wx.navigateBack({
delta: -1
})
//-1可以直接强退小程序,但再次进入的时候无法调起授权弹框
2).当用户首次进入小程序点击允许可以继续访问页面,点击拒绝直跳转到新页显示授权按钮
在新页面使用一个按钮绑定属性和事件来调用是否授权提示框1
2
3
4
5
6
7
8
9
10
11
12<button open-type="getUserInfo"
class="recordingNoneS wx-contact-text"
@getuserinfo="userInfoHandler">点击授权</button>
userInfoHandler(e){
if(e && e.mp && e.mp.detail && e.mp.detail.encryptedData){
wx.setStorageSync('nickName', e.mp.detail.userInfo.nickName);
wx.setStorageSync('avatarUrl', e.mp.detail.userInfo.avatarUrl);
this.getVerifyInfo(e.mp.detail.iv,e.mp.detail.encryptedData);
console.log(e.mp.detail);
}
},
注:如果用户拒绝授权还可以引导手动开启授权1
2
3
4
5wx.openSetting({
success:(res)=>{
console.log(res);
}
});
分享功能两种实现方式
启用右上角分享1
2
3
4
5
6
7
8
9
10
11
12Page({
onShareAppMessage: function (res) {
title: '自定义转发标题',
path: '/page/user?id=123',
success: function(res) {
// 转发成功
},
fail: function(res) {
// 转发失败
}
}
})
启用按钮分享1
<button open-type="share">转发</button>
混合使用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
34onShareAppMessage: function( options ){
var that = this;
// 设置菜单中的转发按钮触发转发事件时的转发内容
var shareObj = {
title: "转发的标题", // 默认是小程序的名称(可以写slogan等)
path: '/pages/share/share', // 默认是当前页面,必须是以‘/’开头的完整路径
imgUrl: '', //自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径,支持PNG及JPG,不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4
success: function(res){
// 转发成功之后的回调
if(res.errMsg == 'shareAppMessage:ok'){
}
},
fail: function(){
// 转发失败之后的回调
if(res.errMsg == 'shareAppMessage:fail cancel'){
// 用户取消转发
}else if(res.errMsg == 'shareAppMessage:fail'){
// 转发失败,其中 detail message 为详细失败信息
}
},
complete: fucntion(){
// 转发结束之后的回调(转发成不成功都会执行)
}
};
// 来自页面内的按钮的转发
if( options.from == 'button' ){
var eData = options.target.dataset;
console.log( eData.name ); // shareBtn
// 此处可以修改 shareObj 中的内容
shareObj.path = '/pages/btnname/btnname?btn_name='+eData.name;
}
// 返回shareObj
return shareObj;
}
注意:使用mpvue的时候默认所有页面均带分享功能,官方暂时没有给出解决方案。但是…但是…这里有一个解决方案
使用mpvue所有页面全部都有分享功能使用onShareAppMessage初始化一下分享,这时候原生小程序,覆盖掉了mpvue的分享,在onLoad的时候添加wx.hideShareMenu();方法,这时候达到的效果:点击右上角,不会出现转发项。
禁止下滑与页面堆栈
1.ios不可以禁止下滑,可以使用view-scroll,进行一点优化
2.重复路径来回跳转,栈堆积到5-8层左右,禁止任何点击,栈堆满了,无法解决
总结
我已经把小程序的框架简单的介绍了一遍,希望在脑海里有一个清晰的思路,这样运用起来将会非常得心应手。小程序还有两部分内容,一部分是小程序自带的一些组件,另一部分是小程序的丰富的微信原生API,这两部分内容就没什么可说的了,需要使用什么组件或者是需要调用什么API自己去文档查吧!very easy
下面奉上两个地址:官方组件地址,官方API地址,前端的你时时刻刻都需要提升自己