速通-微信小程序 3Day

0 阅读16分钟

速通-微信小程序 3Day

速通-微信小程序-CSDN博客

速通-微信小程序 2Day-CSDN博客

紧接前文,搭配有助于快速,巩固/学习!话不多说开始!

经过前面几篇的学习,好简单,最起码对于做过前端Vue 开发,小程序前后端 so so easy!

页面导航🧭

小程序页面导航是实现页面 跳转 的核心能力

分为 声明式导航 WXML 标签实现,无 JS 逻辑编程式导航 JS API 实现,支持逻辑前置处理 两大类;

两类方式均需区分 Tab 页面非 Tab 页面 的导航规则;

  • Tab 页面app.jsontabBar.list中配置的页面 首页、我的... 无法通过 navigateBack 返回;

  • 非 Tab 页面 未在 tabBar 中配置的页面,如商品详情、订单详情... 属于页面栈管理,

    跳转后 保留 原页面可返回,最多保留 10 层页面栈;

以下是完整实战解析:

声明式导航🔉

通过 <navigator> 组件 实现跳转,适合 无前置逻辑 简单跳转,通过 open-type 属性控制跳转类型;

小程序声明式导航的核心场景分为 跳普通页面、跳 tabBar 页面、页面后退

  • 默认-普通页面 open-type="navigate"
  • 底部-tabBar 页面 open-type="switchTab"
  • 页面「后退 / 返回」 open-type="navigateBack" delta="后退层数,默认 1"
  • 重定向普通页面替换当前页面,无返回按钮open-type="redirect"

导航到 tab页面

  • 核心属性:url 必填,tabBar 页面路径
  • open-type="switchTab" 必填,不可省略
  • url 只能填写 tabBar 页面的 基础路径不能携带任何参数 会失效!
  • 目标页面,必须先在小程序根目录的 app.json 中配置在 tabBar.list 数组中;
  • 跳转后会替换页面栈,左上角无「返回」按钮,❌不支持返回到上一级页面;
<navigator url="tabBar 页面路径" open-type="switchTab" >
    跳转到 tabBar页面
</navigator>

导航非 tab页面

  • 核心属性:url 必填,目标页面路径
  • open-type="navigate"(可省略,默认值)
  • 路径规则:支持 绝对路径 从根目录/开始相对路径 可携带 URL 参数 ?k=v&k2=v2
  • 跳转后页面左上角会显示「返回」按钮, ✅支持返回到上一级页面;
<navigator url="普通页面路径">
	跳转到 普通页面
</navigator>

后退导航

  • 核心属性:open-type="navigateBack" 必填delta="后退层级数" 可选,默认值1
  • 关键注意:无需配置url属性(配置也会失效),后退的层级由delta控制;
  • 从当前页面回退到页面栈中已存在的页面,delta=1 表示返回上一级;
<navigator open-type="navigateBack">
	返回上一页(默认delta=1)
</navigator>

在这里插入图片描述 在这里插入图片描述

编程式导航⌨️

编程式导航 是小程序通过 JS API 函数 实现页面跳转的方式;

核心优势是支持前置逻辑处理 如登录验证、表单校验、数据提交

  • 导航到 Tab 页面: wx.switchTab({object:object})
  • 导航非 Tab 页面: wx.navigateTo({object:object})
  • 重定向普通页面: wx.redirectTo({object:object})
  • 后退导航: wx.navigateBack({object:object})

导航函数:大致参数:

属性类型是否必选说明
urlstring需要跳转,页面路径,
Tab路径后不能带参数
非 tabBar 页面的路径,路径后可以带参数
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

后退导航: 大致参数: 小程序中函数回调基本都类似,success\fail\complete

属性类型默认值是否必选说明
deltanumber1返回页面数,delta 大于现有页面数,则返回首页;

home.wxml 首页Tab

<view>
编程式导航:
  <button bindtap="handleGoDetail" style="width: 100%;" >跳转到详情页(普通页面)</button>
  <button bindtap="handleReDetail" style="width: 100%;" >重定向详情页(普通页面)</button>
  <button bindtap="handleGoToMessage" style="width: 100%;" >跳转到“消息”(tabBar页面)</button>
