自定义组件
Component(Object object) | 微信开放文档 (qq.com)
将部分重复代码抽取出来
创建自定义组件
类似于页面,一个自定义组件由json、wxml、wxss、js 4个文件组成
可以在微信开发者⼯具中快速创建组件的⽂件结构
声明组件、引入组件
tabs.json
{
"component": true
}
demo01.json
{
"usingComponents": {
"Tabs": "/components/Tabs/Tabs"
}
}
简单编辑组件
Tabs.wxml
<!--components/Tabs/Tabs.wxml-->
<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
/* components/Tabs/Tabs.wxss */
.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
// 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: {
}
})
Tab.wxml
<view class="tabs">
<view class="tabs_title">
<!-- 列表渲染 -->
<!-- class中三元表达式,根据item的isActive属性判断是否选中,选中则添加类名以显示样式 -->
<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
<view class="tabs_title">
<!-- 列表渲染 -->
<!-- class中三元表达式,根据item的isActive属性判断是否选中,选中则添加类名以显示样式 -->
<!-- data-index自定义属性,用于传递当前的索引值 -->
<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
methods: {
handleItemTap(e) {
// 查看索引所在的位置
console.log(e);
// 1.获取被点击的索引
// ES6常量const,只读不可改
// ES6解构赋值:const { index } = e.currentTarget.dataset;
const index = e.currentTarget.dataset.index;
// 2.获取原数组
// ES6变量let,块级作用域
// ES6解构赋值:let { tabs } = this.data;
let tabs = this.data.tabs;
// 3.循环数组:为当前索引项设置isActive:true,其余false
// ES6箭头函数
tabs.forEach((v, i) => {
i === index ? v.isActive = true : v.isActive = false
});
// 修改数据
this.setData({
tabs
})
}
}
以上数据都写在组件中,接下来来实现父向子传递数据
父向子传递数据
demo01.wxml
<!--
父组件demo01,子组件Tabs
父组件通过标签属性传递数据
子组件在properties中接收
-->
<Tabs abc="要传递的数据"></Tabs>
Tabs.js
properties: {
// 属性名
abc: {
// 接收的数据的类型
type: String,
// 默认值
value: ""
}
},
Tabs.wxml
<!-- 相当于data中的数据使,用{{}}渲染 -->
<view>{{abc}}</view>
接下来修改案例代码
-
将要传递的数据放在父组件的data中,即原先写在Tabs.js的data中的数据放在demo01.js的data中
data: { tabs: [ { id: 0, name: "首页", isActive: true }, { id: 1, name: "原创", isActive: false } , { id: 2, name: "分类", isActive: false } , { id: 3, name: "关于", isActive: false } ] },
-
父组件通过标签属性传递数据
demo01.wxml
<Tabs tabs="{{tabs}}"></Tabs>
-
子组件在properties中接收,最后效果与之前相同
Tabs.js
properties: { tabs: { type: Array, value: [] } },
此时Tabs.js
中代码仍然是在子组件当中修改tab数组,而不是在父组件的data中修改tab(可以在AppData窗口查看)
// this.data中找不到数据,则在properties中寻找
let tabs = this.data.tabs;
// 将tabs放入data当中
this.setData({
tabs
})
所以需要将处理数据放在父组件当中,而所需要的索引值则由子组件传递给父组件(子向父传递数据)
子向父传递数据
Tabs.js
methods: {
handleItemTap(e) {
// 1.获取被点击的索引
const index = e.currentTarget.dataset.index;
// 2.触发父组件中的自定义事件,并传递数据
this.triggerEvent("itemChange", { index }); //triggerEvent("自定义事件名", 要传递的数据)
}
}
demo01.wxml
<!--
子组件Tabs -> 父组件demo01
在子组件的标签中添加自定义事件
编写父组件js事件方法
-->
<Tabs tabs="{{tabs}}" binditemChange="handleItemChange"></Tabs>
demo01.js
// 自定义事件方法
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
<view class="tabs_content">
<slot></slot>
</view>
demo01.wxml
<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>
生命周期
应用
// app.js
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',
})
}
})
页面
// pages/demo02/demo02.js
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");
},
/**
* 当前是tab页,点击当前页的tab时触发
*/
onTabItemTap() {
console.log("onTabItemTap");
}
})
},
/**
- 页面上拉触底事件的处理函数
- 触底加载更多数据
*/
onReachBottom: function () {
console.log(“onReachBottom”);
},
/**
- 用户点击右上角分享
*/
onShareAppMessage: function () {
console.log(“onShareAppMessage”);
},
/**
- 页面滚动
*/
onPageScroll() {
console.log(“onPageScroll”);
},
/**
- 页面尺寸改变
*/
onResize() {
console.log(“onResize”);
},
/**
- 当前是tab页,点击当前页的tab时触发
*/
onTabItemTap() {
console.log(“onTabItemTap”);
}
})