微信小程序学习

记录本人在学习过程中觉得需要重复复习的点

目录

一、页面之间的信息传递

1)父传子

2)子传父

3)任意两个页面之间

[1. 全局数据共享(Global Data)](#1. 全局数据共享(Global Data))

2.页面间数据传递

[3.使用 Storage(持久化存储)](#3.使用 Storage(持久化存储))

各种任意两个页面信息传递方式的对比:

[二、 data属性值之间如何互相使用](#二、 data属性值之间如何互相使用)

错误写法:

正确解法:

[一、在 onLoad 或 onShow 中动态赋值](#一、在 onLoad 或 onShow 中动态赋值)

[二、使用 observers 监听 sharedValue 变化(动态更新)​](#二、使用 observers 监听 sharedValue 变化(动态更新))

三、生命周期函数:

1.作用:

2.核心函数及执行顺序

四、路由导航

五、点击图片或某个组件想要实现页面跳转

1)直接绑定点击事件(最基础)

[2)使用 navigator 组件包裹图片(推荐)](#2)使用 navigator 组件包裹图片(推荐))

3)结合前面所学组件信息传递,通过跳转实现数据传递

六、自定义组件的使用

细节1:自定义组件怎么在外部定义格式

细节2:自定义组件的生命周期

1.组件自身生命周期函数

[2. ​所在页面触发的生命周期函数​(需在 pageLifetimes 中定义)](#2. 所在页面触发的生命周期函数(需在 pageLifetimes 中定义))

细节3.实例:

小程序项目代码:

小程序代码

一、页面之间的信息传递

1)父传子

通过 ​**properties** 属性传递

javascript 复制代码
// 父组件.wxml
<child-component myProp="{{parentData}}"></child-component>

// 子组件.js
Component({
  properties: {
    myProp: {
      type: String, // 类型
      value: ''     // 默认值
    }
  },
  observers: {
    'myProp': function(newVal) {
      // 监听属性变化
    }
  }
})

其中observes用来监听传递对象的某个属性值,可以对属性值进行格式化等操作或处理

javascript 复制代码
Component({
  properties: {
    // 接收父组件传递的商品对象
    goods: {
      type: Object,
      value: {}
    },
    // 接收父组件传递的索引
    index: {
      type: Number,
      value: 0
    }
  },
  observers: {
    // 监听商品数据变化(例如价格格式化)
    'goods.price'(price) {
      this.setData({ formattedPrice: `¥${price.toFixed(2)}` });
    }
  },
html 复制代码
<view class="goods-card" bind:tap="onTap">
  <image src="{{goods.image}}" class="goods-image" />
  <view class="goods-info">
    <text class="goods-name">{{goods.name}}</text>
    <text class="goods-price">{{formattedPrice}}</text>
  </view>
</view>

2)子传父

javascript 复制代码
// 子组件.js
this.triggerEvent('myEvent', { data: value }, { bubbles: true /* 是否冒泡 */ });

// 父组件.wxml
<child-component bind:myEvent="onMyEvent"></child-component>

// 父组件.js
Page({
  onMyEvent(e) {
    const value = e.detail.data; // 获取子组件传递的值
  }
})

3)任意两个页面之间

1. 全局数据共享(Global Data)

通过 app.jsglobalData 存储全局状态:

javascript 复制代码
/ app.js
App({
  globalData: {
    sharedData: '初始值'
  }
});

// 组件A.js 设置数据
const app = getApp();
app.globalData.sharedData = '新值';



B组件获取
 data: {
    selectedGoodsInfo: null, // 存储选中的商品信息
    name:null,
  },
 onShow() {
    // 从全局数据中获取选中的商品信息
    const app = getApp();
    if (app.globalData && app.globalData.selectedGoodsInfo) {
      this.setData({
        selectedGoodsInfo: app.globalData.selectedGoodsInfo
      });
      // 清除全局数据,避免影响下次选择
      app.globalData.selectedGoodsInfo = null;
    }
  },

2.页面间数据传递

若组件位于不同页面,可通过路由参数或页面跳转传递:

javascript 复制代码
//页面A传递比较复杂的参数时
// pages/pageA/pageA.js
Page({
  goToPageB() {
    const productId = 123;
    const productName = "手机";
    
    // 跳转并传递参数(参数拼接在 URL 中)
    wx.navigateTo({
      url: `/pages/pageB/pageB?id=${productId}&name=${encodeURIComponent(productName)}`
    });
  }
});




// 页面A跳转时传递参数
wx.navigateTo({
  url: '/pages/pageB?param=123'
});


// 页面B.js 获取参数
Page({

  /**
   * 页面的初始数据
   */
  data: {
    name:null
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    const name=options.name
    this.setData({
      name//或者直接写为name:options.name
    })
  },
)}

3.使用 Storage(持久化存储)

javascript 复制代码
// 组件A.js 存储数据
//wx.setStorageSync('key', 'value');
wx.setStorageSync('sharedData', newBalance);

// 页面B的 JS
Page({
  data: {
    sharedValue: ''
  },

  // 生命周期:页面加载时读取数据
  onLoad() {
    this.loadStorageData();
  },

  // 生命周期:页面显示时重新读取(确保数据最新)
  onShow() {
    this.loadStorageData();
  },

  // 读取 Storage 数据
  loadStorageData() {
    // 同步读取
    try {
      const value = wx.getStorageSync('sharedData');
      if (value) {
        this.setData({ sharedValue: value });
      } else {
        this.setData({ sharedValue: '暂无数据' });
      }
    } catch (error) {
      console.error('读取失败:', error);
    }

各种任意两个组件信息传递方式的对比:

信方式 应用场景 典型示例 适用性
全局数据(Global Data)​ 多个组件需要共享全局状态,且数据更新频率较低。 用户登录状态、全局配置(如主题色)、应用级别设置(如语言)。 简单场景,数据共享范围广,但需注意避免滥用(频繁更新可能导致维护困难)。
事件总线(Event Bus)​ 跨组件实时通知,组件间需要解耦,一对多通信。 消息推送、状态同步(如购物车数量更新)、跨页面组件联动(如A组件操作触发B组件刷新)。 复杂场景,适合组件分散、交互频繁的情况,需注意及时销毁监听避免内存泄漏。
页面间数据传递 通过路由参数或页面跳转传递一次性数据 商品详情页跳转时传递商品ID、表单提交后返回列表页携带状态参数。 简单数据传递,仅限于页面跳转场景,数据量不宜过大(URL长度限制)。
页面实例中转 同一页面内多个独立组件需要共享临时数据,且无需持久化。 页面内的筛选组件和列表组件同步筛选条件、表单组件和预览组件实时交互。 同一页面内组件间简单通信,依赖页面实例,不适合跨页面。
Storage(本地存储)​ 需要持久化存储的数据,且多个组件或页面需读取同一份数据。 用户偏好设置(如夜间模式)、缓存登录凭证、离线数据暂存。 数据需要长期保存,读写频繁时注意性能(同步接口可能阻塞渲染)。
状态管理库(如MobX)​ 复杂应用需要集中式状态管理,支持响应式更新,跨组件/页面高效同步数据。 大型电商应用(购物车、订单状态)、实时协作类应用(如多人编辑文档)。 超复杂场景,需引入第三方库,适合中大型项目,对代码结构有较高要求。

二、 data属性值之间如何互相使用

错误写法:

javascript 复制代码
data: {
    sharedValue: '',
    xinxi:[
      {
        title:"this.sharedValue",
        subTitle:"我的余额",
      }]
}

在微信小程序中,data 内的字段在初始化时无法直接互相引用

正确解法:

有以下几种方案来解决:

一、onLoadonShow 中动态赋值

javascript 复制代码
Page({
  // ...其他代码...

  onShow(){
    // 从 data 中获取 sharedValue,设置到 xinxi[0].title
    this.setData({
      'xinxi[0].title': this.data.sharedValue
    });
  }
});

二、使用 observers 监听 sharedValue 变化(动态更新)​

javascript 复制代码
Page({
  data: {
    sharedValue: '默认值',
    xinxi: [
      {
        subTitle: '我的余额',
        title: '' // 初始为空,后续通过 observer 更新
      }
    ]
  },

  // 监听 sharedValue 变化
  observers: {
    'sharedValue': function(newValue) {
      this.setData({
        'xinxi[0].title': newValue // 将新值赋给 title
      });
    }
  },

  // 示例:修改 sharedValue(如按钮点击事件)
  updateValue() {
    this.setData({
      sharedValue: '新值'
    });
  }
});

三、生命周期函数:

1.作用:

生命周期函数用于在 ​特定时机自动执行代码,例如:

  • 页面加载时初始化数据
  • 页面显示时刷新内容
  • 页面隐藏时释放资源
  • 应用启动时获取用户信息

2.核心函数及执行顺序

函数名 触发时机 执行次数 典型场景 注意事项
onLoad 页面 ​首次加载​(创建)时触发 一次 接收页面参数、初始化数据 无法操作 DOM(视图未渲染)
onShow 页面 ​显示时 触发 多次 刷新数据、更新用户状态 可能频繁触发(如返回页面)
onReady 页面 ​初次渲染完成 时触发 一次 操作 DOM、初始化地图/图表等组件 确保视图已存在
onHide 页面 ​隐藏时 触发(跳转/切后台) 多次 暂停计时器、保存临时状态 不可见但未被销毁
onUnload 页面 ​销毁时 触发(关闭或跳转) 一次 释放资源(如 WebSocket 连接) 页面实例将被回收

首次进入页面 → onLoad → onShow → onReady

离开页面(跳转/切后台) → onHide

重新进入页面 → onShow

关闭页面 → onUnload

类型 函数名 触发时机 执行次数 核心用途
页面 onLoad 页面首次加载时 一次 初始化数据、获取参数
onShow 页面显示时 多次 刷新动态数据
onReady 页面初次渲染完成时 一次 操作 DOM、初始化组件
onHide 页面隐藏时 多次 暂停操作、保存临时状态
onUnload 页面销毁时 一次 释放资源
应用 onLaunch 小程序初始化完成时 一次 全局配置、检查更新
onShow 小程序启动或从后台返回时 多次 恢复应用状态
onHide 小程序切到后台时 多次 保存全局状态

四、路由导航

目标页面类型 正确 API 说明
普通页面 wx.navigateTo 保留当前页面,新页面压入页面栈
普通页面(不可返回) wx.redirectTo 关闭当前页面,打开新页面
导航栏(tabBar)页面 wx.switchTab 切换到 tabBar 页面
所有页面关闭后跳转 wx.reLaunch 关闭所有页面,打开新页面
API 说明
wx.navigateTo 保留当前页面,跳转到新页面(可返回)
wx.redirectTo 关闭当前页面,跳转到新页面(不可返回)
wx.switchTab 跳转到 tabBar 页面(需在 app.json 的 tabBar 中定义)
wx.reLaunch 关闭所有页面,打开新页面
wx.navigateBack 返回上一页或多层页面(通过 delta 参数控制)

关于navigateBack的使用:

javascript 复制代码
// /pages/payment/payment.js
Page({
  onPaymentSuccess() {
    // 支付成功后返回原页面
    wx.navigateBack({ delta: 1 }); // 返回上一页
  }
});

五、点击图片或某个组件想要实现页面跳转

1)直接绑定点击事件(最基础)

html 复制代码
<image 
  src="/images/button.png" 
  mode="widthFix" 
  bindtap="navigateToPage" 
  data-url="/pages/detail/detail?id=123" 
/>
javascript 复制代码
Page({
  navigateToPage(e) {
    const url = e.currentTarget.dataset.url; // 获取 data-url 参数
    wx.navigateTo({
      url: url
    });
  }
});
html 复制代码
<navigator url="/pages/detail/detail?id=123">
  <image src="/images/button.png" mode="widthFix" />
</navigator>

3)结合前面所学组件信息传递,通过跳转实现数据传递

通过点击事件传递动态参数(如商品 ID、用户信息)。

html 复制代码
<image 
  src="/images/product.png" 
  bindtap="goToDetail" 
  data-product-id="456" 
  data-type="promotion"
/>
javascript 复制代码
Page({
  goToDetail(e) {
    const productId = e.currentTarget.dataset.productId;
    const type = e.currentTarget.dataset.type;
    wx.navigateTo({
      url: `/pages/detail/detail?id=${productId}&type=${type}`
    });
  }
});

目标页面获取参数:

javascript 复制代码
// /pages/detail/detail.js
Page({
  onLoad(options) {
    console.log(options.id);    // 456
    console.log(options.type);  // promotion
  }
});

六、自定义组件的使用

细节1:自定义组件怎么在外部定义格式

使用 externalClasses 外部样式类

组件内部:

javascript 复制代码
// 自定义组件 component.js
Component({
  externalClasses: ['container-class', 'title-class'], // 声明允许外部传入的类名
});
html 复制代码
<!-- 组件 WXML -->
<view class="container-class">
  <text class="title-class">标题</text>
  <slot></slot>
</view>

使用该组件的外部:

(注意:如果组件内部定义了样式,想要覆盖不要忘了加 !important)

html 复制代码
<!-- 页面 WXML -->
<custom-component
  container-class="custom-container" 
  title-class="custom-title"
/>
css 复制代码
/* 页面 WXSS */
.custom-container {
  padding: 20rpx;
  background: #f5f5f5;
}

.custom-title {
  color: #007bff;
  font-size: 32rpx;
}

细节2:自定义组件的生命周期

组件的生命周期函数分为两类:​组件自身生命周期 和 ​所在页面触发的生命周期。以下是核心函数:

1.组件自身生命周期函数
生命周期函数 触发时机 执行次数 典型场景
created 组件实例 ​刚创建 时触发 一次 初始化非响应式数据(非 data 字段)
attached 组件 ​被添加到页面节点树 时触发 一次 访问父组件数据、初始化与页面相关的逻辑
ready 组件 ​视图层布局完成 后触发 一次 操作 DOM、初始化第三方库(如地图)
moved 组件 ​被移动到节点树其他位置 多次 极少数场景(如动态调整节点顺序)
detached 组件 ​被从页面节点树移除 时触发 一次 清理定时器、取消事件监听
2. ​所在页面触发的生命周期函数 ​(需在 pageLifetimes 中定义)
生命周期函数 触发时机 典型场景
show 组件所在页面 ​显示时 触发 刷新数据、恢复动画
hide 组件所在页面 ​隐藏时 触发 暂停动画、保存临时状态
resize 组件所在页面 ​尺寸变化时 触发 调整布局(如屏幕旋转)

书写方法:

javascript 复制代码
// components/my-component/my-component.js
Component({
  // 组件自身生命周期
  lifetimes: {
    created() {
      console.log('组件实例刚创建,此时还不能调用 setData');
      this.internalData = '非响应式数据'; // 适合初始化非 data 字段
    },
    attached() {
      console.log('组件被添加到页面节点树');
      const parentData = this.getPageData(); // 获取父页面数据示例
      this.setData({ parentData });
    },
    ready() {
      console.log('组件视图层渲染完成');
      this.initMap(); // 初始化地图组件
    },
    detached() {
      console.log('组件被移除');
      clearInterval(this.timer); // 清理定时器
    }
  },

  // 页面触发的生命周期
  pageLifetimes: {
    show() {
      console.log('页面显示,组件恢复');
      this.resumeAnimation(); // 恢复动画
    },
    hide() {
      console.log('页面隐藏,组件暂停');
      this.pauseAnimation(); // 暂停动画
    },
    resize(size) {
      console.log('页面尺寸变化', size);
      this.adjustLayout(); // 调整布局
    }
  },

  methods: {
    // 自定义方法
    getPageData() {
      const pages = getCurrentPages();
      return pages[pages.length - 1].data;
    },
    initMap() {
      this.mapCtx = wx.createMapContext('map', this);
    }
  }
});

细节3.实例:

接下来以我封装的组件为例进行细节拆分

wxml

html 复制代码
<!--components/goods.wxml-->
<view style="width: 95%;margin: 25rpx auto;background-color: white; border-radius: 5px;box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);height: 220rpx;position: relative;"  class="custom-class"  wx:for="{{goods}}" wx:key="index" use-slot>
  <slot name="{{'good'+index}}"></slot>
  <van-button round type="info" style="position: absolute;right: 20rpx;bottom: 20rpx;" wx:if="{{isShow}}" bind:tap="onSelectItem" data-index="{{index}}">{{btncont}}</van-button>
</view>

js

javascript 复制代码
Component({
  externalClasses: ['custom-class', 'title-class', 'content-class'],
  options:{
    //设置当前自定义组件使用多插槽模式,默认为false
    multipleSlots:true
  },
  /**
   * 组件的属性列表
   */
  properties: {
    goodsNum:{
      type:Number,
      value:4
    },
    isShow:{
      type:Boolean,
      value:true
    },
    btncont:{
      type:String,
      value:"去评价"
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    goods:[]
  },
  lifetimes:{
    attached(){
        //代表该组件被初始化并且加载,此时完成数组的数据添加操作
        let items = [];
        for(let i = 0; i < this.properties.goodsNum; i++){
             items.push(i);
        }
        //setData微信小程序用来修改data数据的方法,该方法会将给定的对象和data原来的数据进行对象合并,合并之后强制页面进行动态刷新
        this.setData({
           goods: items
        });
    }
 },

  /**
   * 组件的方法列表
   */
  methods: {
    // 处理选择按钮点击
    onSelectItem(e) {
      const index = e.currentTarget.dataset.index;
      // 触发自定义事件,将选中的index传递给父页面
      this.triggerEvent('selectItem', { index });
    }
  }
})

data和properties区别

特性 ​**data** ​**properties**
定义位置 组件内部的 data 字段 组件内部的 properties 字段
用途 存储组件 ​内部状态 接收 ​父组件传递的只读参数
初始化时机 组件创建时初始化 父组件传递数据时初始化(未传则用默认值)
数据来源 组件内部定义 父组件通过属性传入
可修改性 组件内部可通过 setData 修改 不可直接修改(需父组件更新)
类型校验 支持类型校验(type 字段)
默认值设置 直接在 data 中赋值 通过 value 字段设置默认值

通过传入的goodsNum,结合wx:for的使用即实现了创建不同多个商品数量。

那么在外部当中怎么像插槽当中传入数据呢?

外部的使用

html 复制代码
<Good goodsNum="{{2}}"  btncont="去拼团"  custom-class="my-custom-style" bind:selectItem="steptopintuan">
  <view wx:for="{{goods}}"  wx:key="index" slot="{{'good'+index}}">
  <image src="{{item.imgUrl}}" mode="widthFix" style="width: 100%;"/>
  <view style="text-align: center;font-size: large;font-weight: 550;">{{item.title}}</view>
  <view style="text-align: center;margin-top: 10px;color: #ccc;">{{item.subtitle}}</view>
  <view style="text-align: center;margin-top: 10px;"> {{item.time}}</view>
  <view style="text-align: left;margin-top: 10px; display: flex;">
  <view style="color: red;padding-left: 25px;"> {{item.price}}  </view>
  <view style="color: #ccc;padding-left:25px;text-decoration: line-through"> {{item.oldprice}}  </view>
  <view style="color: #ccc; margin-left: 30px;">已团{{item.sales}}件</view>
  </view>
  </view>
</Good>

通过slot="{{}}"实现对应的绑定即可。

后续想到再补充......

相关推荐
FAREWELL000752 小时前
C#核心学习(一)面向过程与面向对象编程---初识类和对象
学习·c#·面向对象
暮雨哀尘3 小时前
微信小程序开发:微信小程序组件应用研究
算法·微信·微信小程序·小程序·notepad++·微信公众平台·组件
sealaugh323 小时前
aws(学习笔记第三十六课) apigw-http-api-lambda-dynamodb
笔记·学习·aws
*TQK*3 小时前
CSS学习笔记5——渐变属性+盒子模型阶段案例
css·笔记·学习
Logintern094 小时前
分享一个Pyside6实现web数据展示界面的效果图
python·学习·web·数据·pyside6
知识分享小能手4 小时前
CSS3学习教程,从入门到精通,CSS3 媒体查询实现响应式布局语法指南(21)
前端·css·学习·css3·html5·媒体
狂团商城小师妹4 小时前
经销商订货管理系统小程序PHP+uniapp
微信·微信小程序·小程序·uni-app·php·微信公众平台
viperrrrrrrrrr74 小时前
大数据学习(92)-spark详解
大数据·学习·spark
2402_881319305 小时前
3.28学习总结
数据结构·学习·算法
云上艺旅5 小时前
K8S学习之基础五十一:k8s部署jenkins
学习·云原生·容器·kubernetes·jenkins