微信小程序自定义组件

自定义组件

开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。

创建自定义组件

类似页面 , 一个自定义组件 由 json wxml wxss js 4个文件组成

  1. 在根目录下 , 新建 components 文件夹 用来存放组件 , 在components 文件夹下新建Tabs 文件夹, 点击Tabs文件夹 ,右击选择 新建Component ,将会自动生成 json wxml wxss js 4个文件
    注意: 如果不先新建 Tabs 文件, 直接右击创建 Component , 就不会为json wxml wxss js 4个文件生成 Tabs 父文件夹
    在这里插入图片描述
    在这里插入图片描述

声明自定义组件
在要使用组件的页面的json文件中添加

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

使用自定义组件
在要使用组件的页面的json文件中添加

<Tabs></Tabs>

案例:头部导航栏

在组件的 wxml ⽂件中编写组件模板,在 wxss ⽂件中加⼊组件样式

编辑wxml


<!-- 不通过data数据方式 -->
<view class="tabs">
  <view class="tabs_title">
    <view class="title_item active">首页</view>
    <view class="title_item">原创</view>
    <view class="title_item">分类</view>
    <view class="title_item">关于</view>
  </view>
  <view class="tabs_content">内容</view>
</view> 

<!-- 
1. 通过js 循环输出数据  
2. {{item.isActive?'active':''}}  三元运算符 如果是isActive 就加上 class样式 active
3. 通过 item. 的方式来获取 data 里面的数据
-->
<view class="tabs">
  <view class="tabs_title">
    <view 
    wx:for="{{tabs}}"
    wx:key="id"
    class="title_item {{item.isActive?'active':''}}"
    >
  {{item.name}}
  </view>
  </view>
  <view class="tabs_content">内容</view>
</view>

编辑wxss样式

