一、主体
1.组成
由app.js、app.json、app.wxss三个文件组成,放在根目录
app.js根目录的app.js很有用,因为在它内部注册的变量或方法,都是可以被所有页面获取到。可以监听并处理小程序的生命周期、声明全局变量。其余的.js文件可以通过var app = getApp()获取其实例,调用其中定义的方法和变量,但不可以调用声明周期的方法
2.page文件
pages文件夹里是小程序的各个页面,每个界面一般由.wxml、.wxss、.js、.json四个文件组成,四个文件必须是相同的名字和路径
1、.js是页面的脚本文件通过函数page()注册页面,可以指定页面的初始数据、生命周期、事件处理等
2、.xml是页面布局文件,只能使用微信定义的组件
3、.wxss是样式表。
(1)尺寸单位:rpx可以根据屏幕的宽带进行自适应
(2)样式导入:@import导入外联样式表,如:@import "test.wxss";
(3)定义在app.wxss中的全局样式,作用于每个页面。定义在page的.wxss文件只作用与对应的页面,会覆盖app.wxss中相同的选择器
4、.json是页面的配置文件,只能设置app.json中的window配置内容,会覆盖app.json中的window的相同配置项
二、视图层 WXML
2.1 数据绑定
传统视图和数据绑定
小程序数据绑定
小程序通过什么方式来管理视图和对象绑定的呢?状态模式-单向数据流,从下图可以看出少了DOM操作。数据流是单向的,即视图变化不会影响对象状态
.wxml中的动态数据都来自page中的data。数据绑定使用双大括号将变量包括起来,可以作用于内容、组件属性、控制属性、关键字
// .wxml文件
<view>{{message}}</view>
<view id='item-{{id}}'></view>
<view wx:if="{{status}}"></view>
<view hidden="{{hidden}}"></view>
// .js文件夹
page({
data:{
message:"hello",
id:0,
status:true
}
})
2.2 条件渲染
用wx:if ="{{status}}"来判断是否渲染代码块
<view wx:if="{{num > 5}}">isShow</view> <!-- 如果小于5,则显示isShow -->
<view wx:elif="{{num > 9}}">hidden</view> <!-- 否则如果小于9,显示hidden -->
<view wx:else>C</view> <!-- 否则显示C -->
2.3 列表渲染
(1)在组件上使用wx:for属性绑定一个数组,就可以渲染组件
(2)默认情况下数组的当前下标变量名为index,当前项的变量名为item
// .wxss 循环数组
<view wx:for="{{array}}"
{{index}} : {{item.message}}
</view>
//.js
page({
data:{
array:["xx","jj","tt"]
}
})
(3)使用wx:for-index可以指定数组当前下标的变量名,使用wx:for-item可以指定数组当前元素的变量名
<view wx:for="{{array}}" wx:for-index="num" wx:for-item="listName"> //wx:for-index 和 wx:for-item 同时使用 当前下标名 当前元素的变量名 (不懂)
{{num}} : {{listName}}
</view>
2.4 模板template
(1)name定义组件模板的名称,引用模板的时候使用is属性指定模板的名字,is可以进行简单的三目运算符,需要传入模板需要的data数据。
(2)因为模板拥有自己的作用域,所以只能使用data传入数据,而不接受花括号的写法
<template name="msgItem">
<view>
<text>{{index}} : {{msg}}</text>
<text>Time:{{time}}</text>
</view>
</template>
<!-- 其它代码 -->
<template is="msgItem" data="{{...item}}" />
2.5 公共模块的引用
(1)WXML提供import和include两种文件引用方式。
(2)import有作用域的概念,不能多重引用
例:使用import导入 B.wxml只能导入到A.wxml中(引用到A文件),不能导入其它文件
<!-- A.wxml -->
<import src="B.wxml">
<!-- B.wxml -->
<template name="A">
<text>A template</text>
</template>
例:使用include导入
<!-- header.wxml -->
<view>header</view>
<include src="footer.wxml"/>
//其它wxml文件
<!-- 引用header。其中header.xml中也引入了footer.wxml -->
<include src="header.wxml">
<view>body</view>
2.6 事件
(1)名称以bind开头的事件不阻止冒泡,名称以catch开头的事件冒泡是阻止的。如bindTab和catchTab
(2)在wxml中,可以使用dataset定义data中的数据,会通过事件传递。它的事件以data-开头,多个单词以-链接,如data-a-b
三、小程序的生命周期
3.1 App() 应用生命周期
(1)用户首次打开小程序,触发onLauch(全局只触发一次)
(2)小程序初始化完成后,触发onShow方法,监听小程序显示
(3)小程序从前台进入后台,触发onHide方法
(4)从后台进入前台显示,触发onShow方法
(5)后台运行一定时间,或系统资源占用过高,会被销毁
(6)小程序出错,触发onError
前台、后台定义:当用户点击左上角关闭,或者按了设备home键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台
//app.js
//app.js
App({
onLaunch:function() {
// 小程序初始化(全局只触发一次)
},
onShow:function() {
// 小程序显示
},
onHide:function() {
// 小程序隐藏
},
onError:function() {
// 小程序错误
}
})
例:
App({
onLaunch: function (options) {
console.log("app.js ---onLaunch---" + JSON.stringify(options));
},
onShow: function () {
console.log("app.js ---onShow---");
},
onHide: function () {
console.log("app.js ---onHide---");
},
onError: function (msg) {
console.log("app.js ---onError---" + msg);
},
globalData: {
userInfo: null
}
})
结果:
3.2 Page页面生命周期
每个页面也有自己的生命周期
(1)小程序注册完成后,加载页面,触发onLoad方法。
(2)页面载入后触发onShow方法,显示页面。
(3)首次显示页面,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次
(4)当小程序后台运行或跳转到其他页面时,触发onHide方法
(5)当小程序从后台进入前台或重新进入页面时,触发onShow方法
(6)当使用重定向方法wx.redirectTo(OBJECT)或关闭当前页返回上一页wx.navigateBack(),触发onUnload
//index.js
page({
onLoad:function(options) {
// 页面加载-----(一个页面只会调用一次)
},
onReady:function() {
// 页面渲染----(一个页面只会渲染一次)
},
onShow:function() {
// 页面显示----(每次打开页面都会被调用一次)
},
onHide:function() {
// 页面隐藏---(当navigateTo或底部tab切换时调用)
},
onUnload:function() {
// 页面卸载---(当redirectTo或navigateBack得时候调用)
},
})
3.3 应用生命周期影响页面生命周期
3
(1)初始化后,单首次加载触发onLoad,只会触发一次
(2)进入后台,第一次执行页面onHide方法,第二次执行应用onHide方法
(3)从后台进入前台,第一次执行应用onShow方法,第二次执行页面onShow方法
例:
Page({
onLoad: function (options) {
console.log("page ---onLoad---");
},
onReady: function () {
console.log("page ---onReady---");
},
onShow: function () {
console.log("page ---onShow---");
},
onHide: function () {
console.log("page ---onHide---");
},
onUnload: function () {
console.log("page ---onUnload---");
}
})
四、小程序限制
4.1 程序限制
(1)js内不能使用window等对象 ps:小程序页面的逻辑是在jsCode下运行,jsCode是没有窗口运行环境
(2) zepto/jquerry 会使用到window对象和document对象,所以无法使用
(3)样式表不支持级联选择器
(4)本地资源无法通过css获取 background-image 可以使用网络图片,或者 base64 ,或者使用标签
(5)不支持A标签,无法打开普通网页
4.2 数量限制
(1)底部或顶部可以添加tab按钮区域tabBar是一个数组,只能配置最少2个、最多5个tab,tab按数组的顺序排序
(2)一个应用同时只能打开5个页面
(3)小程序的wx.request请求最大并发数是10个
4.3 大小限制
(1)tabBar上的按钮iconPath图片路径,icon大小限制为40kb
(2)tabBar上的按钮 selectedIconPath 选中时的图片路径,icon大小限制也是40kb
(3)setData页面单次传递的数据设置不能超过1024kb
(4)setStorage在本地最大缓存为10MB
(5)小程序源码打包后大小限制为1M
五、路由
页面重定向。如下 详细讲解网址:
https://www.jianshu.com/p/4ed4869bd80f
没登录腾讯视频之前 | 点击登录会跳转到当前页 |
没登录发弹幕时 | 会弹出登录框,登录时候就能发 |
(2)页面设置为tab页,那么只支持wx.switchTab,其它两种接口不支持路由接口访问(1)微信路由有wx.redirectTo、wx.navigateTo和wx.switchTab接口。其中wx.navigateTo在全局最多调用五次
5.1 在什么情况下会触发页面跳转
(1)启动时,初始化第一个页面
(2)打开新页面,当打开新页面时会调用API wx.navigateTo 或使用 <navigator /> 组件
(3)页面重定向,会调用API wx.redirectTo 或使用<navigator /> 组件
(4)页面返回,会调用API wx.navigateBack 或用户按左上角返回按钮
(5)tarbar切换
5.2 如何跳转页面
(1)使用wx.navigateTo 接口跳转,原页面保留
wx.navigateTo({
// 将要跳转的页面
url:"pages/logs/index",
success:function(res){},
..
})
(2)使用wx.redirectTo 跳转,关闭原来的页面,不能返回
wx.redirectTo({
// 将要跳转的页面
url:"pages/logs/index",
success:function(res){},
..
})
(3)点击返回按钮时,程序会调用wx.navigateBack接口返回上一页
wx.navigateBack({
delta:1
})
delta为1表示返回上页面,为2时,表示上上页,以此类推;如果delta大于已打开页面的总页数,则返回首页,返回首页之后,原界面会销毁
(4)使用 navigator 组件跳转
<navigator url='pages/logs/index' hover-class='navigator-hover'>跳转</navigator>
当navigator组件添加redirect属性时,等同于wx.redirectTo接口。默认redirect属性为false,等同于navigateTo接口
当页面跳转时会传一个值:url?key=value&key1=value1
5.3 如何正确使用页面跳转 ps:官方规定最多五个页面同时存在,也就是说页面深度为5
(1)对于可逆操作:使用 wx.navigateTo ,例:从首页跳转到二级页面,从二级页面返回是不需要重新渲染首页
(2)对于不可逆操作(无法返回上一级页面):使用wx.redirectTo。例:用户登录成功后不需要返回登录页面 ps:在首页不能使用wx.redirctTo
(3)对于介绍性等不常用的页面。推荐使用wx.redirectTo或wx.navigatrBack
5.4 页面栈
(1)页面栈以栈(先进后出)的形式维护页面与页面的关系
(2)小程序提供了 getCurrentPages() 函数获取页面栈,第一个元素为首页,最后一个元素为当前页面
使用wx.navigateTo每新打开一个页面,页面栈大小加1,直到页面栈大小加到5为止 (页面栈最大为5)
wx.navigateTo和wx.redirctTo的区别如下:
wx.navigateTo重复打开页面 例:
当使用wx.navigateTo从四级页面跳转到二级页面时,会在页面栈顶添加一个与二级页面初始状态一样的界面。这两个页面时相互独立的。页面栈大小会加1,当大于5时,则wx.navigateTo无效
使用wx.redirctTo从四级页面重定向到二级页面时,此时会关闭四级页面,四级页面会替换成二级页面,两个页面相互独立,页面栈大小不会因此而改变
使用wx.navigateBack返回
它们三个的区别:
方法 | 区别 |
wx.navigateTo | 增加页面栈大小,直至页面栈为5时停止跳转 |
wx.redirectTo | 不会改变页面栈大小 |
wx.navigateBack | 减少页面栈大小,直到页面栈为1时停止返回 |
使用wx.navigateTo方法跳转 例:
.wxml文件
<button bindtap='click'>运行</button>
.js文件
page({
click:function(){
wx.navigateTo({
url: '../index/index' //跳转到index页面
})
六、数据通信
setData :把获取到的信息通过 setData 显示到页面上
6.1 页面之间的通信
// A页面-传递数据 // 需要注意的是,wx.switchTab 中的 url 不能传参数。 wx.navigateTo({ url:'../pageD/pageD?name=raymond&gender=male' }) // B页面-接收数据 通过onLoad的option...
page({
onLoad:function(option){
console.log(option.name + 'is' + option.gender) //raymond is male
this.setData({
option:option
})
}
})
6.2 参数传递
6.2.1 小程序传递参数的方式
1.App.js中设置全局变量
app.js的Data通常放不会更改的数据,在每个页面可以通过APP实例获取Data数据
var app = getApp();
var data = app.data;
2.通过拼接URL直接传递
wx.navigateTo({})中携带参数
wx.navigateTo({
url:'test?id=1'
})
在wxml中使用navigator标签中携带URL参数 例:
<navigator class='test-item' url='pages/logs/index?testId={{testData.testId}}'>跳转</navigator>
说明:将要传递到另一个页面的字符串testId的赋值到URL中
在js页面中使用onLoad方法接收
page({
onLoad:function(options){
var testId = options.testId
console.log(testId)
}
})
navigator跳转URL传递数组
如果一个页面以数组为参数进行传递,如:相册列表传递到另一个页面
<navigator class="test-item" url="../../pages/test/test?testId={{testData.testId}}"></navigator>
在js页面中onLoad方法接收
page({
data:{
//相册列表数据
albumList:[]
},
onLoad:function (options) {
var that = this;
that.setData({
albumList:options.albumList.split(",") //albumList为相册列表数据
})
}
})
3.在wxml中绑定事件后,通过data-hi="参数"的方式传递 ps:如果需要传递多个数据,使用data-[参数]的方式进行传递
<view bindtap="clickMe" data-testId="{{testId}}">
</view>
在js页面使用自定义clickMe方式接收
page({
clickMe:function(event){
var testId = event.currentTtarget.dataset.testid;
wx.navigateTo({
url:'../../pages/test/test'
})
}
})
wxml中配置data-albumlist传递数组
<view bindtap="clickMe" data-albumlist="{{testData.albumlist}}">
</view>
js代码
page({
clickMe:function(){
// 打印出来为字符串,所以还要重新组装成数组
var albumlist = event.currentTarget.dataset.albumlist.split(","); //albumList为相册列表数据
wx.navigateTo({
url:'../../pages/test/test'
})
}
})
4.通过数据缓存存储再获取
存储数据:wx.setStroageSync(KEY,DATA) 获取数据:wx.setStroageSync(KEY)
//缓存
try {
wx.setStorageSync('key','value')
}catch (e){
}
// 再获取
try {
var value = wx.getStorageSync('key')
if(value) {
// 返回的值
}
}catch(e){
// 可能出错的值
}
// 或使用
wx.getStorage({
key:'key',
success:function(res){
console.log(res.data)
}
})