小程序API
界面交互
用于界面交互的API,例如:loading提示框、消息提示框、模态对话框等API loading提示框常配合网络请求来使用,用于增加用户体验.
提示框
对应的API有两个:
1. wx.showLoading() --显示 loading 提示框
wx.showLoading({title:'XX' })
2. wx.hideLoading0) --关闭 loading 提示框
wx.hideLoading({})
javascript
Page({
data:{
numList:[1,2,3,4]
},
//监听用户上拉加载
onReachBottom(){
// console.log('监听用户上拉加载');
//当用户上拉,需要数字进行累加
wx.showLoading({
title:'正在加载中'
})
//当用户上拉加载时,需要对数字进行累加,每次累加3个数字
setTimeout(()=>{
//获取数组的最后一项
const lastNum=this.data.numList[this.data.numList.length-1]
//定义需要追加的元素
const newArr=[lastNum+1,lastNum+2,lastNum+3]
this.setData({
numList:[...this.data.numList,...newArr]
})
wx.hideLoading({})
},1500)
},
//监听用户下拉刷新
onPullDownRefresh(){
// console.log('监听用户下拉刷新');
//产品需求
//当用户上拉加载更多以后,如果用户进行下拉刷新
//需要将数据进行重置
this.setData({
numList:[1,2,3,4]
})
//在下来刷新以后,loading效果可能不会回弹过去
if(this.data.numList.length==4){
wx.stopPullDownRefresh()
}
}
})
模态对话框
1.wx.showModal():模态对话框,常用于询问用户是否执行一些操作

2.wx.showToast():消息提示框,根据用户的某些操作来告知操作的结果 例如:提示删除成功等
本地存储

同步就是异步+Sync
异步:wx.setStorage(),wx.getStorage(),wx.removeStorage(),wx.claerStorage()
过程:set,get,remove,clear
wx.setStorage(key, value)
javascript
page.js中://将数据存储到本地
setStorage(){
//第一个参数:本地存储中指定的key
//第二个参数:本地存储的数据
wx.setStorageSync('num', 1)
//在小程序中
//如果存储的是对象类型数据,不需要使用json.stringfy和json.parse进行转换
//直接进行存储和获取即可
wx.setStorageSync('obj', {name:'tom',age:10})
// console.log('已存储');
//----------------异步API----------------------------
wx.setStorage({
key:'num',
data:1
})
wx.setStorage({
key:'obj',
data:{name:'jerry',age:18}
})
},
//获取本地存储的数据
async getStorage(){
//从本地存储的数据中获取指定key的数据,内容
//------------同步API的获取---------
const num=wx.getStorageSync('num')
const obj=wx.getStorageSync('obj')
// console.log(num);
// console.log(obj);
//----------------异步API的获取----------------------------
const data= await wx.getStorage({
key:'obj'
})
console.log(data);
},
//----------------异步API的删除----------------------------
//删除本地存储的数据
removeStorage(){
// //从本地移除指定key的数据,内容--这是同步
// wx.removeStorageSync('num')
// console.log('删除成功');
wx.removeStorage({
key:'num'
})
},
// //清空本地存储的全部数据
clearStorage(){
// //无需填key,直接默认删全部
// wx.clearStorageSync()
wx.clearStorage()
}
})
路由与通信--编程式导航
在小程序中实现页面的跳转,有两种方式:
1.声明式导航 :navigator 组件
2.编程式导航:使用小程序提供的API
wx.navigateTo ():保留当前 页面,跳转到应用内的某个页面,但是不能跳到tabbar页面
wx.redirectTo( ):关闭当前 页面,跳转到应用内的某个页面。但是不允许跳转到tabbar 页面
wx.switchTab() :跳转到tabBar页面,路径后不能带参数
wx.reLaunch() :关闭所有 页面,打开到应用内的某个页面
wx.navigateBack():关闭当前页面,返回上一页面或多级页面
路径后可以带参数 ,参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔,例如:path?key=value&key2=value2
参数需要在跳转到的页面的onLoad钩子函数中通过形参进行接收
javascript
1.index.js里:函数+跳转并传参到detail页面
Page({
// 保留当前页面,跳转到新页面
goNavigate() {
wx.navigateTo({
url: '/pages/detail/detail?id=1001&name=小程序跳转'
})
},
// 返回上一页(如果有的话)
goBack() {
wx.navigateBack({
//如果是2就是返回上两页
delta: 1
})
}
})
2.detail.js:用onload--接收参数
Page({
data: {
id: '',
name: ''
},
onLoad(options) {
this.setData({
id: options.id,
name: options.name
})
},
goBack() {
wx.navigateBack()
}
})
页面处理函数
上拉加载onReachBottom(){ }
上拉后下面的内容增加(类似瀑布流),直接写在page里就行
下拉刷新onReachBottom(){ }
下拉页面时,页面会自动刷新,以便用户获取最新的内容。直接写在page里就行
具体看上面API提示框部分代码
小程序中实现上拉加载更多的方式:
- 在 app.json 或者 page.json 中开启允许下拉,同时可以配置 窗口、loading 样式等
2.在页面js中定义onPullDownRefresh事件监听用户下拉刷新
拓展
增强scroll-view(滚动条)-多属性
除了scroll-y,还有很多属性
html
<scroll-view
scroll-y
class="scroll-y"
lower-threshold="100" --设置「距离底部多少距离时,触发上拉加载事件」
bindscrolltolower="getMore"-- 触底时触发的事件
enable-back-to-top--是否启用「点击状态栏返回顶部」功能(点击手机顶部状态栏,快速回到列表顶部)
refresher-enabled--是否开启「下拉刷新」功能
refresher-default-style="black"--下拉刷新指示器的默认样式
refresher-background="#f7f7f8"-下拉刷新区域的背景颜色。
bindrefresherrefresh="refreshHanler"--下拉后触发的事件回调
refresher-triggered="{{isTriggered}}"--手动控制「刷新动画」的显示 / 隐藏
>
<view wx:for="{{numList}}" wx:key="this">{{item}}</view>
</scroll-view> -->
自定义组件
创建,注册,使用
创建
注册组件
开发中常见的组件主要分为公共组件和页面组件两种,因此注册组件 的方式也分为两种:
1.全局注册:在app.json 文件中配置usingComponents 进行注册,注册后可以在任意页面 使用
2.局部注册:在页面的json文件中配置usingComponents进行注册,注册后只能在当前页面使用
在usingComponents中进行组件注册时,需要提供自定义组件的组件名和自定义组件文件路径
在将组件注册好以后,直接将自定义组件的组件名当成组件标签名使用即可