</view>

message.wxml 消息Tab

<view>
编程式导航:
  <button bindtap="handleback" style="width: 100%;" >返回上一页 (Tab页无效) </button>
</view>

detail.wxml 详情普通页面

<view>
编程式导航:
  <button bindtap="handleback" style="width: 100%;" >返回上一页(默认delta=1,重定向无效~)</button>
</view>

导航到 tab页面

wx.switchTab 仅能跳转至 app.jsontabBar.list 中配置的页面:如首页、我的

  • 跳转后 关闭所有非 Tab 页面,页面栈仅保留 Tab 页面,无法通过 navigateBack 返回;

  • 路径不能携带参数,若需传参,需用本地存储 wx.setStorageSync 本地存储 中转;

Page({
  /*** 页面的初始数据 */
  data: {  },
  // 页面JS:从首页 跳转到 商品详情页 非Tab页)
  handleGoDetail(){   },
  // 页面JS:从首页 重定向 到商品详情页 非Tab页)
  handleReDetail(){    },
  // 页面JS:从首页 切换到 Tab消息页面
  handleGoToMessage(){
      // 前置逻辑:验证用户是否登录(实战常用)
      // 未登录则跳转到登录页(非Tab页)
      // 核心:跳转Tab消息页
      wx.switchTab({
        url: '/pages/message/message',
        success: () => { console.log('跳转到“消息Tab” 成功'); },
        fail: (err) => { console.error('跳转失败:', err); },
      })
  }
})

导航非 tab页面

wx.navigateTo 跳转后原页面保留在 页面栈 中,新页面入栈,最多保留 10 层页面栈;

  • 支持 URL 携带参数 适合列表→详情传值,新页面可通过 navigateBack 返回原页面

wx.redirectTo 跳转后 关闭当前页面 并出栈,新页面入栈,无法返回原页面;

Page({
  /*** 页面的初始数据 */
  data: {  },
  // 页面JS:从首页 跳转到 商品详情页 非Tab页)
  handleGoDetail(){
    wx.navigateTo({
      url: '/pages/detail/detail',
      success: () => { console.log('跳转到“详情页面” 成功'); },
      fail: (err) => { console.error('跳转失败:', err); },
    })
  },
  // 页面JS:从首页 重定向 到商品详情页 非Tab页)
  handleReDetail(){
      wx.redirectTo({
        url: '/pages/detail/detail',
        success: () => { console.log('跳转到“详情页面” 成功'); },
        fail: (err) => { console.error('跳转失败:', err); },
      })
  },
  // 页面JS:从首页 切换到 Tab消息页面
  handleGoToMessage(){ }
})

后退导航

wx.navigateBack 通过 delta 参数控制后退层数

默认 delta: 1,若delta超过页面栈总数,仅返回页面栈最底层,通常-首页;

Page({
  /*** 页面的初始数据 */
  data: {  },
  // 页面JS:返回上一个页面;
  handleback(){
    //默认delta=1
    // wx.navigateBack();
    wx.navigateBack({ delta: 1 });
  },
})

在这里插入图片描述

在这里插入图片描述

导航传参📠

⚠️⚠️⚠️注意:Tab 页传参禁止 URL 拼接

url仅能是 Tab 页路径,不能拼接参数,强行拼接会被忽略,必须用本地存储中转;

声明式导航传参

通过 <navigator>url 属性拼接参数 实现,适合无前置逻辑的简单传参;

核心是 URL 查询字符串格式: 路径?键1=值1&键2=值2

<!-- 跳转到详情页,传递 数字 和 字符串 -->
<navigator url="/pages/detail/detail?k=540&k2='参数传递2'" open-type="navigate" >
    跳转到详情页,参数传递
</navigator>

在目标页面的 onLoad 生命周期中,通过 **options参数 ** 获取传递的参数 参数默认是字符串类型

