Skip to content
This repository has been archived by the owner on May 4, 2022. It is now read-only.

Latest commit

 

History

History
644 lines (478 loc) · 17.5 KB

3-小程序视图与逻辑.md

File metadata and controls

644 lines (478 loc) · 17.5 KB

目标:

  • 知道如何实现页面之间的导航跳转
  • 知道如何实现下拉刷新效果
  • 知道如何实现上拉加载更多效果
  • 知道小程序中常用的生命周期钩子函数

1. 页面导航

1.1 页面导航简介

1. 什么是页面导航

页面导航指的是页面之间的相互跳转,例如,浏览器实现页面导航的方式有两种:

  • <a>超链接
  • location.href

2. 小程序实现页面导航的方式

  • 声明式导航
    • 在页面中生命一个<navigator>导航组件
    • 通过点击<navigator>组件来实现页面跳转
  • 编程式导航
    • 调用小程序导航 API

1.2 声明式导航

1. 导航到 tabBar 页面

tabBar 页面指的是被配置为tabBar的页面

在使用<navigator>组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性

  • url表示要跳转的页面的地址,必须以/开头
  • open-type表示为跳转的方式,必须是swicthTab
<navigator url="/pages/index/index" open-type="switchTab">
	跳转到 index tabBar
</navigator>

2. 导航到非 tabBar 页面

非 tabBar 页面指的是未被配置到tabBar的页面

在使用<navigator>组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性

  • url表示要跳转的页面的地址,必须以/开头
  • open-type表示为跳转的方式,必须是navigate
<navigator url="/pages/user/user" open-type="navigate">
	跳转到 user
</navigator>

3. 后退导航

如果需要后退到上一级页面甚至多级页面,需要指定open-type属性和delta属性

  • open-type值必须是navigateBack,表示为后退导航
  • delta的值必须是数字,表示后退的级数
<navigator open-type="navigateBack" delta="3">
	后退3个页面
</navigator>

1.3 编程式导航

1. 导航到 tabBar

调用wx.switchTab(Object object)方法,可以跳转到 tabBar 页面,其中 Object 是参数对象,属性如下:

属性 类型 是否必选 说明
url string 需要跳转的 tabBar 的页面路径,路径不能带参数
success function 接口调用成功的回调函数
fail function 接口调用失败的回调函数
complete function 接口调用结束的回调函数(包括成功、失败)
wx.switchTab({
    url: '/pages/index/index',
    // 如果没有特殊需求,写一个 url 即可
    success: function() {
        console.log('跳转成功')
    },
    fail: function() {
        console.log('跳转失败')
    },
    complete: function() {
        console.log('执行跳转')
    }
})

2. 导航到非 tabBar 页面

调用wx.navigateTo(Object object)方法,可以跳转到 tabBar 页面,其中 Object 是参数对象,属性如下:

属性 类型 是否必选 说明
url string 需要跳转的 tabBar 的页面路径,路径不能带参数
success function 接口调用成功的回调函数
fail function 接口调用失败的回调函数
complete function 接口调用结束的回调函数(包括成功、失败)
wx.navigateTo({
    url: '/pages/user/user'
})

3. 后退导航

调用wx.navigateBack(Object object)方法,可以跳转到 tabBar 页面,其中 Object 是参数对象,属性如下:

属性 类型 是否必选 说明
delta number 返回的页面数,如果 delta 大于现有页面数,则返回到首页(默认值:1)
success function 接口调用成功的回调函数
fail function 接口调用失败的回调函数
complete function 接口调用结束的回调函数(包括成功、失败)
// 默认值是 1
wx.navigateBack()

1.4 导航传参

1. 声明式导航传参

navigator 组件中的 url 属性可以指定跳转的页面的路径,同时路径后面也可以携带一些参数:

  • 参数与路径之间使用?分开
  • 参数与参数值直接使用=相连
  • 不同参数之间使用&分割
<navigator url="/pages/info/info?username=zs&age=18">
	跳转到 info 页面
</navigator>

2. 编程式导航传参

调用wx.navigateTo(Object object)方法时,也可以携带参数

