微信小程序自定义组件整理总结(案例说明,页面通过标签属性给子组件传参,子组件通过properties接收,子组件通过触发事件向页面传参,slot插槽)

前言:组件是放在components文件夹内,页面是放在pages文件夹内,
页面.js 文件中 存放事件回调函数的时候 存放在data同层级下!!!
组件.js 文件中 存放事件回调函数的时候 必须要存在在 methods中!!!
不要搞混

在这里插入图片描述
通过一个实例进行讲解

先介绍自定义组件,稍后会涉及父子组件传参

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

组件使用

首先在components文件夹内新建一个文件,例如Tab,用来抽取公共头部,Tab可以像view标签一样被页面使用,即 <Tabs></Tabs>
要求:
子组件:wxml写需要在父组件中展示的内容
页面:在json中先引入子组件,再用标签呈现子组件

具体操作如下:

首先在Tab.wxml写点内容

<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>

Tab.js文件,先模拟子组件自己模拟数据并操作

Component({
  data: {
    tabs: [
      {
        id: 0,
        name: "首页",
        isActive: true
      },
      {
        id: 1,
        name: "原创",
        isActive: false
      }
      ,
      {
        id: 2,
        name: "分类",
        isActive: false
      }
      ,
      {
        id: 3,
        name: "关于",
        isActive: false
      }
    ]
  },
  methods: {
    hanldeItemTap(e) {
      /* 
      1 绑定点击事件  需要在methods中绑定
      2 获取被点击的索引 
      3 获取原数组 
      4 对数组循环
        1 给每一个循环性 选中属性 改为 false
        2 给当前的索引的 项 添加激活选中效果就可以
      */
      //  2 获取索引,解构赋值
      const { index } = e.currentTarget.dataset;
      // 3 获取data中的数组
      // 最严谨的做法:重新拷贝一份数组,再对这个数组的备份进行处理,
      let tabs=JSON.parse(JSON.stringify(this.data.tabs));
      // 4 循环数组
      // [].forEach 遍历数组 遍历数组的时候 修改了 v ,也会导致源数组被修改
      tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false);
      this.setData({
        tabs
      })
    }
  }
})

页面使用Tabs自定义组件就很简单
需要在该页面文件夹下的json文件补充以下,记录组件

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

wxml

<Tabs></Tabs>

wcss

.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;
}

在这里插入图片描述

看起来是不是很简单呢

在这里插入图片描述
但是,传参呢?
在这里插入图片描述

组件传参

现在我们开始做组件传参了!

具体如下:
页面通过标签属性给子组件传参,子组件通过properties接收,子组件通过触发事件向页面传参

页面(父)

  1. 向子组件传递数据:在子组件的标签(此标签在父组件内),例如tabs="{{tabs}}"通过tabs属性传递页面中的定义的tabs数据。

  2. 接收子组件数据:在子组件的标签(此标签在父组件内即Tabs)上加入一个 自定义事件,注意做好对应关系才能接收数据,用下图可以说明

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

在这里插入图片描述
接收子组件传递过来的数据时,注意要子组件进行传递时的父组件的方法名,也就是说如果子组件用的是itemChange进行传递,那么父组件需要用binditemChange来绑定父组件的方法进行接收。

子组件
3. 从父接收数据: 子组件下有个properties,把这里面的数据当成是data中的数据直接用即可,里面存放的是从父组件中接收的数据,如下

properties: {
    tabs:{
      type:Array,
      value:[]
    }
  }
  1. 向父传递数据:通过自定义事件绑定要传递的数据(例如当前索引index),操作如下
//this.triggerEvent("父组件自定义事件的名称",要传递的参数)
this.triggerEvent("itemChange",{index});

代码实现

父组件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) {
    // 接收传递过来的参数
    const { index } = e.detail;
    let { tabs } = this.data;
    tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false);
    this.setData({
      tabs
    })
  }
})

父组件wxml

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

子组件wxml

<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>

子组件js

// components/Tabs.js
Component({
  properties: {
    tabs:{
      type:Array,
      value:[]
    }
  },
  data: {
  },
  methods: {
    hanldeItemTap(e){
      const {index}=e.currentTarget.dataset;
      // 5 触发父组件中的自定义事件 同时传递数据给  
      this.triggerEvent("itemsChange",{index});
    }
  }
})

至此,我们就完成了自定义组件的使用和传参啦

在这里插入图片描述

总结一下内容!!

父组件要使用子组件的话,首先在json中引入,然后在页面中用子组件标签<子组件名></子组件名>

父组件向子组件传参通过自己页面内的子标签传递,通过子组件的传递的方法名进行绑定接收的方法

子组件向父组件传参通过绑定方法传递,通过properties进行接收。

还有一个点,如果将父组件的写在子组件标签内容的元素显示出来呢,这时候就用到slot

slot插槽

slot 标签 其实就是一个占位符 插槽,写在子组件内用来接收父组件通过标签传递过来的
等到父组件调用子组件的时候,再传递标签过来最终这些被传递的标签,就会替换 slot 插槽的位置

子组件wxml,增加一个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>

父组件wxml,block就是要传递给子组件的内容,会替换slot

<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>

在这里插入图片描述

至此,完成小案例啦!你也快去试试吧!

在这里插入图片描述

发布了128 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44523860/article/details/105186435