Page({
  /**
   * 页面加载时接收参数
   * @param {Object} options - 导航传递的参数对象
   */
  onLoad(options) {
    console.log('接收的参数:', options); 
    // 输出:{ k: "540", k2: "参数传递2" }
    // 类型转换:数字参数需手动转Number(默认是字符串)
    const k = Number(options.k);
    const k2 = options.k2;
    // 赋值到data 供页面渲染
  }
})
复杂数据类型:

URL 仅支持传递字符串, 复杂数据需先,在 data:{ 中定义数据 }

通过 JSON.stringify() 序列化,接收方再通过JSON.parse()反序列化;

<!-- 先在JS的 data 中定义复杂数据,再拼接序列化后的字符串 -->
<navigator url="/pages/detail/detail?detailstr={{detailstr}}" open-type="navigate">
  跳转到详情页,复杂数据传递
</navigator>

发送方页面 JS

Page({
  data: {
    // 原始复杂数据(对象)
    detailstr: {
      orderId: 'O20260205001',
      goodsList: [{ id: 1001, count: 2 }, { id: 1002, count: 1 }],
    },
    detailInfoStr: '' // 序列化后的字符串
  },
  onLoad() {
    this.setData({
		// 序列化复杂数据为字符串(需转义特殊字符,避免URL解析错误)
      	detailstr: encodeURIComponent(JSON.stringify(this.data.detailstr))
    });
  }
})

接收方页面 JS

Page({
  onLoad(options) {
    // 接受复杂数据类型
    if(options.detailstr != null){
      const details = decodeURIComponent(options.detailstr);
      const detailInfo = details==null?"":JSON.parse(details);
      console.log('接收的复杂数据:', detailInfo);
    }
  }
})

在这里插入图片描述

在这里插入图片描述

编程式导航传参

通过 wx.navigateTo/wx.redirectTo 等 API 实现,支持前置逻辑处理

传参方式与声明式一致,且新增 **eventChannel事件通道 ** 传递复杂数据 无需序列化

<!-- 发起方页面WXML,绑定事件并传递初始参数 -->
<button bindtap="handleGoToDetailParam" data-k1="1">
  查看详情(编程式传参)
</button>
Page({
  // 点击按钮触发编程式导航
  handleGoToDetailParam(e) {
    // 获取点击的ID(从事件对象中获取)
    const k1 = e.currentTarget.dataset.k1;
    
    // 编程式跳转,URL拼接参数,动态拼接参数;
    wx.navigateTo({
      url: `/pages/detail/detail?k1=${k1}`,
      success: () => { console.log('跳转成功'); }
    });
  }
})

与声明式一致,在 onLoadoptions 中获取参数:

Page({
  onLoad(options) {
    const k1 = Number(options.k1);
    console.log('接受传递过来的参数ID:', k1,);
  }
})
eventChannel 事件通道

对于熟悉/了解过 Vue的朋友来说,这个应该不会陌生… Vue 项目工程化

eventChannel 小程序页面间事件通信机制,可直接传递 对象/数组,无需序列化,适合复杂数据场景

// 发起方页面JS
Page({
  handleGoToDetailEvent() {
    wx.navigateTo({
      url: '/pages/detail/detail',
      success: (res) => {
        // 获取事件通道,向目标页发送数据
        res.eventChannel.emit('sendParam', {
          orderId: '123',
          goodsList: [{ id: 1001, count: 2 }]
        });
      }
    });
  }
})
// pages/detail/detail.js 	接收方页面JS
Page({
  onLoad() {
    // 获取事件通道,监听发起方的事件
    const eventChannel = this.getOpenerEventChannel();
    eventChannel.on('sendParam', (data) => {
      console.log('通过eventChannel接收的数据:', data);
    });
  }
})

在这里插入图片描述 在这里插入图片描述

页面事件📌

微信小程序的 页面事件,这类事件是小程序页面级别的核心回调,

写在页面 .js 文件的 Page({}) 配置中(与 data 同级),区别于组件的:点击/绑定事件

  • 主要分为 页面生命周期事件 页面从创建到销毁的核心回调)
  • 页面特殊交互事件 下拉刷新、上拉触底等业务常用)

⏬下拉刷新

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