.tabs{}
.tabs_title{
  display: flex;
  padding:10 rpx 0;
}
.title_item{
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.active{
  color: red;
  border-bottom: 5rpx solid currentColor;
}
.tabs_content{}

编辑 js 数据

  data: {
    tabs:[
      {
        id:0,
        name:"首页",
        isActive:true
      },
      {
        id:1,
        name:"原创",
        isActive:false
      },
      {
        id:2,
        name:"分类",
        isActive:false
      },
      {
        id:3,
        name:"关于",
        isActive:false
      }
    ]
  }

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

导航栏绑定点击事件(标题激活选中功能)

在组件wxml 中,添加
bindtap=“hanldeItemTap” 事件绑定和
data-index="{{index}}" 数据传参

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

在组件js的methods中添加事件回调函数

  1. 页面的js中 的事件回调函数, 存放在 data 同层级下
  2. 但是在组件js中 的 事件回调函数 , 存放在 methods 中!!!

过程:

1. 绑定点击事件, 需要在methods 中绑定 
2. 点击事件触发的时候, 获取被点击的索引, 就是事件传参  在wxml中通过    data-index="{{index}}"  方式传参
3. 获取原数组
4. 对数组循环
   1. 给每一个循环项 的 选中属性 改为 false
   2. 给当前的索引的项 添加 激活选中效果
  methods: {
    hanldeItemTap(e){  //绑定点击事件
      //获取索引
      const {index} = e.currentTarget.dataset;
      console.log(index);
      //获取data中的数组,  
      //如果使用页面传输过来的数据 , 那么获取的就不是data中的数据, 而是properties中的页面专递过来的数据
      let {tabs} = this.data;

      //循环数组
      //数组.foreach(v,i)  可以用来遍历数组, 修改了v, 也会导致原数组 被修改
      tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
      console.log(tabs);
      this.setData({
        tabs
      })
    }
  }
父(页面组件)向子(自定义组件)传递数据

前面将导航标题的data数据定义在自定义组件中,这样不能适用于多个页面,
所以需要将导航data数据放在页面js中,

通过属性方式传递数据

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

1.先找到页面的wxml文件,为标签添加属性aaa

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

2.在自定义组件的js文件里的properties属性里进行接收
properties里面的接收的数据可以像在data中一样使用

Component({
  /**
   * 里面存放的是要从父组件接收的数据
   */
  properties: {
    //要接受的数据的名称
    tabs:{
      //type : 要接受的数据的类型
      type:String,
      // value 默认值
      value:""
    }
  },
  data{
  }

3.剪切自定义组件中的data中的数据,拷贝到页面的js的data属性中

  data: {
    tabs:[
      {
        id:0,
        name:"首页",
        isActive:true
      },
      {
        id:1,
        name:"原创",
        isActive:false
      },
      {
        id:2,
        name:"分类",
        isActive:false
      },
      {
        id:3,
        name:"关于",
        isActive:false
      }
    ]
  }
子(自定义组件)向父(页面组件)传递数据

点击 事件触发的时候,
触发父组件(页面)中的自定义事件, 同时传递数据给 父组件

  1. 子向父传递数据, 通过事件的方式传递
    1. 在子组件的标签上加入一个自定义事件

在父组件的xml文件中添加

<!-- 在自定义组件中触发了itemChange 事件, 
相当于触发了binditemChange事件,相当于执行了handleItemChange方法 -->
<Tabs tabs="{{tabs}}" binditemChange= "handleItemChange"></Tabs>

在自定义组件中的js文件的hanldeItemTap点击事件中添加
this.triggerEvent(“itemChange”,{index})
将对数组的操作放在页面js中
注释掉自定义组件的数组操作

1. 绑定点击事件, 需要在methods 中绑定 
2. 点击事件触发的时候, 获取被点击的索引, 就是事件传参  在wxml中通过    data-index="{{index}}"  方式传参
3. 获取原数组
4. 对数组循环
   1. 给每一个循环项 的 选中属性 改为 false
   2. 给当前的索引的项 添加 激活选中效果
5. 点击 事件触发的时候, 
   1. 触发父组件(页面)中的自定义事件, 同时传递数据给 父组件
   2. 通过triggerEvent触发事件,将自定义组件的数据返回给页面组件
      this.triggerEvent("父组件自定义事件的名称",{要传递的参数})
    hanldeItemTap(e){  //绑定点击事件
      //获取索引
      const {index} = e.currentTarget.dataset;
      this.triggerEvent("itemChange",{index})
      //获取data中的数组,  如果使用页面传输过来的数据 , 那么获取的就不是data中的数据, 而是properties中的页面专递过来的数据
      // let {tabs} = this.data;

      //循环数组
      //数组.foreach(v,i)  可以用来遍历数组, 修改了v, 也会导致原数组 被修改
      // tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
      //如果是从页面传递过来的数据,那么data属性中是没有数据的
      //这里setData ,相当于在data中加了tabs数组
      // this.setData({
      //   tabs
      // })
    }
  }

在页面js中编写自定义事件,

  //自定义事件, 用来接收子组件传递的数据的
  handleItemChange(e){ 
    //接收传递过来的参数, 拿到要操作的索引
    const {index} = e.detail;
    //拿到原数组
    let {tabs} = this.data;
    //循环数组, 根据点击的索引修改数组
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    //将修改后的值填充回data
    this.setData({
       tabs
    })
  }

传参的时候,在自定义组件中通过 this.triggerEvent(“itemChange”,{index}) 事件
将index参数, 传递给页面组件的 binditemChange 事件 ,
binditemChange 事件调用页面js中的 handleItemChange 方法,
参数index也随着传递给 handleItemChange 回调函数, 通过打印 e , 可以在 e 里面的detail中找到携带的index参数

效果图:

在这里插入图片描述
当点击原创后 , data中 的 tabs 数组也随着改变
在这里插入图片描述

点击导航实现改变内容 : slot标签

1.在自定义组件标签中添加 slot标签

  1. slot标签 只是一个占位符没有实际意义 , 一个插槽
  2. 当页面组件调用自定义组件的时候, 传递标签过来 , 传递过来的标签会替换掉 slot标签
<view class="tabs">
  <view class="tabs_title">
    <view 
    wx:for="{{tabs}}"
    wx:key="id"
    class="title_item {{item.isActive?'active':''}}"
    bindtap="hanldeItemTap" 
    data-index="{{index}}"  
    >
  {{item.name}}
  </view>
  </view>
  <view class="tabs_content">
    <slot></slot>
  </view>
</view>

2.在页面组件的wxml文件中添加标签
【小程序】block标签的介绍和使用
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
通过wx:if判断 当前是data中哪个是isActive

<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:elif="{{tabs[3].isActive}}">3</block>
</Tabs>

在这里插入图片描述
当点击导航栏的时候 , 下面的内容也会发生改变
在这里插入图片描述

最后附上完整代码:

页面wxml:

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

-->
<!-- 在自定义组件中触发了itemChange 事件, 
相当于触发了binditemChange事件,相当于执行了handleItemChange方法 -->
<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:elif="{{tabs[3].isActive}}">3</block>
</Tabs>

页面js:

// pages/demo11/demo11.js
Page({
  data: {
    tabs:[
      {
        id:0,
        name:"首页",
        isActive:true
      },
      {
        id:1,
        name:"原创",
        isActive:false
      },
      {
        id:2,
        name:"分类",
        isActive:false
      },
      {
        id:3,
        name:"关于",
        isActive:false
      }
    ]
  },
  //自定义事件, 用来接收子组件传递的数据的
  handleItemChange(e){ 
    //接收传递过来的参数, 拿到要操作的索引
    console.log(e);
    const {index} = e.detail;
    //拿到原数组
    let {tabs} = this.data;
    //循环数组, 根据点击的索引修改数组
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    //将修改后的值填充回data
    this.setData({
       tabs
    })
  }
})

自定义组件wxml:

<!-- 不通过data数据方式 -->
<!-- <view class="tabs">
  <view class="tabs_title">
    <view class="title_item active">首页</view>
    <view class="title_item">原创</view>
    <view class="title_item">分类</view>
    <view class="title_item">关于</view>
  </view>
  <view class="tabs_content">内容</view>
</view>  -->
<!-- 
1. 通过js 循环输出数据  
2. {{item.isActive?'active':''}}  三元运算符 如果是isActive 就加上 class样式 active
3. 通过 item. 的方式来获取 data 里面的数据
-->
<view class="tabs">
  <view class="tabs_title">
    <view 
    wx:for="{{tabs}}"
    wx:key="id"
    class="title_item {{item.isActive?'active':''}}"
    bindtap="hanldeItemTap" 
    data-index="{{index}}"  
    >
  {{item.name}}
  </view>
  </view>
  <view class="tabs_content">
    <slot></slot>
  </view>
</view>

自定义组件wxss:

.tabs_title{
  display: flex;
  padding:10 rpx 0;
}
.title_item{
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.active{
  color: red;
  border-bottom: 5rpx solid currentColor;
}

自定义组件js:

// components/Tabs/Tabs.js
Component({
  /**
   * 里面存放的是要从父组件接收的数据
   */
  properties: {
    //要接受的数据的名称
    tabs:{
      //type : 要接受的数据的类型
      type:Array,
      // value 默认值
      value:[]
    }
  },
  data: {

  },

/*
  1. 页面的js中 的事件回调函数, 存放在 data 同层级下
  2. 但是在组件js中 的 事件回调函数 , 存放在 methods 中!!!!!!
*/
  methods: {
    /*
    1. 绑定点击事件, 需要在methods 中绑定 
    2. 点击事件触发的时候, 获取被点击的索引, 就是事件传参  在wxml中通过    data-index="{{index}}"  方式传参
    3. 获取原数组
    4. 对数组循环
       1. 给每一个循环项 的 选中属性 改为 false
       2. 给当前的索引的项 添加 激活选中效果
    5. 点击 事件触发的时候, 
       1. 触发父组件(页面)中的自定义事件, 同时传递数据给 父组件
       2. this.triggerEvent("父组件自定义事件的名称",{要传递的参数})

       */
    hanldeItemTap(e){  //绑定点击事件
      //获取索引
      const {index} = e.currentTarget.dataset;
      this.triggerEvent("itemChange",{index})
      //获取data中的数组,  如果使用页面传输过来的数据 , 那么获取的就不是data中的数据, 而是properties中的页面专递过来的数据
      // let {tabs} = this.data;

      //循环数组
      //数组.foreach(v,i)  可以用来遍历数组, 修改了v, 也会导致原数组 被修改
      // tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
      //如果是从页面传递过来的数据,那么data属性中是没有数据的
      //这里setData ,相当于在data中加了tabs数组
      // this.setData({
      //   tabs
      // })
    }
  }
})

其他属性

properties
组件的对外属性,是属性名到属性设置的映射表,参⻅下⽂
data
组件的内部数据,和 properties ⼀同⽤于组件的模板渲染
observers
组件数据字段监听器,⽤于监听properties和data的变化,参⻅数据监听器
methods
组件的⽅法,包括事件响应函数和任意的⾃定义⽅法,关于
事件响应函数的使⽤,参⻅组件间通信与事件

created
组件⽣命周期函数,在组件实例刚刚被创建时执⾏,注意此
时不能调⽤ setData ,参⻅组件⽣命周期
attached
组件⽣命周期函数,在组件实例进⼊⻚⾯节点树时执⾏,参⻅组件⽣命周期
ready
组件⽣命周期函数,在组件布局完成后执⾏,参⻅组件⽣命周期
moved
组件⽣命周期函数,在组件实例被移动到节点树另⼀个位置时执⾏,参⻅组件⽣命周期
detached
组件⽣命周期函数,在组件实例被从⻚⾯节点树移除时执
⾏,参⻅组件⽣命周期

总结

  1. 右击,新建Component , 创建自定义组件
  2. 在页面json的usingComponents属性中配置自定义组件路径
  3. 在页面wxml中直接使用组件名称标签
  4. 组件的事件回调函数存放在methods下,而不是和data同级
  5. ⽗组件通过属性的⽅式给⼦组件传递参数
  6. ⼦组件通过事件的⽅式向⽗组件传递参数
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信小程序是一种基于微信平台的应用程序,它可以在微信中直接运行,无需下载安装。而自定义组件小程序中的一种重要功能,它允许开发者将一些常用的UI元素封装成组件,以便在不同的页面中复用。 自定义组件具有以下特点: 1. 组件是由wxml、wxss和js文件组成,可以独立定义样式和逻辑。 2. 组件可以接受外部传入的数据,通过属性进行配置。 3. 组件可以触发事件,向外部传递消息。 4. 组件可以包含子组件,形成组件的嵌套结构。 使用自定义组件的步骤如下: 1. 在小程序项目中创建一个新的文件夹,用于存放自定义组件的相关文件。 2. 在该文件夹中创建一个wxml文件,定义组件的结构。 3. 在同一文件夹中创建一个wxss文件,定义组件的样式。 4. 在同一文件夹中创建一个js文件,定义组件的逻辑。 5. 在需要使用该组件的页面中引入组件,并在wxml中使用组件标签。 例如,我们创建一个名为"custom-component"的自定义组件,其文件结构如下: ``` custom-component/ ├── custom-component.wxml ├── custom-component.wxss └── custom-component.js ``` 在custom-component.wxml中定义组件的结构,例如: ```html <view class="custom-component"> <text>{{text}}</text> <button bindtap="handleClick">点击按钮</button> </view> ``` 在custom-component.wxss中定义组件的样式,例如: ```css .custom-component { background-color: #f5f5f5; padding: 10px; } ``` 在custom-component.js中定义组件的逻辑,例如: ```javascript Component({ properties: { text: { type: String, value: '默认文本' } }, methods: { handleClick() { this.triggerEvent('click', { message: '按钮被点击了' }); } } }) ``` 在需要使用该组件的页面中引入组件,并在wxml中使用组件标签,例如: ```html <custom-component text="Hello World" bind:click="handleCustomComponentClick"></custom-component> ``` 以上就是微信小程序自定义组件的简单介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值