小程序
常用UI组件
text文本
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
selectable | Boolean | false | 文本是否可选,除了text以外其他组件都无法长按选中 |
space | String | 显示连续空格,可选值:ensp英文符大小,emsp中文符大小,nbsp空格大小会根据字体大小而改变 | |
decode | Boolean | false | 是否解码, < > & '     |
<text decode>5<7</text>
view视图容器
块级元素
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
hover-class | String | none | 指定按下去的样式类,当hover-class="none"时,没有点击态效果 |
hover-stop-propageation | Boolean | false | 指定是否阻止本节点大的祖先节点出现点击态,添加在子级节点中 |
hover-start-time | Number | 500 | 点击后多久出现点击态,单位毫秒 |
hover-stay-time | Number | 700 | 点击后点击状态保留事件,单位毫秒 |
<view hover-class="box" hover-start-time="10000" hover-stay-time="6000">握手</view>
.box {
color:red
}
button 按钮
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
size | String | default | 按钮大小 可选 mini |
type | String | default | 按钮的样式类型 背景颜色 |
plain | Boolean | false | 按钮是否镂空,背景色透明 |
disable | Boolean | false | 是否禁用 |
loading | Boolean | false | 名称前是否loading图标 |
<button type="primary" loading="true">按钮</button>
<button type="warn" disabled>按钮</button>
<button type="primary" plain>按钮</button>
input 输入框
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 输入框的初始内容 | |
type | String | “text” | input的类型 |
password | Boolean | false | 是否是密码类型 |
placeholder | String | 输入框为空时占位符 | |
disable | Boolean | false | 是否禁用 |
maxlength | Number | 140 | 最大输入长度,设置为 -1 的时候不限制最大长度 |
<input value="000" type="number" password="true"></input>
<input placeholder="请输入内容" maxlength="5"></input>
<input placeholder="请输入内容" disabled></input>
image 图片
image默认宽度300px、高度225px
属性名 | 说明 |
---|---|
src | 图片的路径支持本地和网络上的图片 |
mode | 指定图片剪裁,缩放的模式 4个缩放,9个剪裁 |
<image src="/img/img/1.jpg" mode="aspectFit"></image>
<image src="https://dss0.baidu.com/73x1bjeh1BF3odCf/it/u=3501484420,2335078330&fm=85&s=4A86DA0AC6A6A4FED679F587000030C1"
mode="aspectFill">
</image>
wxss
属性选择器:在小程序中的所有的自定义属性必须以"data-",
rpx、
微信小程序独有的解决屏幕自适应的尺寸单位
-
根据屏幕宽度进行自适应,不论大小屏幕,规定屏幕宽度为750rpx
-
通过rpx设置元素的字体大小,小程序在不同尺寸的屏幕上可以实现自动适配
-
rpx与px之间的单位换算 ,以iPhone6为例 1rpx=0.5px=1物理像素
设备 rpx换算px(屏幕宽度/750) px换算rpx(750/屏幕宽度) iPhone5 1rpx=0.42px 1px=2.34rpx iPhone6 1rpx=0.5px 1px=2rpx iPhone6 Plus 1rpx=0.552px 1px=1.81rpx 在iPhone6上面绘制一个宽100px,高200px的盒子,换算成rpx单位后就是200rpx和400rpx
rpx和iPhone设计稿的关系
设计师根据iPhone6作为视觉稿的标准,如果根据iPhone6的设计稿,绘制小程序页面,可以直接吧单位px换算成rpx。如果iPhone6设计稿上面,绘制一个宽高为100px的盒子,单位换算为200rpx
375rpx永远会被各种屏幕尺寸识别为屏幕宽度的一般
@import 样式导入
使用@import语句导入外联样式表
语法格式:@import “wxss样式表的相对路径”
全局配置文件app.json
小程序根目录下的app.json文件用来对微信小程序进行全局配置,它决定了页面的路径,窗口表现,设置网络超时时间,设置多tab栏等
-
pages 数组:配置小程序的页面路径
- pages用于指定下程序由那些页面组成,每一项都对应一个页面的 路径+文件名 信息
- 文件名不需要后缀,框架会自动去寻找对应位置的json,.js, .wxml, .wxss,四个文件
- 数组的的一项代表下程序的初始页面(首页)
- 小程序中新增/减少页面,都需要对pages 数组进行修改
-
window 对象:用于设置小程序的状态栏,导航条,标题,窗口背景颜色,
-
tabBar 对象:配置小程序的tab栏效果
-
tab栏最多有5项,最少有2项
-
小程序中通常有底部tabBar和顶部tabBar,但是顶部的tabBar不包含icon图标,只显示文本
属性 类型 必填 默认值 描述 color HexColor(16进制) 否 tab上的文字默认颜色 selectedColor HexColor(16进制) 否 tab上的文字选中时的颜色 backgroundColor HexColor(16进制) 否 tab的背景颜色 borderStyle String 否 black tabBar上边框的颜色 list Array 是 tabBar的列表,详见list属性说明,最少2个,最多5个tab position String 否 bottom tabBar的位置,bottom,top tabBar节点中list的配置项
属性 类型 必填 描述 pagePath String 是 页面路径必须在pages中先定义 text String 是 tab上按钮文字 iconPath String 否 图片路径;不支持网络图;当position为top时,不显示icon selectedlconPath String 否 选中时的图片路径;不支持网络图
-
{
"pages": [
"pages/home/home",
"pages/index/index",
"pages/ss/ss",
"pages/logs/logs",
"pages/swipers/swipers"
],
"window": {
// 设置下拉loding的样式
"backgroundTextStyle": "dark",
// 设置导航条的背景颜色 ,只接受16进制的颜色
"navigationBarBackgroundColor": "#c3c4c5",
// 设置小程序的标题
"navigationBarTitleText": "Speike",
// 设置导航栏标题文本颜色
"navigationBarTextStyle": "white",
// 开启下拉刷新,每一页面全局开启
"enablePullDownRefresh": true,
// 设置下拉刷新的背景色
"backgroundColor": "#ccc",
// 设置上拉触底,默认距离为50像素,如果没有特殊需求建议使用默认值
"onReachBottomDistance": 80
},
"tabBar": {
"selectedColor": "#00ff00",
"color": "000000",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"selectedIconPath": "/assets/images/home-active.png",
"iconPath": "/assets/images/home.png"
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"selectedIconPath": "/assets/images/contact-active.png",
"iconPath": "/assets/images/contact.png"
},
{
"pagePath": "pages/ss/ss",
"text": "客服会话",
"selectedIconPath": "/assets/images/message-active.png",
"iconPath": "/assets/images/message.png"
},
{
"pagePath": "pages/swipers/swipers",
"text": "轮播图",
"selectedIconPath": "/assets/images/message-active.png",
"iconPath": "/assets/images/message.png"
}
]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
页面级别的page.json
小程序中,app.json中window节点,可以全局配置小程序每一个页面的窗口表现;
如果某些小程序页面,想要有特殊的窗口表现,此时,”页面级别的.json配置文件“,可以实现这种需求,页面级别的配置优先于全局配置生效
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色 |
navigationBarTextStyle | String | white | 导航栏标题颜色 |
navigationBarTitleText | String | 导航栏标题文字内容 | |
backgroundColor | HexColor | #ffffff | 窗口的背景颜色 |
backgroundTextStyle | String | dark | 下拉loding的样式,仅支持dark/light |
enablePullDownRefresh | Boolean | false | 是否全局开启下拉刷新 |
onReachBottomDistance | Number | 50 | 页面的上拉触底 |
disableScroll | Boolean | false | 设置为true则页面整体不能上下滚动,只有在页面配置中有效,无法在app.json中设置改项 |
页面的.json中只能设置window相关的配置项,以决定本页面的窗口表现
小程序中的生命周期
- 应用生命周期: 特指小程序 => 运行 => 销毁的过程
- 页面生命周期: 特指小程序中,每个页面的加载 => 渲染 => 销毁的过程
小程序生命周期函数
生命周期函数:由下程序框架提供的内置函数,会伴随这生命周期,自动按次序执行;
生命周期函数的作用: 允许程序员在特定的生命周期节点上,执行某些特定的操作。例如页面刚开始进来时自动发起数据请求,获取当前页面的数据。
注意: 生命周期强调的是一个时间段,生命周期函数强调的是一个时间点
属性 | 类型 | 描述 | 触发时机 |
---|---|---|---|
onLauch | Function | 生命周期回调函数-监听小程序初始化 | 小程序初始化完成时(全局只触发一次) |
onShow | Function | 生命周期回调函数-监听小程序显示 | 小程序启动,或从后台进入前台显示时 |
onHide | Function | 生命周期回调函数-监听小程序隐藏 | 小程序从前台进入后台时 |
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
console.log('初始化完成')
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log('小程序启动')
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
}
})
小程序页面生命周期函数
页面生命周期函数必须调用Page()函数,否则就会报错,Page()函数用来注册小程序页面的
Page(Object)函数接收一个Object参数,可以通过这个Object参数指定页面生命周期函数
属性 | 类型 | 描述 |
---|---|---|
onLoad | Function | 生命周期回调函数-监听页面加载 |
onShow | Function | 生命周期回调函数-监听页面显示 |
onReady | Function | 生命周期回调函数-监听页面初次渲染完成 |
onHide | Function | 生命周期回调函数-监听页面隐藏 |
onUnload | Function | 生命周期回调函数-监听页面卸载 |
page({
onLoad: function(options){}, //监听页面加载
onShow: function(){}, // 监听页面显示
onReady: function(){}, // 监听页面初次渲染完成
onHide: function(){}, // 监听页面隐藏
onUnload: function(){} // 监听页面卸载
})
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
小程序的数据绑定与事件绑定
数据绑定
- 小程序中每一个页面,有4部分组成,其中 .js 文件内可以定义页面的数据,生命周期函数,以及其他业务逻辑。如果要在 .js 文件内定义页面的数据,只需把数据定义到data节点下即可
- 渲染data中的数据使用Mustache语法格式{{}} ,在vue中的插值表达式只允许用在内容节点中,但是在小程序中可以用在属性节点中
- 在Mustache中可以
- 绑定内容
- 绑定属性
- 运算(三元表达式,算术运算,逻辑判断,字符串运算,数据路径运算)
<view>{{info}}</view>
<view id="item-{{id}}">黑子</view>
<view>{{flag ? '条件为真' : '条件为假'}}</view>
Page({
/**
* 页面的初始数据
*/
data: {
info: '我是定义的数据',
id: '0',
flag: true
}
)}
事件绑定
bindtap绑定触摸事件:
在小程序中是不存在网页中的onclick鼠标点击事件,而通过tap事件来响应触摸行为
bind 是阻止不了冒泡的,catch 可以阻止事件的冒泡行为
bindtap 改成 catchtap可以阻止事件冒泡行为
<view bindtap="tapName">click me</view>
Page({
tapName(){
console.log('点击了')
},
)}
bindinput绑定文本框输入事件:
在小程序中通过input事件来响应文本框的输入事件
<input bindinput="inputName"></input>
Page({
inputName(e){
console.log(e)
console.log(e.detail.value)
},
)}
data和文本框之间的数据同步
- 监听文本框的数据变化, e.detail.value
- 修改data中的数据 ,通过**this.setData()**方法可以给页面中的data重新赋值
<input bindinput="inputName"></input>
<view>{{msg}}</view>
Page({
data: {
msg:'',
},
inputName(e){
console.log(e)
console.log(e.detail.value)
this.setData({
msg: e.detail.value
})
},
)}
事件传参
在小程序中不能在为组件绑定事件的同时,为事件处理函数传递参数的
下面的代码将不能正常工作
<view bindtap="tapName(123)">事件传参</view>
小程序会把bindtap后指定的值,统一当作事件名称来处理
如果要在组件触发事件处理函数的时候传递参数,可以为组件提供**data-***自定义属性传参
<view bindtap="tapName" data-info="{{123}}">事件传参</view>
其中info会被作为参数名,数值123会被作为参数值
获取传递的参数通过event.target.dataset.参数名获取传递的参数
<button type="primary" bindtap="inclick" data-adds="www">按钮传参</button>
<view>{{msg}}</view>
Page({
data: {
msg:'',
},
inclick(e){
this.setData({
msg: e.target.dataset.adds
})
},
)}
wxs脚本
wxs没有兼容性:不依赖与运行的基础库版本,可以在所有版本的小程序中运行
wxs与JavaScript不同:wxs与JavaScript是不同的语言,有自己的语法并不和JavaScript一致
隔离性:wxs的运行环境和其他JavaScript代码是隔离的,wxs中不能调用其他JavaScript文件中定义的函数,也不能调用小程序中提供的API
wsx不能作为事件回调:wxs函数不能作为组件的事件回调
在IOS设备上要比JavaScript运行快:在IOS设备上小程序内的wxs会比JavaScript代码快2-20倍,在Android设备上二者运行效率无差异
wxs遵循CommonJS模块化规范
module对象:每个wxs都是独立的模块,每个模块均有一个内置的module对象,每个模块都有自己独立的作用域
module.exports:由于wxs拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见,通过module.exports属性,可以对外共享模块的私有变量与函数
require函数:在wxs模块中引用其他wxs文件模块,可以使用require函数
引用.wxs 文件模块,且必须使用相对路径
wxs模块均为单例,wxs模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个wxs模块对象
如果一个wxs模块在定义后,一值没有被引用,则该模块不会被解析运行,
目前wxs支持,number,string,Boolean,object,function,array,date日期类型,regexp正则
内嵌式wxs代码及使用如下:
<view>{{foo.msg}}</view>
<wxs module="foo">
var some_msg = "hello world"
module.exports = {
msg:some_msg
}
</wxs>
外联wxs脚本
<wxs module="tools" src="../tools.wxs"/>
<!-- 这里的wxs是一个自闭合的标签 路径使用相对路径 module给脚本命一个名称 -->
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
var foo="hello world from tools.wxs"
var bar = function(d) {
return '===' + d + '==='
}
module.exports ={
FOO:foo,
bar:bar
// 这里不能只写一个bar js高级中可以这样写,但是wxs中不可以这样写
}
module.exports.msg = 'some msg'
wxs中不能使用JavaScript高级语法
页面渲染
vx:if
<view wx:if="{{length > 5}}">1</view>
<view wx:elif="{{length > 3}}">2</view>
<view wx:else>3</view>
Page({
data: {
length:6
}
)}
当判断条件需要渲染多个标签时可以使用标签将多个标签包装起来,并在上面使用wx:if控制属性
<block wx:if="{{ture}}">
<view>1</view>
<view>2</view>
</block>
并不是一个组件,它仅仅是一个包装元素,不会在页面中作渲染,只接受控制属性 鸡肋
hidden
<view hidden="{{flag}}">000</view>
Page({
data: {
flag:true
}
)}
wx:if 与 hidden 的对比
- wx:if会根据条件的改变动态创建或者销毁
- vx:if 是惰性的当条件为false时,框架什么也不会作,只有在条件变为真的时候才会开始局部渲染
- hidden就知识控制元素的显示与隐藏,不会去销毁元素
- wx:if 有更高的切换消耗而hidden有更高的渲染消耗,如多频繁切换的情景下,用hidden比较好,如果在运行条件不大可能改变则wx:if 较好
<view hidden="{{flag}}">000</view>
<button bindtap="click">点击</button>
这里一定要注意取用data中的值时要加data.属性名
Page({
data: {
flag:true
}
click(){
this.setData({
flag: !this.data.flag
// 这里一定要注意取用data中的值时要加data.属性名
})
},
)}
wx:for
wx:for循环渲染数组
<view wx:for="{{list}}" wx:kye="index">索引是:{{index}},值是:{{item}}</view>
<view wx:for="{{list}}" wx:kye="index" wx:for-index="idx" wx:for-tiem="itname">索引是:{{idx}},值是:{{itname}}</view>
Page({
data: {
list:[
'zs',
'ls',
'ww'
]
}
)}
key 值的注意点
-
key值必须具有唯一性,且不能动态改变
-
key的值必须是数字或字符串
-
保留关键字 *this 代表在for循环中的item本身,它也可以充当key值,但是item本身必须是唯一的字符串或者数字
<view wx:for="{{list}}" wx:kye="*this">索引是:{{index}},值是:{{item}}</view>
Page({ data: { list:[ 'zs', 'ls', 'ww' ] } )}
-
如果不提供wx:key ,会报一个warning警告,如果明确知道该列表是静态的,或者不必关心其顺序,也可以选择忽略
下拉刷新
下拉刷新是移动端更新列表数据的交互行为,通过用户手指在屏幕上自上而下的滑动,可以触发页面的下拉刷新,更新列表数据,下拉刷新的用户体验方便友好,已经成为移动端刷新数据的最佳解决方案
两种方式:
-
在app.json的window选项中或这页面配置中开启 enablePullDownRefresh,一般情况下推荐在需要开启下拉刷新的页面中单独开启下拉刷新行为
-
通过**wx. startPullDownRefresh()**触发下拉刷新,调用函数后触发下拉刷新动画,效果与手动下拉刷新一致
<button type="parmary" bindtap="btn">按钮触发下拉刷新</button>
btn(){ wx.startPullDownRefresh() },
监听下拉刷新事件
为页面添加**onPullDownRefresh()**函数,可以监听用户在当前页面的下拉刷新事件
停止下拉刷新效果
当处理完下拉刷新后,下拉刷新的loding效果会一直显示,并不会主动消失,所有需要手动隐藏下拉刷新的loding效果。调用**wx.PullDownRefresh()**可以停止当前页面的下拉刷新
上拉加载更多
在移动端,随着手指不断向上滑动,当内容将要达到屏幕底部的时候,页面会随之不断的加载后续的内容,知道没有内容为止
两种方式
- 可以在app.json的window选项中或者页面的配置中设置触底距离onReachBottomDistance,单位为px,默认50px
- **onReachBottom()**函数可以监听用户在当前页面的上拉触底事件,从而实现上拉加载更多列表数据的效果
**onPageScroll(object)**监听用户页面的滚动事件
属性 | 类型 | 说明 |
---|---|---|
scrollTop | Number | 页面在垂直方向已经滚动的距离(单位px) |
onPageScroll(obj){
console.log('当前页面在垂直方向已经滚动了'+ obj.scrollTop + 'px')
},
**onShareAppMessage(object)**用户点击右上角分享
参数 | 类型 | 说明 |
---|---|---|
from | String | 转发事件来源,button:页面内按钮转发;menu:右上角转发菜单 |
target | Object | 如果from值为button,则target是触发这次转发事件的button否则为undefind |
webViewUrl | String | 页面中包含组件时,返回当前的的url |
按钮转发
<button type="primary" open-type="share"> 转发</button>
转发事件return一个object用于自定义转发内容,返回内容如下
字段 | 说明 | 默认值 |
---|---|---|
title | 转发标题 | 当前程序的名称 |
path | 转发路径 | 当前path,必须是以/开头的完整路径 |
imageUrl | 自定义图片路径,可以是本地文件路径,代码包文件路径或者网络图片路径支持PNG级JPG。显示图片的长宽比为5:4 | 使用默认截图 |
onShareAppMessage: function (obj) {
console.log(obj)
return {
title:'测试转发标题',
// A用户点击转发后,B用户收到分享点击进入之后的页面路径
path:'pages/home/home',
imageUrl:''
}
}
onTabltemTap(object)
点击tab触发,其中object参数说明如下
参数 | 类型 | 说明 |
---|---|---|
index | String | 被点击tabitem的序号,从0开始 |
pagePath | String | 被点击tabitem的页面路径 |
text | String | 被点击tabitem的按钮文字 |
onTabltemTap(item) {
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
}
页面导航
- 声明式导航:通过点击navigator组件实现页面跳转的方式;
- 编程式导航:通过小程序的api接口实现的跳转的方式
声明式导航
- 导航到非tabBar页面
<navigator url='/pages/info/info'>去info页面</navigator>
上述代码使用 url 属性指定要跳转到的页面路径;其中,页面路径应该以 / 开头,且路径必须提前在 app.json 的 pages 节点下声明,才能实现正常的跳转。
- 导航到 tabBar 页面
tabBar 页面指的是被当作 tabBar 进行切换的页面。如果 navigator 组件单纯使用 url 属性,无法导航到 tabBar 页面,需要结合 open-type 属性,值必须是switchTab进行导航。
<navigator url='/pages/home/home' open-type='switchTab'>
导航到home页面
</navigator>
关于 navigator 组件的更多用法,翻阅官方文档
- 后退导航
如果要后退到上一页面或多级页面,需要把 open-type 设置为 navigateBack,同时使用 delta 属性指定后退的层数,
<navigator open-type='navigateBack' delta='1'>
返回上一页
</navigator>
关于 navigator 组件的更多用法,翻阅官方文档
编程式导航
- 导航到非 tabBar 页面
通过 wx.navigateTo(Object object) 方法,可以跳转到应用内的某个页面。但是不能跳到 tabbar 页面。其中 Object 参数对象的属性列表如下:
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | string | 是 | 需要跳转的 tabBar 页面的路径(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数。 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
- 导航到 tabBar 页面
通过 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。其中 Object 参数对象的属性列表如下:
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | string | 是 | 需要跳转的 tabBar 页面的路径(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数。 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
- 后退导航
通过 wx.navigateBack(Object object) 方法,关闭当前页面,返回上一页面或多级页面。其中 Object 参数对象的属性列表如下:
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
delta | number | 是 | 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
声明式导航传参
navigator 组件的 url 属性用来指定导航到的页面路径,同时路径后面还可以携带参数,参数与路径之间使用 ?分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。
<navigator url=‘/pages/logs/logs?name=zs&age=20’>去logs页面</navigator>
编程式导航传参
wx.navigateTo(Object object) 方法的 object 参数中,url 属性用来指定需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。
wx.navigateTo({
url: '/pages/logs/logs?name=zs&age=20',
})
页面接收导航传递过来的参数
不论是声明式导航还是编程式导航,最终导航到的页面可以在 onLoad 生命周期函数中接收传递过来的参数。
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
console.log(options) // options 就是导航传递过来的参数
}
自定义编译模式快速传参
小程序每次修改代码并编译后,会默认从首页进入,但是在开发阶段,我们经常会针对特定的页面进行开发,为了方便编译后直接进入对应的页面,可以配置自定义编译模式,步骤如下:
- 单击工具栏上的“普通编译”下拉菜单;
- 单击下拉菜单中的“添加编译模式”选项;
- 在弹出的“自定义编译条件窗口”,按需添加模式名称、启用页面、启动参数、进入场景等。
网络数据请求
配置服务器域名
每个微信小程序需要事先设置一个通讯域名,小程序只可以跟指定的域名进行网络通信。
服务器域名请在 「小程序后台-开发-开发设置-服务器域名」 中进行配置,配置时需要注意:
- 域名只支持 https (request、uploadFile、downloadFile) 和 wss (connectSocket) 协议
- 域名不能使用 IP 地址或 localhost
- 域名必须经过 ICP 备案
- 服务器域名一个月内可申请5次修改
跳过域名校验
在微信开发者工具中,可以临时开启 「开发环境不校验请求域名、TLS 版本及 HTTPS 证书」 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机开启调试模式时,不会进行服务器域名的校验。
注意:在服务器域名配置成功后,建议开发者关闭此选项进行开发,并在各平台下进行测试,以确认服务器域名配置正确。
发起网络数据请求
发起 get 请求
调用 wx.request(Object object) 方法发起 get 请求
wx.request({// 请求的URL地址,必须基于 HTTPS 协议
url: 'https://www.liulongbin.top:8082/api/get',
// 发送到服务器的数据
data: { name: 'zs', age: 20 },
// 成功之后的回调函数
success: function(result) {
console.log(result)
}
})
<button type="primary" bindtap="gettap">发起get请求</button>
gettap(){
wx.request({
url: 'https://www.liulongbin.top:8082/api/get',
data: { name: 'zs', age: 20 },
// 成功之后的回调函数
success: function (result) {
console.log(result)
}
})
},
发起 post 请求
调用 wx.request(Object object) 方法发起 post 请求,设置一个method选项即可
wx.request({
url: 'https://www.liulongbin.top:8082/api/post',
method: 'POST', // 设置请求类型,如果不设置,默认发起 GET 请求
data: { name: 'ls', gender: '男' }, // 发送到服务器的数据
success: function(result) {
console.log(result)
}
})
<button type="primary" bindtap="posttap">发起get请求</button>
posttap(){
wx.request({
url: 'https://www.liulongbin.top:8082/api/get',
method: 'post'
data: { name: 'zs', age: 20 },
// 成功之后的回调函数
success: function (result) {
console.log(result)
}
})
},
小程序中没有跨域限制
- 在普通网站开发中,由于浏览器的同源策略限制,存在数据的跨域请求问题,从而衍生出了 JSONP 和 CORS 两种主流的跨域问题解决方案。但是,小程序的内部运行机制与网页不同,小程序中的代码并不运行在浏览器中,因此小程序开发中,不存在数据的跨域请求限制问题。
- 关于微信小程序更多的数据请求内容,请翻阅 wx.request() 的相关文档:文档
组件的创建与引用
1. 创建组件
- 在项目的根目录中,鼠标右键,创建 components -> test 文件夹
- 在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”
- 为新建的组件命名之后,会自动生成组件对应的 4 个文件,后缀名分别为 .js,.json, .wxml 和 .wxss
注意:尽量将不同的组件,存放到单独的文件夹中,从而保证清晰的目录结构
2. 引用组件
- 在需要引用组件的页面中,找到页面的 .json 配置文件,新增 usingComponents 节点
- 在 usingComponents 中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的相对引用路径
- 在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上
注意:注册组件名称时,建议把名称注册为短横线连接的形式,例如 vant-button 或 custom-button
{
"usingComponents": {
"custom-test": "../../components/test/test"
}
}
3. 使用样式美化组件
组件对应 wxss 文件的样式,只对组件 wxml 内的节点生效。编写组件样式时,需要注意以下几点:
- 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
- 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
- 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
- 继承样式,如 font 、 color ,会从组件外继承到组件内。
- 除继承样式外, app.wxss 中的样式、组件所在页面的样式对自定义组件无效。
组件的 data 与 methods
1. 使用 data 定义组件的私有数据
小程序组件中的 data,和小程序页面中的 data 用法一致,只不过:
-
页面的 data 定义在 Page() 函数中
-
组件的 data 定义在 Component() 函数中
在组件的 .js 文件中:
- 如果要访问 data 中的数据,直接使用 this.data.数据名称 即可
- 如果要为data 中的数据重新赋值,调用 this.setData({ 数据名称: 新值 }) 即可
在组件的 .wxml 文件中:
- 如果要渲染 data 中的数据,直接使用 {{ 数据名称 }} 即可
<text>这是自定义的test组件</text> <view>当前组件中name的值为{{name}}</view>
// components/test/test.js Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { name:'张三' }, /** * 组件的方法列表 */ methods: { } })
2. 使用 methods 定义组件的事件处理函数
和页面不同,组件的事件处理函数,必须定义在 methods 节点中。示例代码如下:
Component({
methods: {
// 按钮的点击事件处理函数
btnHandler: function() {}
}
})
<button type="ptimary" bindtap="modification">修改name的值</button>
// components/test/test.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
name:'张三'
},
/**
* 组件的方法列表
*/
methods: {
modification(){
this.setData({
name:'李四'
})
}
}
})
组件的 properties
1. properties 的作用
类似于 vue 组件中的 props, 小程序组件中的 properties,是组件的对外属性,用来接收外界传递到组件中的数据。
在小程序中,组件的 properties 和 data 的用法类似,它们都是可读可写的,只不过:
- data 更倾向于存储组件的私有数据
- properties 更倾向于存储外界传递到组件中的数据
2. 声明 properties 的两种方式
Component({
properties: {
// 完整的定义方式
propA: { // 属性名
type: String, // 属性类型
value: '' // 属性默认值
},
propB: String // 简化的定义方式
}
})
注意:type 的可选值为 Number,String、Boolean、Object、Array、null(表示不限制类型)
3. 为组件传递 properties 的值
可以使用数据绑定的形式,向子组件的属性传递动态数据,示例代码如下:
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
</component-tag-name>
</view>
在以上例子中,组件的属性 propA 和 propB 将收到页面传递的数据。页面可以通过 setData 来改变绑定的数据字段。
注意:在定义 properties 时,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“attr value”),应用于数据绑定时,采用驼峰写法(attr=“{{propertyName}}”)。
4. 在组件内修改 properties 的值
小程序中,properties 的值是可读可写的,它的用法与 data 几乎一致,因此可以通过 setData 修改 properties 中任何属性的值,示例代码如下:
properties: {
count: Number
},
methods: {
add: function() {
this.setData({ count: this.properties.count + 1 })
}
}
数据监听器
1. 什么是数据监听器
数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。作用类似于 vue 中的 watch。
数据监听器从小程序基础库版本 2.6.1 开始支持。
数据监听器的基本语法格式如下:
Component({
observers: {
'字段A, 字段B': function(字段A的新值,字段B的新值) {
// do something
}
}
})
2. 监听子数据字段的变化
Component({
observers: {
'some.subfield': function (subfield) {
// 使用 setData 设置 this.data.some.subfield 时触发
// (除此以外,使用 setData 设置 this.data.some 也会触发)
},
'arr[12]': function (arr12) {
// 使用 setData 设置 this.data.arr[12] 时触发
// (除此以外,使用 setData 设置 this.data.arr 也会触发)
}
}
})
3. 使用通配符 ** 监听所有子数据字段的变化
Component({
observers: {
'some.field.**': function (field) {
// 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
// (除此以外,使用 setData 设置 this.data.some 也会触发)
field === this.data.some.field
}
}
})
组件的生命周期
1. 组件的主要生命周期
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。其中,最重要的生命周期是 created, attached, detached ,包含一个组件实例生命流程的最主要时间点
- 组件实例刚刚被创建好时, created 生命周期被触发。此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段
- 在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化完毕。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
- **在组件离开页面节点树后, detached 生命周期被触发。**退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发
2. 组件可用的全部生命周期函数
生命周期 | 参数 | 描述 | 最低版本 |
---|---|---|---|
created | 无 | 在组件实例刚刚被创建时执行 | 1.6.3 |
attached | 无 | 在组件实例进入页面节点树时执行 | 1.6.3 |
ready | 无 | 在组件在视图层布局完成后执行 | 1.6.3 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 | 1.6.3 |
detached | 无 | 在组件实例被从页面节点树移除时执行 | 1.6.3 |
error | Object Error | 每当组件方法抛出错误时执行 | 2.4.1 |
3. 定义生命周期函数
生命周期方法可以直接定义在 Component 构造器的第一级参数中。
自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)。
Component({
// 主流定义方法
lifetimes: {
attached() {}, // 在组件实例进入页面节点树时执行
detached() {}, // 在组件实例被从页面节点树移除时执行
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached() {}, // 在组件实例进入页面节点树时执行
detached() {}, // 在组件实例被从页面节点树移除时执行
// ...
})
4. 组件所在页面的生命周期
有一些特殊的生命周期,它们并非与组件有很强的关联,但有时候组件需要获知,以便组件内部处理。这样的生命周期称为"组件所在页面的生命周期",在pageLifetimes定义段中定义,其中可用生命周期包括
生命周期 | 参数 | 描述 | 最低版本 |
---|---|---|---|
show | 无 | 组件所在的页面被展示时执行 | 2.2.3 |
hide | 无 | 组件所在的页面被隐藏时执行 | 2.2.3 |
resize | Object Size | 组件所在的页面尺寸变化时执行 | 2.4.0 |
Component({
pageLifetimes: {
show() { // 页面被展示
},
hide() { // 页面被隐藏
},
resize(size) { // 页面尺寸变化
}
}
})
组件插槽
1. 默认插槽
在组件的 wxml 中可以包含 slot 节点,用于承载组件使用者提供的 wxml 结构。默认情况下,一个组件的 wxml 中只能有一个slot。需要使用多 slot 时,可以在组件 js 中声明启用。
注意:小程序中目前只有默认插槽和多个插槽,暂不支持作用域插槽。
<!-- 组件模板 -->
<view class="wrapper">
<view>这里是组件的内部节点</view>
<slot></slot>
</view>
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name>
<!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
<view>这里是插入到组件slot中的内容</view>
</component-tag-name>
</view>
2. 启用多个插槽
在组件中,需要使用多 slot 时,可以在组件 js 中声明启用。示例代码如下:
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
3. 定义多个插槽
可以在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽。示例代码如下:
<!-- 组件模板 -->
<view class="wrapper">
<slot name="before"></slot>
<view>这里是组件的内部细节</view>
<slot name="after"></slot>
</view>
4. 使用多个插槽
使用时,用 slot 属性来将节点插入到不同的 slot 中。示例代码如下:
<!-- 引用组件的页面模板 -->
<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>
组件间的通信
1. 组件之间的三种基本通信方式
- WXML 数据绑定:用于父组件向子组件的指定属性传递数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)
- 事件:用于子组件向父组件传递数据,可以传递任意数据。
- 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。
2. this.selectComponent(string)
在小程序的组件中,调用 this.selectComponent(string),可以返回指定组件的实例对象。示例代码如下:
<!-- wxml -->
<component-a class="customA" id= "cA" ></component-a>
<!--父组件的 .js 文件中,可以调用 selectComponent 函数并指定 id 或 class 选择器,获取子组件对象-->
Page({
onLoad(){
// 切记下面参数不能传递标签选择器(component-a),不然返回的是 null
var component = this.selectComponent('.customA'); // 也可以传递 id 选择器 #cA
console.log(component);
}
})
3. 通过事件监听实现子向父传值
事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件。
通过事件监听实现子组件向父组件传值的步骤
- 在父组件的 js 中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
- 在父组件的 wxml 中,通过自定义事件的形式 bind:+事件名=“对应事件的函数名称”,将步骤一中定义的函数引用,传递给子组件
- 在子组件的 js 中,通过调用 *this.triggerEvent(‘自定义事件名称’, { / 参数对象 */ }) ,**将数据发送到父组件
- 在父组件的 js 中,通过 e.detail 获取到子组件传递过来的数据