<button bindtap="goToInfo"></button>
goToInfo: function () {
    wx.navigateTo({
        url: '/pages/info/info?username=zs&age=18'
    })
}

3. 在 onLoad 中接收导航参数

通过声明式导航的编程式导航进行传递的参数,可以通过在onLoad钩子函数中获取到

onLoad: function (options) {
    // options 就是导航传递过来的参数对象
    console.log(options)
}

2. 页面事件

2.1 下拉刷新事件

1. 什么是下拉刷新

下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,来重新加载页面的行为

2. 启动下拉刷新

  • 全局开启下拉刷新(不推荐)
    • app.json中的window节点中,将enablePullDownRefresh设置为true
  • 局部开启下拉刷新
    • 只为需要的页面单独开启下拉刷新效果
    • 在页面的.json中将enablePullDownRefresh设置为true

3. 配置下拉刷新的样式

通过在页面或全局的.json文件中,配置backgroundColorbackgroundTextStyle来定制不同的下拉刷新样式

  • backgroundColor:配置下拉刷新的背景颜色,仅支持16禁止的颜色值
  • backgroundTextStyle:配置下拉刷新的loading 样式,仅支持dark/light
{
    "backgroundColor": "#00000",
    "backgroundTextColor": "light"
}

4. 监听下拉刷新事件

通过onPullDownRefresh来监听页面的下拉刷新事件

onPullDownRefresh: function() {
    // 下拉刷新,重新获取数据
    this.getDataList()
}

5. 停止下拉刷新的效果

下拉刷新的效果不会自动关闭,我们可以在获取数据成功后让下拉刷新停止。调用wx.stopPullDownRefresh()来关闭下拉刷新

onPullDownRefresh: function() {
    // 获取数据操作......
    // 获取数据成功,停止下拉刷新
    wx.stopPullDownRefresh()
}

2.2 上拉触底事件

1. 什么是上拉触底

上拉触底是移动端的专有名词,指的是通过手指在屏幕上的上拉拉滑动操作,来重新加载页面的行为,一般上拉触底实现的就是分页效果

2. 监听上拉触底事件

通过onReachBottom来监听上拉触底事件

onReachBottom: function() {
    // 上拉触底,加载第二页
    this.getDataList(params)
}

3. 配置上拉触底的距离

上拉触底距离,指的就是触发上拉触底事件后,滚动条距离页面底部的距离,默认是 50 px,我们可以在全局或页面的.json文件中,配置onReachBottomDistance来改变上拉触底的距离,默认是 px 作为单位,配置时不需要加入单位

{
    "onReachBottomDistance": 80
}

4. 上拉触底案例

