十年河东,十年河西,莫欺少年穷
学无止境,精益求精
1、首先我们创建一个基本的小晨旭组件【/Components/Tabs/Tabs】,如下
Tabs.js
// pages/Components/Tabs/Tabs.js 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: { tabitemchange: function (e) { const { index } = e.currentTarget.dataset; let list = this.data.tabs; list.forEach((v, i) => { console.log(v); console.log(i); i == index ? v.isactive = true : v.isactive = false; }); this.setData({ tabs: list }); } } })
Tabs.wxss
/* pages/Components/Tabs/Tabs.wxss */ .tabs{ } .tabs_title{ display: flex; padding:10rpx; } .tabs_item{ flex: 1; display: flex; justify-content: center; align-items: center; } .active{ color:red; border-bottom:4rpx solid red; } .tabs_content{}
Tabs.wxml ,注:tabitemchange 点击方法传参为:data-index 及 wx:for 中 item 的索引
<view class="tabs"> <view class="tabs_title"> <view class="tabs_item {{item.isactive?'active':''}}" wx:for="{{tabs}}" wx:key="id" bindtap="tabitemchange" data-index="{{index}}" wx:for-index="index" wx:for-item="item" > {{item.name}} </view> <!-- <view class="tabs_item active" bindtap="tabitemchange">首页</view> <view class="tabs_item">原创</view> <view class="tabs_item">分类</view> <view class="tabs_item">关于</view> --> </view> <view class="tabs_content">内容</view> </view>
在page页面中,引用该组件,如下
demo17.json
{ "usingComponents": {"Tabs":"../Components/Tabs/Tabs"} }
demo17.wxml
<Tabs> </Tabs>
这样,demo17的页面展示如下
以上我们就简单构建了一个组件。
在上述构造中,父组件为页面demo17.wxml ,子组件为tabs.wxml,那么组件之间怎么进行传值呢?
父向子传值
首先演示下父向子传值的简易demo,如下
在父组件中,自定义一个属性叫:fatherData
<!--pages/demo17/demo17.wxml--> <Tabs fatherData="请叫我爸爸"> </Tabs>
在子组件的属性中,创建 对象fatherData ,并声明 Type 属性为字符串,value 默认为空值
// pages/Components/Tabs/Tabs.js Component({ /** * 组件的属性列表 */ properties: { fatherData:{ type:String, value:"" } },
最后,在Tabs.wxml中添加如下代码
<view> 我接受到的值为:{{fatherData}} </view>
保存,并查看效果
这样,父传子就简单的完成了。
现在,我们传递变量给子组件,在demo17.js 中创建tabs数组如下:
// pages/demo17/demo17.js Page({ /** * 页面的初始数据 */ data: { tabs: [{ id: 0, name: "首页", isactive: true }, { id: 1, name: "原创", isactive: false }, { id: 2, name: "分类", isactive: false }, { id: 3, name: "关于", isactive: false } ] }, })
然后在demo17.wxml 中修改如下:
<!--pages/demo17/demo17.wxml--> <Tabs tabs="{{tabs}}"> </Tabs>
最后,在子组件Tab.js中申明要接收的tabs的类型及默认值
// pages/Components/Tabs/Tabs.js Component({ /** * 组件的属性列表 */ properties: { tabs:{ type:Array, value:[] } },
此时保存,并查看页面效果,和之前一样
但是,此时,子组件的tabitemchange 点击事件就有问题了,如下:

// pages/Components/Tabs/Tabs.js Component({ /** * 组件的属性列表 */ properties: { tabs:{ type:Array, value:[] } }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { tabitemchange: function (e) { const { index } = e.currentTarget.dataset; let list = this.data.tabs; list.forEach((v, i) => { console.log(v); console.log(i); i == index ? v.isactive = true : v.isactive = false; }); this.setData({ tabs: list }); } } })
此时,子组件的data 中并没有tabs 变量,因此 this.setData({}) 不生效,也不报错。
现在,tabs 变量是父组件传递过来的,那么,我们真正要修改的是父组件的tabs变量,这时,就需要子向父传值了,可参考:https://www.bilibili.com/video/BV1nE41117BQ?p=40
子向父传值
子向父传值时,需要使用 this.triggerEvent("itemChange",index); 绑定一个触发事件,并传递 index 变量
因此,在tabs.js 中 我们修改如下:
// pages/Components/Tabs/Tabs.js Component({ /** * 组件的属性列表 */ properties: { tabs:{ type:Array, value:[] } }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { tabitemchange: function (e) { const index= e.currentTarget.dataset.index; this.triggerEvent("itemChange",index); } } })
在父组件中,我们接受这个触发事件,如下:
<!--pages/demo17/demo17.wxml--> <Tabs tabs="{{tabs}}" binditemChange="itemChange"> </Tabs>
在父组件中,定义itemChange方法
// pages/demo17/demo17.js Page({ /** * 页面的初始数据 */ data: { tabs: [{ id: 0, name: "首页", isactive: true }, { id: 1, name: "原创", isactive: false }, { id: 2, name: "分类", isactive: false }, { id: 3, name: "关于", isactive: false } ] }, itemChange:function(e){ console.log(e) const index= e.detail; //传递过来的值 一般都放在 e.detail 中 let list = this.data.tabs; list.forEach((v, i) => { i == index ? v.isactive = true : v.isactive = false; }); this.setData({ tabs: list }); } })
这样,父组件就可以根据自个的需求,进行导航条的定义了。
最后,我们根据条目的切换,显示的内容变成动态的,这时,我们需要使用一个标签,插槽
插槽---Slot
首先在子组件中,内容部分,用插槽替代,如下
<view class="tabs_content"> <slot></slot> </view>
在父组件中,填充插槽
<!--pages/demo17/demo17.wxml--> <Tabs tabs="{{tabs}}" binditemChange="itemChange"> <view> 我要替代插槽 </view> </Tabs>
效果如下
最后,我们将我要替代插槽改成变量,即可完成内容的动态化
<!--pages/demo17/demo17.wxml--> <Tabs tabs="{{tabs}}" binditemChange="itemChange"> <block wx:if="{{tabs[0].isactive}}">首页被选中</block> <block wx:elif="{{tabs[1].isactive}}">原创被选中</block> <block wx:elif="{{tabs[2].isactive}}">分类被选中</block> <block wx:else="{{tabs[3].isactive}}">关于被选中</block> </Tabs>
效果
@天才卧龙的博客