首先:开启下拉刷新: 全局开启、页面级开启(推荐),仅当前页面生效;

其次:编写刷新逻辑,页面 .js onPullDownRefresh 生命周期函数;

⚠️注意:需要手动,停止下拉刷新 wx.stopPullDownRefresh();

开启下拉刷新

全局开启:在 app.jsonwindow 配置中设置,所有页面默认生效,

{
  "window": {
    "enablePullDownRefresh": false,	// 不建议,全局开启,可以设置 false,在特定页面设置true
    "backgroundTextStyle": "dark", 	// 下拉加载图标的颜色(dark/light)
    "backgroundColor": "#f5f5f5" 	// 下拉时露出的背景色
  }
}

页面级开启:在目标页面的 .json 中配置,仅当前页面生效(优先级高于全局)

{
  "enablePullDownRefresh": true,
  "backgroundTextStyle": "dark"
}

在这里插入图片描述

编写刷新逻辑

在页面的 onPullDownRefresh 生命周期函数中处理刷新逻辑

必须调用 wx.stopPullDownRefresh() 停止刷新动画 否则加载图标会一直显示;

示例DEMO: 在页面的 wxml 中有如下的 UI 结构,点击按钮可以让 count 值自增 +1

在触发页面的下拉刷新事件的时候,要把 count 的值重置为 0;

<view> count 值为: {{count}} </view>
<button bindtap="countAdd">+1</button>
Page({
  /*** 页面的初始数据 */
  data: { count: 0, },
  // +1 按钮的点击事件处理函数
  countAdd(){ this.setData({ count: this.data.count + 1 }); },
  // 监听用户下拉刷新
  onPullDownRefresh(){ 
    console.log('下拉动作');
    this.setData({ count: 0 }); 
    // 数据加载完成后,停止下拉刷新动画
    wx.stopPullDownRefresh();
  }
})

在这里插入图片描述

⏫上拉触底

上拉触底 是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而 加载更多数据 的行为

触发下一页数据加载,常用于分页列表如: 商品列表、订单列表,实现 “无限滚动” 效果

配置触底距离:

在页面 .json 中设置 onReachBottomDistance(默认 50px,即距离底部 50px 时触发):

{
  "onReachBottomDistance": 60
}
编写触底加载逻辑:

在页面的 onReachBottom 生命周期函数中处理分页加载,

需添加加载锁避免重复请求,同时判断是否还有更多数据,最新版小程序,已经有自动节流处理;

  • 前端请求节流,是前端性能优化中针对 高频触发的网络请求 设计的核心技巧;
  • 控制请求的触发频率—— 在指定时间间隔内,无论请求被触发多少次,都只允许执行一次
  • 设置一个 开关False,每次请求时候判断,开关TRUE 则请求忽略,开关False 放行,
  • 并立刻设置 开关True,这样之后的请求,都会被忽略,
  • 等待请求最终回调 complete({ 开关False });

示例Demo: 开发一个无限下拉的,颜色块瀑布🎞️

<!-- 因为是随机的, 如果长度撑不起来页面,没有滚动条就不会触发! -->
<view wx:for="{{colorList}}" wx:key="index"class="num-item"style="background-color:rgba({{item}});">{{item}}</view>
<view wx:for="{{colorList}}" wx:key="index"class="num-item"style="background-color:rgba({{item}});">{{item}}</view>
Page({
  /*** 页面的初始数据 */
  data: { 
    count: 0, 
    colorList:[],
    isloading: false,
  },
  // +1 按钮的点击事件处理函数
  countAdd(){ this.setData({ count: this.data.count + 1 }); },
  // 监听用户下拉刷新
  onPullDownRefresh(){ 
    console.log('下拉动作');
    this.setData({ count: 0 }); 
    // 数据加载完成后,停止下拉刷新动画
    wx.stopPullDownRefresh();
  },
  // 生命周期函数--监听页面加载
  onLoad(options) {
    this.getColors();
  },
  // 获取随机颜色方法
  getColors(){
    wx.showLoading({ title: '数据加载中...' });
    if(this.data.isloading){
      console.log("当前存在未结束请求...");
      return;
    }
    this.setData({ isloading: true });
    // 核心:等待2秒后执行接口请求
    setTimeout(() => {
      wx.request({
        url:'https://applet-base-api-t.itheima.net/api/color',
        method: 'GET',
        success: ({ data: res }) => {
          this.setData({
            // ES6 语法数组拆分 ... 
            colorList: [...this.data.colorList,...res.data]
          })
        },
        complete: ()=>{
          wx.hideLoading();
          this.setData({ isloading: false });
        }
      })
    }, 2000);
  },
  // 页面上拉触底事件的处理函数
  onReachBottom(){
    console.log('上拉动作');
    this.getColors();
  }
})
.num-item {
  border:1rpx solid #efefef;
  border-radius: 8rpx;
  line-height:200rpx;
  margin: 15rpx;
  text-align: center;
  text-shadow: Orpx Orpx 5rpx #fff;
  box-shadow: 1rpx 1rpx 6rpx #aaa;
}