数据和方法
组件数据和方法需要在组件js的Component方法中进行定义,
Component创建自定义组件
1.data: 定义组件的内部数据
2.methods:在组件中事件处理程序需要写到methods中才可以
javascript
js:// components/custom-checkbox/custom-checkbox.js
Component({
/*** 组件的属性列表*/
properties: {
},
/*** 组件的初始数据:用来定义当前组件内部需要使用的数据 */
data: {
isChecked:false
},
/**
* 组件的方法列表:在组件中,所有的事件处理程序都需要写到methods方法中
*/
methods: {
//更新复选框的状态--methods里写方法
updateChecked(){
this.setData({
isChecked:!this.data.isChecked
})
}
}
})
javascript
//组件的方法和数据的使用
<view class="custom-checkbox-container">
<view class="custom-checkbox-box">
<checkbox checked="{{isChecked}}" bind:tap="updateChecked"/>
</view>
</view>
属性properties
组件的属性列表:组件的对外属性,主要用来接收组件使用者传给组件内部的数据--父页面使用组件,给它传属性
label:{ type: ,value:' '}
position:type: ;value:
javascript
1.子组件js里定义属性:
Component({
// 属性列表(外部可传递的数据)
properties: {
// 写法1:简单写法(只写类型)
label: String,
// 写法2:完整写法(推荐!)
position: {
type: String, // 类型:string / number / boolean / object / array
value: "left" // 默认值(不传的时候用这个)
},
checked: {
type: Boolean,
value: false
}
}
})
2.父页面wxml里传值:
<!-- 父页面使用组件,给它传属性 -->
<custom-checkbox
label="我是外部传的文字"
position="right"
checked="{{true}}"
/>
3.在子组件wxml使用属性:
<!-- 直接用 {{ 属性名 }} 就行 -->
<view>{{label}}</view>
<view>{{position}}</view>
<checkbox checked="{{checked}}" />
注意事项:
设置属性类型需要使用type属性,属性类型是必填项 ,value属性为默认值
属性类型可以为String、Number、Boolean、Object、Array,也可以为 null 表示不限制类型
wxml的slot(插槽)

