创建自定义组件
自定义组件类似一个页面,一个自定义组件由.json .wxml .wxss .js
4个文件组成.
可以在微信开发者工具中快速创建组件的文件结构
创建组件文件夹componments
,然后这里先创建一个组件Tabs
关于组件如何使用看后面的案例.
声明引入自定义组件
在要使用组件的页面中的page.json
中进行应用声明
{
"usingComponents": {
"Tabs": "../../components/Tabs/Tabs"
}
}
页面中使用自定义组件
声明了要引用的组件,就可以直接在page.wxml
中使用组件了
<Tabs></Tabs>
案例: Tabs组件
首先新建一个页面demo05
并置顶显示,编辑app.json
如下
{
"pages": [
"pages/demo05/demo05",
...
创建components/
,并创建组件Tabs
在要使用的页面中引入组件
在pages/demo05/demo05.json
中,编辑代码如下
{
"usingComponents": {
"Tabs": "../../components/Tabs/Tabs"
}
}
引入自定义组件之后,就可以在.wxml
中直接使用Tabs
了
编辑demo05.wxml
<Tabs></Tabs>
可以看到,现在页面一点效果都没有,接下来就开始对Tabs
组件添加功能.
编辑Components/Tab/Tab.wxml
,代码如下
<view class="tabs">
<view class="tabs_title">
<view class="title_item">首页</view>
<view class="title_item">原创</view>
<view class="title_item">分类</view>
<view class="title_item">关于</view>
</view>
<view class="tabs_content">内容</view>
</view>
编辑Components/Tab/Tab.wxss
,代码如下
.tabs {
}
.tabs_title {
display: flex;
padding: 10rpx 0;
}
.title_item {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.tabs_content {
}
.active {
color: red;
border-bottom: 5rpx solid currentColor;
}
现在开始增加点击激活样式.
编辑components/Tabs/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: {},
});
编辑components/Tabs/Tabs.wxml
代码如下
<view class="tabs">
<view class="tabs_title">
<!-- <view class="title_item">首页</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':''}}">
{{item.name}}
</view>
</view>
<view class="tabs_content">内容</view>
</view>
现在选中效果默认是第一个的,然后开始设置激活选中效果.
首先给标题绑定一个点击事件,编辑Tabs.wxml
代码如下
bindtap="绑定事件"
data-xxx="{{item.xx}}"
...
<view wx:for="{{tabs}}" wx:key="id" class="title_item {{item.isActive?'active':''}}" bindtap="handleItemTap" data-id="{{item.id}}" >
{{item.name}}
</view>
...
编辑Tabs.js
代码如下
...
methods: {
handleItemTap: function (e) {
// console.log(e);
const id = e.currentTarget.dataset.id; // 获取id
let tabs = this.data.tabs; // 获取data中的数组
// [].forEach 遍历数组,修改了v,也会导致原数组的值修改
tabs.forEach((v,i)=>i===id?v.isActive=true:v.isActive=false);
// 最后还是要将数据给设置回去
this.setData({
tabs:tabs
})
},
},
...
显示效果如下:
组件-自定义组件传参
(1) 父组件通过属性的方式给子组件传递参数
(2) 子组件通过事件的方式向父组件传递参数
(3) slot
自定义组件中占位符
父组件向子组件传递参数
一般父组件就是使用自定义组件的page
,子组件也就是自定义组件.
看回刚刚的案例,刚刚自定义组件的数据不应该写死在自定义组件中,而应该从父组件传递而来,这样自定义组件才能更大程度被其他组件复用. 接下来就修改下刚刚的案例代码.
首先自定义组件中properties
属性来接收父组件传递过来的列表.
properties: {
变量名:{
type:变量属性,
value:变量默认值
}
},
将Tabs.js
中的tabs
数组剪切到demo05.js
当中.
然后编辑demo05.wxml
,通过自定义属性传递参数给子组件,代码如下,
<Tabs tabs="{{tabs}}"></Tabs>
demo05.js
// pages/demo05/demo05.js
Page({
/**
* 页面的初始数据
*/
data: {
tabs: [
{ id: 0, name: "首页", isActive: true },
{ id: 1, name: "原创", isActive: false },
{ id: 2, name: "分类", isActive: false },
{ id: 3, name: "关于", isActive: false },
]
},
...
Tabs.js
// components/Tabs/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
tabs:{
type:Array,
value:[]
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
handleItemTap: function (e) {
// console.log(e);
const id = e.currentTarget.dataset.id; // 获取id
let tabs = this.data.tabs; // 获取data中的数组
// [].forEach 遍历数组,修改了v,也会导致原数组的值修改
tabs.forEach((v,i)=>i===id?v.isActive=true:v.isActive=false);
// 最后还是要将数据给设置回去
this.setData({
tabs:tabs
})
},
},
});
显示效果没有变化
子组件向父组件传递参数
但是这里有一个问题,就是指修改了子组件的数据,但是没有修改父组件的数据.
最后的this.setData({})
相当于是把tabs
这个修改后的数组给到子组件(原本子组件中的data
是没有数组的)
demo05.js
代码如下
...
handleItemChange:function(e){
// console.log(e);
const id = e.detail; // e.detail获得传递过来的参数
let tabs = this.data.tabs; // 获取data中的数组
// [].forEach 遍历数组,修改了v,也会导致原数组的值修改
tabs.forEach((v,i)=>i===id?v.isActive=true:v.isActive=false);
// 最后还是要将数据给设置回去
this.setData({
tabs:tabs
});
}
...
demo05.wxml
代码如下
<Tabs tabs="{{tabs}}" binditemChange="handleItemChange" ></Tabs>
Tabs.js
代码如下
// components/Tabs/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
tabs:{
type:Array,
value:[]
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
handleItemTap: function (e) {
const id = e.currentTarget.dataset.id; // 获取id
this.triggerEvent("itemChange",id); // 自定义组件
},
},
});
slot占位符
对于自定义组件,<slot>
就是占位符,父组件传递什么组件就是什么
Tabs.wxml
代码如下
...
<view class="tabs_content">
<slot></slot>
</view>
...
demo05.wxml
代码如下
<Tabs tabs="{{tabs}}" binditemChange="handleItemChange" >
<view wx:if="{{tabs[0].isActive}}">0</view>
<view wx:elif="{{tabs[1].isActive}}">1</view>
<view wx:elif="{{tabs[2].isActive}}">2</view>
<view wx:else>3</view>
</Tabs>
显示效果如下