自定义组件
Component(Object object) | 微信开放文档 (qq.com)
将部分重复代码抽取出来
商品分类 (taobao.com)
创建自定义组件
类似于页面,一个自定义组件由json、wxml、wxss、js 4个文件组成
可以在微信开发者⼯具中快速创建组件的⽂件结构
声明组件、引入组件
tabs.json
demo01.json
1 2 3 4 5
| { "usingComponents": { "Tabs": "/components/Tabs/Tabs" } }
|
简单编辑组件
Tabs.wxml
1 2 3 4 5 6 7 8 9 10 11 12
| <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>
|
Tabs.wxss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| .tabs {}
.tabs_title { display: flex; padding: 10rpx 0; }
.title_item { flex: 1; display: flex; justify-content: center; align-items: center; }
.active { color: #b81d24; border-bottom: 5rpx solid currentColor; }
.tabs_content {}
|
以上数据都写在组件的wxml中,接下来来实现js动态数据
填入初始数据
Tabs.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| 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: { } })
|
Tab.wxml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <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>
|
绑定点击事件
Tab.wxml
1 2 3 4 5 6 7 8 9
| <view class="tabs_title"> <view wx:for="{{tabs}}" wx:key="id" class="title_item {{item.isActive?'active':''}}" bindtap="handleItemTap" data-index="{{index}}"> {{item.name}} </view> </view>
|
注意自定义组件的方法写在methods中
Tabs.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| methods: { handleItemTap(e) { console.log(e);
const index = e.currentTarget.dataset.index;
let tabs = this.data.tabs;
tabs.forEach((v, i) => { i === index ? v.isActive = true : v.isActive = false });
this.setData({ tabs }) } }
|
以上数据都写在组件中,接下来来实现父向子传递数据
父向子传递数据
demo01.wxml
1 2 3 4 5 6
|
<Tabs abc="要传递的数据"></Tabs>
|
Tabs.js
1 2 3 4 5 6 7 8 9
| properties: { abc: { type: String, value: "" } },
|
Tabs.wxml
接下来修改案例代码
将要传递的数据放在父组件的data中,即原先写在Tabs.js的data中的数据放在demo01.js的data中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| data: { tabs: [ { id: 0, name: "首页", isActive: true }, { id: 1, name: "原创", isActive: false } , { id: 2, name: "分类", isActive: false } , { id: 3, name: "关于", isActive: false } ] },
|
父组件通过标签属性传递数据
demo01.wxml
1
| <Tabs tabs="{{tabs}}"></Tabs>
|
子组件在properties中接收,最后效果与之前相同
Tabs.js
1 2 3 4 5 6
| properties: { tabs: { type: Array, value: [] } },
|
此时Tabs.js
中代码仍然是在子组件当中修改tab数组,而不是在父组件的data中修改tab(可以在AppData窗口查看)
1 2 3 4 5 6
| let tabs = this.data.tabs;
this.setData({ tabs })
|
所以需要将处理数据放在父组件当中,而所需要的索引值则由子组件传递给父组件(子向父传递数据)
子向父传递数据
Tabs.js
1 2 3 4 5 6 7 8
| methods: { handleItemTap(e) { const index = e.currentTarget.dataset.index; this.triggerEvent("itemChange", { index }); } }
|
demo01.wxml
1 2 3 4 5 6
|
<Tabs tabs="{{tabs}}" binditemChange="handleItemChange"></Tabs>
|
demo01.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| handleItemChange(e) { console.log(e); const index = e.detail.index; let tabs = this.data.tabs; tabs.forEach((v, i) => { i === index ? v.isActive = true : v.isActive = false }); this.setData({ tabs }) },
|
AppData窗口查看即可
slot标签
slot占位符(插槽),父组件调用子组件传递一些标签来替换slot的位置
Tabs.wxml
1 2 3
| <view class="tabs_content"> <slot></slot> </view>
|
demo01.wxml
1 2 3 4 5 6
| <Tabs tabs="{{tabs}}" binditemChange="handleItemChange"> <block wx:if="{{tabs[0].isActive}}">内容1</block> <block wx:elif="{{tabs[1].isActive}}">内容2</block> <block wx:elif="{{tabs[2].isActive}}">内容3</block> <block wx:else>内容4</block> </Tabs>
|
生命周期
应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| App({ onLaunch() { console.log("onLaunch"); },
onShow() { console.log("onShow"); },
onHide() { console.log("onHide"); },
onError(error) { console.log("onError"); console.log(error); },
onPageNotFound() { console.log("onPageNotFound"); wx.navigateTo({ url: '/pages/demo01/demo01', }) }
})
|
页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| Page({
data: {
},
onLoad: function (options) { console.log("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() { console.log("onPageScroll"); },
onResize() { console.log("onResize"); },
onTabItemTap() { console.log("onTabItemTap"); } })
|