组件样式和注意事项
自定义组件拥有自己的wxss样式,组件wxss文件的样式,默认只对当前组件生效
编写组件样式时,需要注意以下几点:
1.app.wxss或页面的wxss中使用了标签名(view)选择器(或一些其他特殊选择器)来直接指定样式
这些选择器会影响到页面和全部组件,通常情况下这是不推荐的做法
2.组件和引|用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器
3.组
组件和引用组件的页面中使用后代选择器(a.)在一些极端情况下会有非预期的表现 ,如遇,请避免使用
- 子
子元素选择器(a>.b)只能用于view组件与其子节点之间 ,用于其他组件可能导致非预期的情况。
5.继承样式,如font、color,会从组件外继承到组件内 。
6.除继承样式外,全局中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)
组件样式隔离stylelsolation
自定义组件的样式只受自身WXSs的影响,但是有时候我们需要组件使用者的样式能够影响到组件, 时候就需要指定特殊的样式隔离选项stylelsolation,选择它支持以下取值:
isolated:表示启用样式隔离,在自定义组件内外,使用class指定的样式将不会相互影响(一般情况下的默认值)--互不影响
apply-shared:表示页面wxss样式将影响到自定义组件,但自定义组件wxss中指定的样式不会影响页面--页面影响组件
shared:表示页面wxss样式将影响到自定义组件,自定义组件wxss中指定的样式也会影响页面和其他设置了apply-shared 或shared 的自定义组件--双向影响
拓展
小程序修改check-box样式
数据监听器observers
监听数据是否变化
observers:{ key:value}
value可以是一个函数,eg.label:function(options){console.log(options)}--这个options就是改变后的值
而这个函数的形参默认是key的值,只要组件使用者修改/传递了数据,这时候在监听器中就能获取传递/修改的数据。
javascript
Component({
/**
* 组件的属性列表
*/
properties: {
label:{
type:String,
value:'测试'
}
},
/**
* 组件的初始数据
*/
data: {
num:10,
count:100,
obj:{name:'tom',age:10},
arr:[1,2]
},
//用来监听数据已经属性是否发生了变化
observers:{
//key:需要监听的数据
//value:就是一个回调函数,形参:最新的数据
num:function(newNum){
//对data中的数据进行监听,如果数据没有进行变化,监听器不会执行
console.log(newNum);
},
// count:function(newCount){
// //对data中的数据进行监听,如果数据没有进行变化,监听器不会执行
// console.log(newCount);
// }
//同时监听多个数据
// 'num,count':function(newNum,newCount){
// console.log(newNum,newCount);
// }
//支持监听属性以及内部数据的变化
// 'obj.name':function(newName) {
// console.log(newName);
// },
// 'arr[1]':function (newItem) {
// console.log(newItem);
// }
//使用通配符
// 'obj.**':function (newObj) {
// console.log(newObj);
// }
label:function(newLabel){
//只要组件使用者传递了数据,这时候在监听器中就能获取传递的数据
//也就是,监听器立即执行
console.log(newLabel);
}
},
/**
* 组件的方法列表
*/
methods: {
//更新数据
updateData(){
this.setData({
num:this.data.num+1,
// 'obj.name':'jetty',
// 'arr[1]':666
label:'最新的标题'
})
}
}
})
组件通信
父往子传值
父组件如果需要向子组件传递数据,只需要两个步骤:
1.在父组件WXML中使用数据绑定的方式向子组件传递动态数据
2.子组件内部使用properties接收父组件传递的数据即可
javascript
子组件:设置默认属性和值的类型
Component({
properties:{
msg: String,
num: Number,
isShow: Boolean,
// 完整写法(推荐)
title: {
type: String,
value: '默认标题' // 父不传就用默认值
}
}
})
父组件:传值给属性
<!-- 普通字符串直接写 -->
<child msg="你好我是父组件" title="首页"/>
<!-- 数字、布尔、变量 必须加 {{}} -->
<child num="{{666}}" isShow="{{false}}"/>
子组件就已经接收到了
子往父传值
子组件如果需要向父组件传递数据,可以通过小程序提供的事件系统实现,可以传递任意数据。
1.自定义组件内部使用triggerEvent方法发射一个自定义的事件 ,同时可以携带数据
2.自定义组件标签上通过bind方法监听发射的事件,同时绑定事件处理函数,在事件函数函数中通过事件对象获取传递的数据
javascript
--------子组件的js里:triggerEvent方法发射一个自定义事件,可携带数据-------
methods: {
updateChecked(){
this.setData({
isChecked:!this.data.isChecked,
})
//自定义组件内部就需要发射一个自定义事件,
//如果组件使用者、父组件需要使用数据,绑定自定义事件 进行获取即可
this.triggerEvent('changeChecked',this.data.isChecked)
}
}
----------父组件的wxml:组件使用bind+子组件的方法:"自定义函数"。---------
其中自定义函数的event就是子组件传来的数据。
<custom-checkbox
position="right"
checked="{{isChecked}}"
bind:changeChecked="getData"
>
我已阅读并同意用户协议和隐私协议
</custom-checkbox>
--------------父组件的js:可打印传递的数据-----------------------------
getData(event){
console.log(event.detail);
if(event.detail){
console.log('提交');
}else{
console.log('请同意协议');
}
},
获取组件实例
父组件可以通过this.selectComponent方法,获取子组件实例对象,这样就可以直接访问子组件的任意数据和方法
this.selectComponent方法在调用时需要传入一个匹配选择器selector
javascript
----------------父组件wxml:点击事件+ 给子组件添加类名或者id名----------------------------
<button type='primary' plain bind:tap="getChild">获取子组件的实例对象</button><custom-checkbox
bind:changeChecked="getData"
position="right"
checked="{{isChecked}}"
class='child'
id='child'
>
我已阅读并同意用户协议和隐私协议 -111
</custom-checkbox>
-------------父组件js里:函数内容包含this.selectComponent('.child')--------
Page({
data: {
list: [],
isChecked:true
},
getData(event){
console.log(event.detail);
if(event.detail){
console.log('提交');
}else{
console.log('请同意协议');
}
},
//获取子组件的实例对象 --这边
getChild(){
//this.selectComponent 方法获取子组件实例对象
//获取到实例对象以后,就能获取子组件所有的数据,也能调用子组件的方法
const res=this.selectComponent('.child')
console.log(res.data.isChecked);
}})
生命周期lifetimes
lifetimes:{created(){ },attached(前两个一打开含该组件的页面就触发)ready,moved,detached(销毁)}