定义获取随机色的方法
Page({
  data: {
    colorList: [],
  },

  getColors: function(){
    return Math.floor(Math.random()*255)
  },

  getColorList: function(){
    const arr = []
    for(let i=0;i<10;i++){
      arr[i] = {id: i, color: [this.getColors(), this.getColors(), this.getColors()]}
    }
    return arr;
  },

  getColorListByPage: function(){
    const arr = this.getColorList();
    this.setData({
      colorList: [...this.data.colorList, ...arr]
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.getColorListByPage();
  },
}
美化样式
<view 
      wx:for="{{ colorList }}"
      wx:key="{{item.id}}"
      class="color-item"
      style="background-color: rgba({{item.color}})"
>{{item.color}}</view>
.color-item {
  border:1px solid #efefef;
  line-height: 200rpx;
  border-radius: 15rpx;
  margin: 15rpx;
  text-align: center;
  text-shadow: 0rpx 0rpx 5rpx #fff;
  box-shadow: 1rpx 1rpx 6rpx #aaa;
}
添加 loading 加载效果

调用wx.showLoading(Object object)显示加载框,调用wx.hideLoading()隐藏加载框

getColorListByPage: function(){
    wx.showLoading({
        title: '加载中...',
    })
    new Promise((resolve) => {
        setTimeout(()=> {
            const arr = this.getColorList();
            this.setData({
                colorList: [...this.data.colorList, ...arr]
            })
            resolve()
        },300)
    }).finally(() => {
        wx.hideLoading({
            success: (res) => {},
        })
    })
},
对上拉触底进行节流
  • 在 data 中定义 isloading 节流阀
  • 在获取颜色的方法中修改 isloading 节流阀的状态
    • 获取颜色刚开始,将节流阀改为 true
    • 获取颜色结束,将节流阀改为 false
  • 在 onReachBottom 中判断节流阀的状态
    • 如果节流阀是 false,才会触发请求颜色
自定义编译模式

如果我们的首页是index,但是我们在开发user这个Tab,每次更新都要重新点击一次,那么有方法可以更新后直接进入到user呢?

将启动页面更改为pages/user/user即可,还可以设置启动参数和进入场景

3. 生命周期

3.1 什么是生命周期

生命周期(Life Cycle)是指一个对象从创建 -> 运行 -> 销毁的整个过程。强调的是一个时间段。

  • 小程序启动,表示生命周期的开始
  • 小程序关闭,表示生命周期的结束
  • 小程序运行的过程,表示整个小程序的生命周期

3.2 声明周期的分类

在小程序中,生命周期分为两类:

  • 应用生命周期
    • 小程序从启动 -> 运行 -> 销毁的过程
  • 页面生命周期
    • 小程序中每个页面的加载 -> 渲染 -> 销毁 的过程

小程序的生命周期

3.3 生命周期函数

1. 什么是生命周期函数

生命周期函数:由小程序框架提供的内置函数,会伴着生命周期的不同阶段自动按次序执行

生命周期函数的作用:允许程序员在特定时间执行特定操作,比如在onLoad函数中加载页面的初始数据

注意:生命周期强调的是一个时间段,生命周期函数强调的是一个时间点

2. 生命周期函数的分类

生命周期函数分为两类:

  • 应用的生命周期函数
  • 页面的生命周期函数

3. 应用的生命周期函数

小程序的应用生命周期函数需要在app.js中声明,示例如下:

// app.js
App({
    // 小程序初始化完成执行此函数,全局仅触发一次
    onLaunch: function () {},
    // 小程序启动,或从后台进入前台时触发
    onShow: function (options) {},
    // 小程序从前台进入后台时触发
    onHide: function () {},
    // 小程序脚本出现错误时,或调用 API 失败时,调用此函数,并携带错误信息
    onError: function (msg) {}
})
  • 前台与后台:如果我们切换界面,例如按下 Home 键,此时小程序就进入后台运行

  • onLaunch:小程序初始化触发,全局仅触发一次

  • onShow:小程序在前台运行时触发

  • onHide:小程序在后台运行时触发

  • onError:小程序 JS 脚本错误,或调用 API 错误时触发

4. 页面的生命周期函数

小程序的页面生命周期函数需要在Page.js中声明,示例如下:

Page({
    // 监听页面加载,一个页面只调用1次
    onLoad: function (options) {},
    // 监听页面初次渲染完成,一个页面只调用1次
    onReady: function () {},
    // 监听页面显示
    onShow: function () {},
    // 监听页面隐藏
    onHide: function () {},
    // 监听页面卸载(销毁)
    onUnload: function() {}
})
  • onLoad:监听页面加载,一个页面只调用1次
  • onReady:监听页面初次渲染完成,一个页面只调用1次
  • onShow:监听页面显示
  • onHide:监听页面隐藏
  • onUnload:监听页面卸载(销毁)

4. WXS 脚本

4.1 WXS 简介

1. 什么是 WXS

WXS(WeiXin Script)是小程序独有的脚本语言,结合 WXML,可以构建出页面结构

2. WXS 的应用场景

WXML 中无法调用页面中的.js的函数,但是 WXML 可以调用 WXS 中的函数,因此小程序中的 WXS 的典型应用场景是过滤器

3. WXS 和 JS 的关系*

虽然 WXS 的语法类似于 JavaScript,但是本质上这两者是完全不同的编程语言:

  • WXS 有自己的数据类型
    • number数值类型,string字符串类型,boolean布尔类型,object对象类型
    • function函数类型,array数组类型,date日期类型,regexp正则类型
  • WXS 不支持 ES6 及以上的高级语法
    • 不支持:let、const、解构赋值、展开运算符、箭头函数、对象属性简写、etc...
    • 支持:var声明变量,普通function以及其他 ES5 语法
  • WXS 遵循 CommonJS 的规范
    • module对象
    • require函数
    • module.exports暴露成员

4.2 基础语法

1. 内嵌 WXS 脚本

wxs 可以编写在 WXML 的<wxs>标签内,类似于 JS 编写在 HTML 的<script>

每一个<wxs>标签必须提供module属性,用来指定当前 WXS 的模块名称,方便在 WXML 中访问成员

<view>{{ m1.toUpper('zs') }}</view>
<wxs module="m1">
    module.exports.toUpper = function(str) {
    	return str.toUpperCase();
    }
</wxs>

2. 外联 WXS 脚本

wxs 还可以编写在.wxs文件内

// tool.wxs
var toLower = function (str) {
    return str.toLowerCase()
}
module.exports = {
    toLower: toLower
}
<!-- WXML 页面中 -->
<wxs src="./tool.wxs" module="tool"></wxs>
<view>{{ tool.toLower('LS') }}</view>

4.3 WXS 的特点

1. 与 JavaScript 不同

为了降低 WXS 的学习成本,WXS 在设计初借鉴了 JS 的很多语法,但是本质上,WXS 与 JS 是两门不同的编程语言!

2. 不能作为组件的事件回调

WXS 的典型应用场景就是过滤器,经常配合 Mustache 语法进行回调,例如

<view>{{ m1.toUpper(str) }}</view>

但是不能作为组件的事件回调,下面的语法是错误的

<button bindinput="m1.doSomething">点击</button>

3. 隔离性

指的是 WXS 和其他 JS 代码是隔离的,体现在两个方面:

  • WXS 不能调用 JS 中的函数
  • WXS 不能调用小程序的 API

4. 性能好

  • 在 IOS 设备上,WXS 比 JS 的性能要快 2~20 倍
  • 但是在安卓设备上,这两者没有什么差异

5. 其他案例

5.1 动态设定 navigationBarTitle

如果我们的某个页面是复用的,例如管理所有的用户,点击某个用户的信息,上方的navigationBarTitleText显示的就是用户名,此时我们就不能写死了,需要在页面的生命周期函数中

Page({
    onReady: function () {
        wx.setNavigationBarTitle({
            title: 'xx用户'
        })
    }
})

举个例子:

<!-- 用户列表的 WXML 页面 -->
<view>
    用户名:张三
    操作:<button bindtap="goToInfo" data-username="张三">详情</button>
  </view>
  <view>
    用户名:李四
    操作:<button bindtap="goToInfo" data-username="李四">详情</button>
  </view>
// 用户列表页面的 .js 文件
Page({
    goToInfo: function (e) {
        // 编程式导航传参
        wx.navigateTo({
            url: '/pages/userinfo/info?username=' + e.target.dataset.username
        })
    }
})
// userinfo.js
Page({
    data: {
        username: '',
	},
    // onLoad 接收导航参数
    onLoad: function (options) {
        this.setData({
            username: options.username
        })
    },
    // onReady 更改页面标题
    onReady: function () {
        wx.setNavigationBarTitle({
            title: this.data.username
        })
    }
})

5.2 如果没有下一页就不再触发触底加载

判断是否还有下一页数据的公式:

页码值 * 每页条数 >= 总条数,如果结果是true,则没有下一页数据了

// page
Page({
    data: {
        pagenum: 1,
        pagesize: 10,
        total: 100
    },
    // onReachBottom 监听页面触底事件
    onReachBottom: function () {
        // 先判断是否有下一页
        if(this.data.pagenum * this.data.pagesize >= this.data.total) {
           	// 如果没有下一页,不加载下一页,并提示用户
            return wx.showToast({
                title: "没有下一页了...",
                icon: "none"
            });
        }
        // 有下一页就加载下一页
        this.setData({
            pagenum: this.data.pagenum + 1
        })
    }
})