微信小程序基本用法3(四)

本文详细介绍了微信小程序的自定义组件创建、声明、使用及其优化,包括标题激活选中、数据传递等。同时,讲解了小程序的生命周期,包括应用生命周期和页面生命周期,并通过图表进行图解。此外,还探讨了自定义组件的slot和定义段与实例方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、自定义组件

类似 vue 或者 react 中的自定义组件, 小程序允许我们使用自定义组件的方式来构建页面

一.1 创建自定义组件

创建 :

类似于页面,一个自定义组件由 json wxml wxss js 4个文件组成
1.在 app.json 中新建页面
2.在 和 pages 同级目录下 创建 components 文件夹
3.在 commponents 里面 创建 Tabs 文件夹
4.创建 Tabs 文件解构,点击 文件夹 Tabs,然后右键,点击新建 Commponent,会弹出一个输入框,输入 Tabs 点击回车,就会自动生成 Tabs.js、Tabs.json、Tabs.wxml、Tabs.wxss 文件

在 Tabs.json 中的代码 :

{
  "component": true,     // 表示当前的组件是一个组件
  "usingComponents": {}     // 在里面可以继续引入其它的组件
}

在 Tabs.js 中的代码

// components/Tabs/Tabs.js
// 组件是 Component,而不是 pages 了
Component({
  /**
   * 组件的属性列表
   */
  // 接收父向子传递的数据
  properties: {

  },

  /**
   * 组件的初始数据
   */
  // 自己的数据
  data: {
    
  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

一.2 声明引入自定义组件

声明 :

打开我们新建的页面,点击 xxx.json,会看到里面有一段代码,我们想要声明组件,就需要在这里面配置 标签名字 和 组件相对路径,注意最后文件的后缀名可以不用添加

{
  "usingComponents": {
    "Tabs":"../../commponents/Tabs/Tabs"
  }
}

一.3 页面使用自定义组件

打开新建页面的 xxx.wxml, 直接把刚才在 xxx,json 中配置过的 标签名字,当做标签写上,就可以在小程序中看到引入的 Tabs 组件

<!--pages/work14/work14.wxml-->
<Tabs></Tabs>

在这里插入图片描述

一.4 编辑组件, tabs 样式优化

在 tabs.wxml 中编辑 :

<!--commponents/Tabs/Tabs.wxml
<Tabs></Tabs> -->

<view class="tabs">
  <view class="tabs_title">
    <!-- 不能用写死的数据,应该在 组件 tabs.js 的 data 中存数据,然后遍历数据到 页面的wxml 文件上 -->
    <!-- <view class="title_item active">首页</view>
    <view class="title_item">原创</view>
    <view class="title_item">分类</view>
    <view class="title_item">关于</view> -->

    <view
      wx:for="{{tabs}}"
      wx:key="id"
      class="title_item {{item.isActive?'active':''}}"
    >
      {{item.name}}
    </view>
  </view>
  <view class="tabs_content">内容</view>
</view>

<Tabs></Tabs>

在 tabs.wxss 中编辑 :

/* commponents/Tabs/Tabs.wxss */
.tabs {}

.tabs_title {
  display: flex;
  padding: 10rpx 0;
}

.title_item {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

.active {
  color: red;
  border-bottom: 5rpx solid currentColor;
}

.tabs_content{}

在 tabs.js 中编辑 :

// components/Tabs/Tabs.js
// 组件是 Component,而不是 pages 了
Component({
  /**
   * 组件的属性列表
   */
  // 接收父向子传递的数据
  properties: {

  },

  /**
   * 组件的初始数据
   */
  // 自己的数据
  data: {
    tabs:[
      {
        id:0,
        name:"首页",
        isActive:true
      },
      {
        id:1,
        name:"原创",
        isActive:false
      },
      {
        id:2,
        name:"分类",
        isActive:false
      },
      {
        id:3,
        name:"关于",
        isActive:false
      }
    ]
  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

成功图示,现在是个死的样式,不能点击 :
在这里插入图片描述

一.5 标题激活选中

在 tab.wxml 标签中添加方法和下标索引

<view
      wx:for="{{tabs}}"
      wx:key="id"
      class="title_item {{item.isActive?'active':''}}"
      bindtap="handleItemTap"
      data-index="{{index}}"
    >

在 tabs.js 中 data 同级下的 methods 里面定义

/**
   * 组件的方法列表
   一. 页面.js 文件中 存放事件回调函数的时候,存放在 data 同层级下!!!
   二. 组件.js 文件中 存放事件回调函数的时候,必须要存在 methods中!!!

   */
  methods: {
    handleItemTap(e){
       /*
      一. 绑定点击事件 需要在 methods 中绑定
      二. 获取被点击的索引
      三. 获取原数组
      四. 对数组循环
        1. 给每一个循环性 选中属性 改为 false
        2. 给 当前的索引的 项 添加激活选中效果就可以了!!!
    */

    // 2 获取索引
    // console.log(e)
    const {index} = e.currentTarget.dataset;

    // 3 获取 data 中的数组
    // 解构 对复杂类型进行解构的时候,复制了一份 变量的引用而已
    // 最严谨的做法,重新拷贝一份数组,在对这个数组的备份进行处理
    // let tabs = JSON.parse(JSON.stringify(this.data.tabs))
    // 不要直接修改 this.data.数据
    let {tabs} = this.data;
    
    // 4.循环数组
    // [].forEach 遍历数组 遍历数组的时候 修改了 v ,也会导致原数组被修改
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);

    this.setData({
      tabs
    })
    }
  }

保存,看效果,可以随便点击

图1
图2

一.6 父向子传递数据

将 Tabs.js 中 data 里面的数据剪贴,复制到 页面.js 中的 data 数据里面

在 Tabs.js 文件的 properties 中接收约束

properties: {
    // 要接受的数据名称
    // type 要接受的数据的类型
    // value 默认值

    tabs:{
      type:Array,
      value:[]
    }
  },

在 页面.wxml 中 使用,最后保存的效果和之前一样

<!--. 父组件(页面) 向子组件 传递数据 通过 标签属性的方式来传递
    1. 在子组件上进行接收
    2. 把这个数据当成是 data 中的数据直接用即可
 -->

<Tabs tabs="{{tabs}}"></Tabs>

流程图 :

在这里插入图片描述

一.7 子向父传递数据

我们用上面的写法运行,打开 调试器的 AppData,我们本身给 首页的 isActive 设置的是 true,当后来点了别处之后,虽然底部颜色消失了,但是 可以清除的看到 AppData 里面的 isActive 还是 true,为了解决这个问题,我们就用到了 子传父

在 Tabs.js 的 methods 中定义的方法里面编译

<!--. 点击事件触发的时候
        触发父组件中的自定义事件 同时传递数据给 父组件
        this.triggerEvent("父组件自定义事件的名称",要传递的参数 )
-->

//  触发父组件中的自定义事件 同时传递数据给 父组件
    this.triggerEvent("itemChange",{index});

在页面.wxml 标签中自定义方法名

<Tabs tabs="{{tabs}}" binditemChange="handleItemChange"></Tabs>

在 页面.js data 同级下 新添方法,编写

// 自定义事件 用来接收子组件传递的数据的
  handleItemChange(e){
    // console.log(e)
    // 接收传递过来的参数
    const {index} = e.detail;
    // console.log(index)
    let {tabs} = this.data;
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    this.setData({
      tabs
    })
  }

点击保存,看调试器的 AppData,可以看到当我们点击变化时 isActive 的中值发生变化
在这里插入图片描述

一.8 自定义组件 slot

在 Tabs.wxml 中修改 view 标签 内容这一块

<view class="tabs_content">
    <!-- 
      slot 标签 其实就是一个占位符 插槽
      等到 父组件调用 子组件的时候 再传递 标签过来,最终这些被传递的标签
    就会替换 slot 插槽的位置    
    -->
    <slot></slot>
</view>

在 页面.wxml Tabs 组件中添加 block 占位符

<Tabs tabs="{{tabs}}" binditemChange="handleItemChange">
  <block wx:if="{{tabs[0].isActive}}">0</block>
  <block wx:elif="{{tabs[1].isActive}}">1</block>
  <block wx:elif="{{tabs[2].isActive}}">2</block>
  <block wx:else>3</block>
</Tabs>

点击保存,查看小程序,发现点那个就显示里面的内容
在这里插入图片描述

一.9 定义段与实例方法

        Component 构造器可用于定义组件,调用Component 构造器时可以指定组件的属性、数据、方法 等。

定义段类型是否必填描述
propertiesObject Map组件的对外属性,是属性名到属性设置的映射表,j参见下文
dataObject组件的内部数据,和 properties 一同用于组件的模板渲染
observersObject组件数据字段监听器,用于监听 properties 和 data 的变化
methodsObject组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用
createdFunction组件生命周期函数,在组件实例刚刚被创建时执行,注意此时不能调用 setData
attachedFunction组件生命周期函数,在组件实例进入页面节点树时执行
readyFunction组件生命周期函数,在组件布局完成后执行
movedFunction组件生命周期函数,在组件实例被移动到节点树另一个位置时执行
detachedFunction组件生命周期函数,在组件实例被从页面节点树移出时执行

二、小程序生命周期

分为应⽤生命周期和页面生命周期
关于小程序前后台的定义和小程序的运行机制,请参考运行机制章节

二.1 应用生命周期

表格 :

属性类型默认值必填说明
onLaunchfunction监听小程序初始化
onShowfunction监听小程序启动或切前台
onHidefunction监听小程序切后台
onErrorfunction错误监听函数
onPageNotFoundfunction页面不存在监听函数

测试及注意点 :

        在 app.js 中编译

// app.js
App({
  // 一. 应用第一次启动的就会触发的事件
  onLaunch(){
    // 在应用第一启动的时候,获取用户的个人信息
    console.log("onLaunch")

    // 这里的 aabbcc 是为了测试 onError 报错 和 事件源的,如果没有报错信息,就不能打印 onError,所以在这里让小程序故意报错
    // aabbcc

    // 这里的代码是写一个假的地址,然后测试 onPageNotFound 找不到页面的,不然不会报错,查看不方便
    // js 的方式来跳转 不能触发 onPageNotFound
    // wx.navigateTo({
    //   url:'/11/22/33'
    // })
  },

  // 二. 应用 被用户看到
  onShow(){
    // 对应用的数据或者页面效果 重置
    console.log("onShow")
  },

  // 三. 应用 被隐藏了
  onHide(){
    // 暂停或清除定时器
    console.log("onHide")
  },

  // 四. 应用的代码发生了报错的时候,就会触发
  onError(err){
    // 在应用发生代码错误的时候,收集用户的错误信息,通过异步请求,将错误的信息发送后台去
    console.log("onError")
    console.log(err)
  },

  // 五. 页面找不到就会触发
    // 应用第一次启动的时候,如果找不到第一个入口页面,才会触发
    onPageNotFound(){
      // 如果页面不存在了,通过 js 的方式来重新跳转页面,重新跳到第二个页面 
        // 不能跳到 tabbar 页面,导航组件类似
        //  找到微信开发者工具上方正中间的位置,会看到 "普通编译",点击找到 "添加编译模式",模式名称自定义,
            // 启动页面写一个不存在的,为了测试,然后确定,就可以测试下面这个找不到跳转到指定页面了
      wx.navigateTo({
        url:'/pages/work8/work8'
      })
      console.log("onPageNotFound")
    }
})

二.2 页面生命周期

表格 :

属性类型说明
dataobject页面的初始数据
onLoadfunction生命周期回调—监听页面加载
onShowfunction生命周期回调—监听页面显示
onReadyfunction生命周期回调—监听页面初次渲染完成
onHidefunction生命周期回调—监听页面隐藏
onUnloadfunction生命周期回调—监听页面卸载
onPullDownRefreshfunction监听用户下拉动作
onReachBottomfunction页面上拉触底事件的处理函数
onShareAppMessagefunction用户点击右上角转发
onPageScrollfunction页面滚动触发事件的处理函数
onResizefunction页面尺寸改变时触发
onTabItemTapfunction当前是 tab 页时,点击 tab 时触发

测试及注意点 :

app.json 中添加一个 tabbar,后面测试点击 tabbar 的

{
      "pagePath": "pages/work15/work15",
      "text": "我的",
      "iconPath": "icon/_search.png",
      "selectedIconPath": "icon/search.png"
}

页面.js

// pages/work15/work15.js
Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // console.log("onLoad")
    // onLoad 发送异步请求来初始化页面数据
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    // console.log("onShow")
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    // console.log("onReady")
  },


  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
    // console.log("onHide")
  },

  /**
   * 生命周期函数--监听页面卸载  也是可以通过点击超链接来演示 
   */
  onUnload: function () {
    // console.log("onUnload")
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   * 我们之前写过这个下拉刷新的配置,所以这里直接输出
   */
  onPullDownRefresh: function () {
    // console.log("onPullDownRefresh")
    // 页面的数据 或者效果 重新 刷新
  },

  /**
   * 页面上拉触底事件的处理函数
   * 需要让页面 出现上下滚动才行
   */
  onReachBottom: function () {
    // console.log("onReachBottom")
    // 上拉加载下一页数据
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    // console.log("onShareAppMessage")
    // 点击小程序的右上角 "···" 转发,就会在调试台触发
  },

// 后面这三个生命周期函数是我们自己手动添加的 

// 页面滚动就会触发
  onPageScroll:function(){
    // console.log("onPageScroll")
  },

  // 页面的尺寸发生改变的时候,触发
    // 小程序 发生了 横屏竖屏 切换的时候就会触发
    // 在 页面.json 中添加配置  { "pageOrientation":"auto" }
    // 点击小程序页面上边有一个 "旋转按钮",点击就可以在调试台看到输出了
    // 但是我的在开发工具里面不能输出,在手机上预览就可以实现了
  onResize:function(){
    // console.log("onResize")
  },

  // 1. 点击 tabbar 就会触发,必须是当前页面
  // 2. 点击的是自己的 tab item 才会出发
  onTabItemTap:function(){
    // console.log("onTabItemTap")
  }
})

页面.wxml

<!--pages/work15/work15.wxml-->

<!-- 为了测试 onHide 才写的这个,当我们点击跳转时, "onHide" 在调试台就显示出来了 -->
<navigator url="/pages/work14/work14" open-type="navigate">
  work14
</navigator>

<!-- 为了测试 onUnload 才写的这个,当我们点击跳转时, "onUnload" 在调试台就显示出来了 关闭当前页面也就意味着卸载了页面-->
<navigator url="/pages/work14/work14" open-type="redirect">
  work14 redirect
</navigator>

<!-- 这里为了测试屏幕上拉,通过标签来顶出来  可以使用快捷方式 view{$}*25 会直接输出 25 个标签 -->
<view>1</view>
<view>2</view>
<view>3</view>
<view>4</view>
<view>5</view>
<view>6</view>
<view>7</view>
<view>8</view>
<view>9</view>
<view>10</view>
<view>11</view>
<view>12</view>
<view>13</view>
<view>14</view>
<view>15</view>
<view>16</view>
<view>17</view>
<view>18</view>
<view>19</view>
<view>20</view>
<view>21</view>
<view>22</view>
<view>23</view>
<view>24</view>
<view>25</view>

二.3 页面生命周期图解

在这里插入图片描述

三、补充

        生命周期就是一些事件,只不过它触发的时机不是我们来定义的,而是应用或者程序自己来定义的

四、总结

        如果你能看到这里,那么屏幕前的你毅力也是很强大.小程序的基本使用我们就结束了.在这四天中,每天都有不一样的收获和体验.也希望我的博客内容对你们有所帮助,也是对我最大的支持了!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值