javascript
//组件生命周期声明函数
lifetimes:{
//created:组件实例被创建好以后执行
created(){
console.log('组件 created');
//所以在created钩子函数中不能调用setData
//可以给组件添加一些自定义的属性,可以通过this的方式进行添加
this.test='测试'
// this.setData({
// name:'jerry'
// })
},
//组件被初始化完毕,模板解析完成,已经把组件挂载到页面上
attached(){
console.log('组件 attached');
console.log(this.test);
//一般页面中的交互会在attached钩子函数中进行执行
this.setData({
name:'jerry'
})
},
//组件被销毁时
detached(){
console.log('组件 detached');
},
}
组件所在页面的生命周期

javascript
//组件所在页面的生命周期
pageLifetimes:{
//监听组件所在的页面展示状态(后台切前台)
show(){
console.log('组件所在页面被展示');
},
//监听组件所在的页面隐藏(前台切后台)的状态
hide(){
console.log('组件所在页面被隐藏');
}
}
小程序生命周期总结
一个小程序完整的生命周期由应用生命周期、页面生命周期和组件生命周期三部分来组成
1.小程序冷启动,钩子函数执行的顺序
2.保留当前页面,进入下一个页面,钩子函数执行的顺序
3.销毁当前页面,进入下一个页面,钩子函数执行的顺序
4.小程序热启动,钩子函数执行的顺序


