微信小程序自定义组件(component)
1 需求实现一个分类标题的tab组件,可以放在任意页面使用,不需要重复编写
2 创建组件文件
在组件文件上右键 新建组件(Tabs),编辑器会自动生成组件文件
3 编写组件文件
组件属性方法说明
属性 | 类型 | 说明 |
---|---|---|
tabs | Array | Tabs组件显示的内容信息 |
binditemChange | 绑定接收子组件向父组件传递参数的事件<br />// 接收传递过来的参数是点击tabs的索引 在事件中获取参数: e.detail.index; |
|
<slot>占位符 | 在<tabs></tabs>自定义中加入任意内容,可以替代子组件中的占位标签 |
tabs 的示例数据
tabs:[{
id:0,
name:"首页",
isActive:true
},{
id:1,
name:"原创",
isActive:false
},{
id:2,
name:"分类",
isActive:false
},{
id:3,
name:"关于",
isActive:false
}]
binditemChange 示例
wxml 页面调用Tabs 组件
<Tabs tabs="{{tabs}}" binditemChange="handItemChange">
wxjs文件中添加获取回传参数的自定义事件监听方法
// 自定义事件 用来接收子组件传递的数据
handItemChange(e){
// 接收传递过来的参数
const {index} = e.detail;
console.log(e)
// 3 获取原数组,以下写法等价于 let tabs = this.data.tabs;
// 最好的方法 let tabs = JSON.stringify(this.data.tabs);深拷贝
let {tabs} = this.data;
//4 数组循环
// 1 给每一个循环项 选中属性 改为false
// 2 就给当前索引的项 添加激活选中效果就可以了
//4 数组循环 forEach 遍历数组时, 修改了 v 会导致源数组被修改
tabs.forEach((v,i)=> i===index?v.isActive=true:v.isActive=false);
this.setData({
tabs
});
}
Tabs.wxml 页面代码
<view>
</view>
<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
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>
Tabs.wxcss 样式文件
.tabs{}
.tabs-title{
display: flex; /*伸缩盒子*/
padding: 10px 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 js代码
父组件通过属性传递参数到子组件的properties中
// components/Tabs/Tabs.js
// components/Tabs/Tabs.js
Component({
/**
* 组件的属性列表
* 从父组件传递过来的数据
*/
properties: {
// 要接受的数据的名称
tabs:{
// type 要接受的数据的类型
type:Array,
// value 默认值
value:[]
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
hanldeItemTap(e){
console.log(e);
// 1.绑定点击事件 需要在methods中绑定
// 2 获取被点击的索引
const {index} = e.currentTarget.dataset;
//5 触发父组件的自定义事件 同时传递数据给 父组件
this.triggerEvent("itemChange",{index});
},
}
})
4 组件的调用
1 在页面的json配置文件中引用自定义组件(Tabs)
{
"usingComponents": {
"Tabs":"/components/Tabs/Tabs"
}
}
2 在页面中引用自定义组件标签
父组件通过属性的形式给子组件传递参数
子组件通过事件的形式式向父组件传递参数
流程 :
tabs="{{tabs}} 将当前页面的 tabs 传递给子组件<Tabs>
子组件<Tab> 回去到值,遍历tabs中的数据,将标题信息展现到页面
用户点击子组件<Tabs>的标题块,触发自定义事件itemChange
子组件的自定义事件 itemChange 获取到点击标题的索引,通过触发当前页面的自定义方法temChange,将索引值传递给当前页面
<!--
1 父组件 向传递子组件 传递数据 通过 标签属性的方式来传递的
1 在子组件上进行接收
2 把这个数据当成是data中的数据直接用即可
2 子向父传递数据 通过事件的方式传递
1 在子组件的标签中加入一个 自定义事件
-->
<!--
tabs 标题数组 传给子组件
binditemChange 子组件回传tabs被点击的标题的index
block 替代子组件中的占位标签 <slot>
-->
<Tabs tabs="{{tabs}}" binditemChange="handItemChange">
<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>
3 在js文件中加入要传递给子组件的数据, 以及从子组件中取值的方法
Page({
/**
* 页面的初始数据
*/
data: {
tabs:[{
id:0,
name:"首页",
isActive:true
},{
id:1,
name:"原创",
isActive:false
},{
id:2,
name:"分类",
isActive:false
},{
id:3,
name:"关于",
isActive:false
}]
},
// 自定义事件 用来接收子组件传递的数据
handItemChange(e){
// 接收传递过来的参数
const {index} = e.detail;
console.log(e)
// 3 获取原数组,以下写法等价于 let tabs = this.data.tabs;
// 最好的方法 let tabs = JSON.stringify(this.data.tabs);深拷贝
let {tabs} = this.data;
//4 数组循环
// 1 给每一个循环项 选中属性 改为false
// 2 就给当前索引的项 添加激活选中效果就可以了
//4 数组循环 forEach 遍历数组时, 修改了 v 会导致源数组被修改
tabs.forEach((v,i)=> i===index?v.isActive=true:v.isActive=false);
this.setData({
tabs
});
}
})