在这里插入图片描述

自定义编译模式

微信开发者工具 自定义编译模式

它是小程序开发调试的核心效率工具,主要用于模拟不同启动场景,

无需重复从首页跳转即可直接进入目标页面,提升调试效率,模拟真实场景;支持 启动参数配置

在这里插入图片描述

生命周期🎞️

什么是生命周期:

生命周期是小程序的「生命周期钩子函数」,

框架会在特定时间点自动调用这些函数,你可以在函数中编写业务逻辑

如:初始化数据、请求接口、清理资源),无需手动触发,是小程序开发的核心基础;

应用生命周期:

应用生命周期: 全局, 定义在 app.js中

小程序从启动到销毁 的全局生命周期,仅在 app.js 中配置,作用于整个小程序

App({
  // 全局数据
  globalData: { },

  // 小程序首次启动(仅执行1次)
  onLaunch(options) { console.log('小程序启动:', options); },

  // 小程序切到前台(每次切回都执行)
  onShow(options) { console.log('小程序切到前台:', options); },

  // 小程序切到后台(每次切走都执行)
  onHide() { console.log('小程序切到后台'); },

  // 错误捕获
  onError(error) { console.error('小程序发生代码错误或 API 调用失败时触发', error); },

  // 页面不存在时触发
  onPageNotFound(res) { console.log('访问的页面不存在时触发:', res); },

  // 自定义全局方法
  getUserInfo() { },
  checkToken() { }
  // ...
});

页面生命周期:

页面生命周期(单页面,定义在页面 .js 中)

页面生命周期是单个页面从 加载到卸载 的生命周期,作用于当前页面,核心函数如下:

Page({
  data: { },

  // 页面加载(仅执行1次)接收导航参数、初始化页面数据
  onLoad(options) { console.log('页面加载,接收参数:', options); },

  // 页面显示(每次切回都执行)刷新页面数据、恢复状
  onShow() { console.log('页面显示'); },

  // 页面初次渲染完成(仅执行1次)操作 DOM、初始化组件
  onReady() { console.log('页面渲染完成'); },

  // 页面隐藏(如跳转到商品详情页)暂停页面任务、保存临时数据
  onHide() { console.log('页面隐藏');  },

  // 页面卸载(如返回上一页并关闭当前页)清理资源、移除监听
  onUnload() { console.log('页面卸载'); },

  // 下拉刷新触发 刷新页面数据
  onPullDownRefresh() { },

  // 上拉触底触发 加载下一页数据
  onReachBottom() { },

  // 自定义方法:请求商品列表
  getGoodsList(callback) { },

  getCartCount() { /** 模拟获取购物车数量 */ }
});

应用生命周期 与 页面生命周期,联动关系

小程序启动流程app.onLaunch → 加载首页 → 首页 onLoad → 首页 onShow → 首页 onReady

切后台流程:当前页面 onHideapp.onHide

切前台流程app.onShow → 当前页面 onShow

页面跳转流程:当前页面 onHide → 目标页面 onLoad → 目标页面 onShow → 目标页面 onReady

