小程序基础知识
导航
声明导航
// tab 页面导航 open-type="switchTab"
<navigator url="/pages/logs/logs" open-type="switchTab"> open-type="switchTab"</navigator>
// 非tab页面导航 open-type="navigate" 或者不写
<navigator url="/pages/info/info" open-type="navigate">open-type="navigate"</navigator>
// 返回上一页 open-type="navigateBack"
// delta="1" 回退几页
<navigator open-type="navigateBack" delta="1">返回</navigator>
变成式导航
// tab页面导航
<button bindtap="bindTap">wx.switchTab跳转</button>
bindTap() {
wx.switchTab({
url: '/pages/logs/logs',
})
},
//非tab页面导航
<button bindtap="navigateTo"> wx.navigateTo</button>
navigateTo() {
wx.navigateTo({
url: '/pages/info/info',
})
},
//关闭当前页面,返回上一页面或多级页面
wx.navigateBack({
delta: 2 // 返回的页面数,如果 delta 大于现有页面数,则返回到首页
})
语法wx:for
将数组数据遍历绑定到组件中。通过 wx:for 控制属(类似vue中的指令)实现。
**wx:for 属性将当前组件按着数组的长度动态创建,并且通过 index 变量可以访问到数组的索引值,通过item变量可以访问到单元值。
下面展示一些 `内联代码片`。
**基本用法**
Page({
// 通过 data 属性,初始化页面中用到的数据
data: {
users: [
{name: '小明', age: 16, gender: '男'},
{name: '小刚', age: 19, gender: '男'},
{name: '小红', age: 18, gender: '女'},
{name: '小丽', age: 17, gender: '女'}
]
}
});
<view wx:for="{{users}}">
<text>{{index+1}}</text>
<text>{{item.name}}</text>
<text>{{item.age}}</text>
<text>{{item.gender}}</text>
</view>
注意:**wx:for="{{list}}",使用模版语法{{}}绑定数据
指定索引值变量、单元值变量**
- 通过 wx:for 对数组数据进行遍历时,可以分别指定访问数组索引值变量和单元值的变量。
- wx:for-index 指定索引值变量,wx:for-item 指定单元值变量。
- wx:for 支持嵌套
Page({
// 通过 data 属性,初始化页面中用到的数据
data: {
brands: [
{
name: '耐克',
origin: '美国',
category: ['男装', '女装', '鞋', '体育用品']
},
{
name: 'SK-II',
origin: '韩国',
category: ['防晒霜','面膜', '洗护']
}
]
}
});
<view wx:for="{{brands}}" wx:for-index="k" wx:for-item="v">
<view>
<text>{{k+1}} </text>
<text> {{v.name}} </text>
<text> {{v.origin}}</text>
</view>
<view>
<text wx:for="{{v.category}}">{{item}}</text>
</view>
</view>
wx:key 的值以两种形式提供
1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
2. 保留关键字 `*this` 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
<!--
name 在当前数据中是不重复的,具有唯一性!
现实开发中一般使用数据中的 id 字段
与 vue 不一样,这里只需要添写属性名即可,即不必写 v.name
-->
<view wx:key="name" wx:for="{{brands}}" wx:for-index="k" wx:for-item="v">
<view>
<text>{{k+1}} </text>
<text> {{v.name}} </text>
<text> {{v.origin}}</text>
</view>
<view>
<text wx:for="{{v.category}}">{{item}}</text>
</view>
</view>
block
通过 block 可以将多个组件元素“包”到一起进行渲染,block 只是提供一种结构,并不会被渲染到页面中。一般这样做的目的是可以将多个组件按统一的逻辑进行控制。
<block wx:for="{{users}}">
<text>{{item.name}}</text>
<text>{{item.age}}</text>
</block>
Page({
// 通过 data 属性,初始化页面中用到的数据
data: {
users: [
{name: '小明', age: 18},
{name: '小红', age: 16}
]
}
});
条件渲染
根据条件控制是否渲染某个(些)组件,通过 wx:if和wx:else/wx:elif 属性实现。
1、基本用法
<view wx:if="{{true}}">
<text>锄禾日当午</text>
</view>
2、多分支
<view wx:for="{{users}}">
<text>{{index+1}} </text>
<text> {{item.name}}</text>
<text> {{item.age}} </text>
<text wx:if="{{item.age <= 14}}"> 儿童</text>
<text wx:elif="{{item.age < 18}}"> 未成年</text>
<text wx:else> 成年人</text>
</view>
Page({
// 通过 data 属性,初始化页面中用到的数据
data: {
users: [
{name: '小明', age: 16},
{name: '小红', age: 13},
{name: '小丽', age: 19}
]
}
});
hidden
为小程序组件添加 hidden 属性也可以控制组件是否显示,其效果类似于 vue 中的 v-show,它与 wx:if 的不同之处是 wx:if 通过添加/移除节点实现元素的显示/隐藏,而 hidden 是对过样式 display 属性实现的。
<view hidden="{{true}}">
<text>锄禾日当午</text>
</view>
小程序中组件属性的值如果为布尔类型时,只要包含这个属性即为 true,要表达 false 时,需要通过 {{}} 表达,原因是 {{}} 中的内容为被小程序当成表达式解析,所以 hidden=“{{false}}” 会被解析成数据类型的布尔类型,而如果写成 hidden=“false” 则将 false 当成字符串解析。
事件监听
小程中通过属性为组件添加事件的监听。例如 tap 事件(相当于 html 中的 click事件
语法: bind:事件名称=“回调函数” 或者 bind事件名称=“回调函数”
1.点击click事件:
<!-- 为button组件绑定了 tap 事件,当用户点击了,会执行 sayHi 函数 -->
<button type="primary" bind:tap="sayHi">点我试试</button>
Page({
// 事件回调函数
sayHi: function () {
console.log('Hi~')
}
});
2.监听表单的 blur、 focus事件:
<view>
<label for="">姓名: </label>
<input type="text" bind:focus="sayHi" bind:blur="sayBye" />
</view>
<view>
<label for="">密码: </label>
<input type="text"/>
</view>
Page({
// 事件回调函数
sayHi: function () {
console.log('Hi~');
},
sayBye: function () {
console.log('Bye~');
}
});
事件对象
当某个事件被触发时,通过一个对象可以获得被触发事件的相关信息。事件对象,回调函数的第一个参数即为事件对象。
1.event.target** 获取触发事件的元素属性,例如自定义属性
<view class="parent" data-name="大明" data-age="40" bind:tap="sayHello">
<view class="child" data-name="小明" data-age="16" bind:tap="sayHi">点我试试</view>
</view>
Page({
// 事件回调函数
sayHi: function (ev) {
// ev 即为事件对象,包含了事件相关信息
// 着重关注 ev.target.dataset 它可以获得 wxml 组件中以 data- 开头的自定义属性
console.log(ev.target.dataset);
},
sayHello: function (ev) {
console.log(ev.target.dataset);
}
});
2.event.mark 标记哪个元素的事件被触发了
<view class="parent" mark:name2="大明" bind:tap="sayHello">
<view class="child" mark:name="小明" bind:tap="sayHi">点我试试</view>
</view>
注:ev.mark 是新增加的功能与dataset 有些类似,应用时某些情形下可以互相替代。
事件冒泡
小程序事件处理机制与DOM类似,冒泡现象依然存在,但并非所有事件都会冒泡。
<view class="parent" bind:tap="foo">
<view class="child" bind:tap="bar"></view>
</view>
Page({
// 事件回调函数
foo: function () {
console.log('parent');
},
bar: function () {
console.log('child');
}
});
当点击 .child 盒子时,同时触发了 .child 和 .parent 的 tap事件
cahtch:事件 = “回调函数”
如果想要阻止冒泡现象的发生,可以使用小程序提供了另一种事件监听的方式,即 catch:事件名称=“回调函数” 或 catch事件名称=“回调函数”,bind 和 catch 的区别就在于是否阻止冒泡。
<view class="parent" bind:tap="foo">
<view class="child" catch:tap="bar"></view>
</view>
当点击子盒子,父盒子的事件不会被触发了
事件捕获(了解)
小程序也支持在捕获阶段触发事件,其语法格式为 capture-bind:事件名称=“回调函数”。
事件捕获时事件的触发顺序为 祖先元素 => 父元素 => 子元素,如果父子元素监听了相同的事件时,事件执行顺序为 父元素 => 子元素。
捕获也可以被阻止,其语法格式为 capture-catch:事件名称=“回调函数”,这样父元素事件触发后,子元素便不会再被触发了。
互斥事件 (了解)
所有
mut-bind
是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响bind
和catch
的绑定效果
一个 mut-bind
触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind
绑定函数不会被触发,但 bind
绑定函数和 catch
绑定函数依旧会被触发。
数据更新 this.setData( { a:0} )
使用Page.prototype.setData(Object data, Function callback)方法
字段 | 类型 | 必填 | 描述 | 最低版本 |
---|---|---|---|---|
data | Object | 是 | 要改变的数据 | |
callback | Function | 否 | setData引起的界面更新渲染完毕后的回调函数 | 1.5.0 |
Object
以 key: value
的形式表示,将 this.data
中的 key
对应的值改变成 value
。
其中 key
可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message
,a.b.c.d
,并且不需要在 this.data 中预先定义。
示例代码: wxml:
<view>
<text>{{msg}}</text>
<button bindtap="rev">reverse</button>
<!-- 列表 -->
<view style="display:flex;flex-direction:column">
<text wx:for="{{list}}">{{index+' '+item.name}}</text>
</view>
<button bindtap="changeArr">修改数组</button>
</view>
js:
Page({
data:{
msg: 'hello wx!',
list: [{ id: 1, name: 'html' }, { id: 2, name: 'css' }, { id: 3, name: 'js' }, { id: 4, name: 'java' }],
},
// 数据响应
rev(){
this.setData({
// 反转文字
msg: this.data.msg.split('').reverse().join('')
})
},
// 修改数组
changeArr() {
this.setData({
'list[3].name': 'python'
},()=>{
console.log(this.data.list)
})
}
})
注意:
- 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
- 仅支持设置可 JSON 化的数据。
- 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
- 请不要把 data 中任何一项的 value 设为
undefined
,否则这一项将不被设置并可能遗留一些潜在问题。
扩展阅读::Page方法详解
生命周期
小程序是按着某种特定的流程序执行的,并且允许开发人员对执行过程中的若干节点进行事件监听,通常将这些节点称为生命周期,如小程序启动、销毁等。
vue: 几个生命周期?=》8
分类
小程序中将生命周期分成两类:
- 应用级别
App()中触发
-
页面级别
Page()中触发
App
在小程序 app.js 文件中调用 App() 函数,可以注册一个小程序,应用级别的生命周期在这里进行监听。
// App 函数是小程序内置提供的,接受一个对象类型的数据做为参数。
// 注意大小写
App({
// 小程序启动时
onLaunch: function () {
// 全局只会触发1次
console.log('小程序启动了...');
},
// 小程序前台运行时
onShow: function () {
// 重复执行
console.log('小程序前台运行了...');
},
// 小程序后台运行时
onHide: function () {
// 重复执行
console.log('小程序后台运行了...');
},
// 执行错误时
onError: function (err) {
console.log('出错啦!!!');
},
// 冷启动(如扫码)打开小程序的页面不存在时
onPageNotFound: function () {
console.log('你找到页面去火星了???');
}
})
点击小程序右上角的胶囊的关闭时,并不会将小程序销毁而是处于后台运行的状态,当再次打开小程序时并不会触发 onLaunch 生命周期的监听,而是触发 onShow 将小程序重新前台运行。
关于前台和后台的理解可以简单的理解成最小化了,桌面上暂时看不到,但程序依然在运行,常见的如按了 home 键、接听电话等都会将小程序置于后台运行。
是不是意味着小程序永远都不会被销毁?答案当然不是!小程序销毁是由微信自动控制的,一般情况下如果某个小程序后台运行超过一定时间或者系统内存不足报警时,微信会主动将小程序销毁,当再次从小程序列表找到这个小程序打开时,会再次触发 onLaunch 这个生命周期。
扩展阅读:运行机制
Page
在小程序页面对应的 .js 文件中调用 Page() 函数,可以注册一个小程序页面,页面级别的生命周期在这里进行监听。
// Page 函数是由小程序默认提供的,接受一个对象类型的数据做为参数。
// 注意大小写,必须要调用!!!
Page({
// 1. 初始数据
data: {},
// 2. 定义事件回调
sayHi: function () {
// code...
},
// 3. 监听生命周期
// 页面加载时 vue=>created
onLoad: function () {
// 只会触发1次
console.log('当前页面被加载了...');
},
// 页面显示时(返回、tabBar切换、前台运行)
onShow: function () {
// 重复触发
console.log('当前页面显示了...');
},
// vue=> mounted
onReady: function () {
// 只会触发1次
console.log('当前页面初次渲染完毕了...');
},
// 页面隐藏时(跳转、tabBar切换、后台运行)
onHide: function () {
console.log('当前页面不见了...');
},
// 还有其它,后续应用时介绍
})
onShow 和 onHide 分别表过当前页面是否被显示/隐藏在当前小程序窗口,这其中包括几种情形:
- 页面跳转 => onHide
- 返回 => onShow
- tabBar => onSow 或 onHide
- 前台 => onShow
- 后台 => onHide
场景值 scene
打开小程序的方式多种多样,如扫码、转发、搜索、公众号等,通过场景值可以区分用户是以何种方式打开的小程序,通常用于条件判断或者数据统计等。
在小程序生命周期=>App()函数 onLaunch 和 onShow 中可以获得场景值:
App({
onLaunch: function (res) {
// 根据打开小程序的方式不同,res.scene 的值也不一样
console.log(res.scene);
},
onShow: function (res) {
// 这里也可以获取场景值
console.log(res.scene);
}
})
地址参数query
小程序组件 navigator 指定 url 属性,可以实现页面间的跳转,在跳转的同时支持通过 ? 向跳转页面传递参数,格式如下:
<navigator url="/pages/demo/index?name=小明&age=18">跳转页面</navigator>
在被跳转的页面中通过监听 onLoad 生命周期获得地址中的参数
// pages/demo/index.js
Page({
onLoad: function (query) {
// 获取地址中的参数
console.log(query);
}
})
网络请求
基本使用
语法:wx.request(Object:config)
Page({
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
wx.request({
url: 'http://5990367be1e4470011c46fa8.mockapi.io/meng/user',
success(res) {
console.log(res)
}
})
}
})
使用注意
非法的请求域名
解决办法:
- 通过添加合法域名:满足=》支持https协议和已经备案
- 打开小程序管理后台=》开发=〉开发设置
- 在=》服务器域名=〉点击开始配置
- 在开发者工具=》详情=〉本地设置,关闭校验
⚠️注意:适用于开发、测试阶段
扩展阅读:网络文档