拓展
使用component构造页面
如果使用component方法构造页面,事件处理函数要写在methods里面
注意事项:
1.要求对应json文件中包含usingComponents定义段
2.页面使用Component构造器创建,需要定义与普通组件一样的字段与实例方法
3.页面Page中的一些生命周期方法 (如onLoad)等以"on"开头的方法),在Component中要写在methods属性中 才能生效
4.组件的属性Properties可以用于接收页面的参数,在onLoad)中可以通过this.data拿到对应的页面参数
javascript
json:
{ "usingComponents":{'组件名':"路径"} }
.js:
Component({
//小程序页面也可以使用component方法进行构造
//注意事项:
//1.要求:json文件中必须包含usingComponents字段
//2.里面的配置项需要和component中的配置项一致
//3.页面中page方法有一些钩子函数,事件监听方法,这些钩子函数,事件监听方法必须放到methods里面
//4.组件的属性 properties 也可以接受页面的参数,在onload钩子函数中通过this.data进行接受
properties:{
id:Number,
name:String
},
data:{
name:'tom'
},
methods:{
//更新名字
updateName(){
this.setData({
name:'jerry'
})
},
//满足第三点:钩子函数,事件监听方法必须放到methods里面
onLoad(options){
// console.log('页面加载 -1');
// console.log(options);
//满足第四点:在onload钩子函数中通过this.data进行接受
console.log(this.data.id);
console.log(this.data.name);
},
}
})
.wxml:
<view>{{name}}</view>
<button type="warn" bind:tap="updateName">更新 name</button>profile.wxml:
<custom06 wx:if="{{num===1}}"/>
<button bind:tap="handler" type="warn">销毁自定义组件</button>
<navigator url="/pages/detail/detail?id=10&name=candy">跳转到detail</navigator>
组件复用机制behaviors
一些通用的逻辑和方法提取出来,然后在多个组件中复用,从而减少代码冗余,提高代码的可维护性。
使用Behavior()方法 ,每个behavior可以包含一组属性、数据、生命周期函数和方法
组件和它引用的behavior中可以包含同名的字段 ,对这些字段的处理方法如下:
1.如果有同名 的属性或方法,采用"就近原则",组件会覆盖behavior中的同名属性或方法
2.如果有同名的数据字段且都是对象类型,会进行对象合并 ,其余情况会采用"就近原则"进行数据覆盖
3.生命周期函数和observers不会相互覆盖,会是在对应触发时机被逐个调用,也就是都会被执行
外部样式类
默认情况下,组件和组件使用者之间如果存在相同的类名不会相互影响 ,组件使用者如果想修改 组件的样式,需要就解除样式隔离 ,给我们的开发带来一定的麻烦 。
解决方案:在使用组件时,组件使用者可以给组件传入CSS类名,通过传入的类名修改组件的样式, 在Component中需要用extemalClasses定义若干个外部样式类。
外部样式类的使用步骤:
1.在Component中用externalClasses定义 段定义若干个外部样式类
2.自定义组件标签通过属性绑定的方式提供一个样式类,属性是externalClasses定义的元素 ,属性值是传递的类名
3.将接受到的样式类用于自定义组件内部
注意事项:
在同一个节点上使用普通样式类和外部样式类时,两个类的优先级是未定义的,因此需要添加!important以保证外部样式类的优先级
html
profile.wxml:
<custom09 extend-class="my-class"/>
scss:<custom09 extend-class="my-class"/>custom09.js:Component({
//组件接受的外部样式类
externalClasses:['extend-class']})
wxml:
<!-- 在同一个节点上,如果外部样式类和普通样式类 -->
<!-- 两个类的优先级是未定义的 -->
<!-- 建议:在使用外部样式类时,样式需要通过!important添加权重 -->
<view class="extend-class box">通过外部样式类修改组件的样式</view>
完善复选框案例
总结自定义组件
1.组件基本使用:数据、属性、方法、插槽
2.组件样式使用:组件样式、注意事项、样式隔离、外部样式类
3.组件通信传值:父往子传值、子往父传值、获取组件实例
4.组件生命周期:组件的生命周期、组件所在页面的生命周期、总结了小程序全部的生命周期
5.组件数据监听器:observers
6.组件拓展:使用Component构造页面、组件复用机制behaviors等