页面返回流程:当前页面 onUnload → 上一页 onShow

WXS 脚本📃

什么是 wxs

WXS(WeiXin Script)是小程序专属的 渲染层脚本语言

运行在视图层(与逻辑层 JS 分离),核心作用是在 WXML 中直接处理数据或轻量逻辑,

避免频繁的跨线程通信,提升页面渲染性能,解决「逻辑层 JS」与「视图层 WXML」通信性能问题;

wxs 的应用场景:

数据格式化: 在 WXML 中直接格式化日期、金额、手机号等,无需 JS 预处理

复杂条件判断: 多条件组合判断显示内容,避免 WXML 中嵌套过多 wx:if

列表过滤 / 排序: 渲染列表时直接过滤或排序数据,减少 JS 计算压力


对于仅当前页面使用的简单逻辑,可直接在 WXML 中内联定义 WXS:

  • wxs 代码可以编写在 wxml 文件中的 <wxs> 标签内
  • wxml 文件中的每个 <wxs></wxs> 标签,必须提供 module 属性
  • 用来指定当前 wxs 的模块名称,方便在 wxml 中访问模块中的成员
<view>
调用内联函数:
  <view wx:if="{{filter.isHot(111)}}" >判断数据是否合格展示!</view>
  <view>让字符大小写抓换, {{filter.toUpper('AdsdV')}}</view>
</view>

<wxs module="filter">
  // 内联函数:判断商品是否为热销(销量>100)
  function isHot(sales) {
    return sales > 100;
  }
  function toUpper(str){
    return str.toUpperCase(str);
  }
  // 导出函数,供外部调用
  module.exports = { isHot: isHot,toUpper: toUpper };
</wxs>

外联 wxs 脚本

WXS 支持 内联定义外联引入 ,外联方式适合封装通用工具函数(如格式化工具)

在项目中创建 WXS 工具文件(如 utils/format.wxs),编写通用函数;

// utils/format.wxs
// 格式化日期:时间戳 → YYYY-MM-DD
function formatDate(timestamp) {
  var date = getDate(timestamp || getDate().getTime());
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  // 补零处理
  month = month < 10 ? '0' + month : month;
  day = day < 10 ? '0' + day : day;
  return year + '-' + month + '-' + day;
}

// 导出函数,供外部调用
module.exports = {
  formatDate: formatDate,
};

通过 <wxs> 标签引入外联文件,需指定 src(文件路径)和 module(模块名,用于调用函数):

<view>
调用内联函数:
  <view wx:if="{{filter.isHot(111)}}" >判断数据是否合格展示!</view>
  <view>让字符大小写抓换, {{filter.toUpper('AdsdV')}}</view>
  <!-- 在WXML中调用WXS函数 -->
<view>订单创建时间:{{formatTool.formatDate()}}</view>
</view>
<!-- 引入外联WXS脚本,module命名为"formatTool" -->
<wxs src="/utils/format.wxs" module="formatTool"></wxs>
<wxs module="filter">
  // 内联函数:判断商品是否为热销(销量>100)
  function isHot(sales) {
    return sales > 100;
  }
  function toUpper(str){
    return str.toUpperCase(str);
  }
  // 导出函数,供外部调用
  module.exports = { isHot: isHot,toUpper: toUpper };
</wxs>

在这里插入图片描述

注意事项:wxs 脚本

运行环境限制:

WXS 运行在 渲染层 无法调用小程序 API 如: wx.requestwx.showToast

也不能访问页面的 data,只能通过参数传递数据;不能与逻辑层 JS 直接通信;

语法差异(与 JS 对比:

  • 变量声明仅,支持 var,无 let/const wxs 不支持类似于 ES6 及以上的语法形式
  • 函数声明仅,支持 function 声明,无箭头函数;
  • 异步能力,无异步 API,不支持 Promise/async/await
  • 全局对象,提供 getDate()/parseInt() 等基础 API,无 window/document

在 iOS 设备上,小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍

在 android 设备上,二者的运行效率无差异

相关文档

黑马—小程序简介_哔哩哔哩_bilibili 对应:Day3 天内容!