类似vue或者react中的自定义组件
小程序允许我们使用自定义组件的方式来构建页面
10.1 创建自定义组件
类似于页面,一个自定义组件由.json/ .wxml / .wxss / .js 4个文件组成
可以在微信开发者工具中快速创建组件的文本结构
父组件的json文件:
{
"usingComponents": {
"Tabs": "../../components/Tabs/Tabs"
}
}
父组件的wxml页面:
<Tabs></Tabs>
子组件的js文件
// components/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
//要接收的数据的名称
tabs: {
type: Array, //要接收的数据类型
value: []
}
},
/**
* 组件的初始数据
*/
data: {
tabs: [
{
id: 1,
name: '首页',
isActive: true
}, {
id: 2,
name: '原创',
isActive: false
}, {
id: 3,
name: '分类',
isActive: false
}, {
id: 4,
name: '关于',
isActive: false
}
]
},
/**
* 1.页面.js文件中存放事件的回调函数的时候 存放在data的同层级下!!
* 2.组件.js文件中存放事件的回调函数的时候 必须要存放在methods中!
*/
methods: {
/*
* 1.绑定点击事件,需要在methods中绑定
* 2.获取被点击的索引
* 3.获取原数组
* 4.对数组循环
* 4.1给每一个循环项选中属性改为false
* 4.2给当前选中项的选中属性改为true
* */
handleItemTap(e){
console.log('handleItemTap')
//获取被点击的索引
console.log(e.currentTarget.dataset);
const {index} = e.currentTarget.dataset;
//获取data中的数组
//解构 对复杂类型进行解构的时候,复制了一份变量的引用而已
//最严谨的做法,重新拷贝一种数组,再对这个数组的备份进行处理
let {tabs} = this.data; //等同于:let tabs = this.data.tabs;
//循环遍历数组
//arr.forEach循环遍历数组,循环遍历数组的时候,修改了v,也会导致原数组被修改
tabs.forEach((v, i) => {
i===index?v.isActive=true:v.isActive=false;
})
this.setData({
tabs
})
}
}
})
子组件wxml页面:
<!--components/Tabs.wxml-->
<view class="tabs">
<view class="tabs_title">
<view
wx:for="{{tabs}}"
wx:key="id"
data-index="{{index}}"
class="title_item {{item.isActive?'active':''}}"
bindtap="handleItemTap">{{item.name}}</view>
</view>
<view class="tabs_content">内容</view>
</view>
10.2 父组件往子组件传值
父组件js
// pages/demoComponent/demoComponent.js
Page({
data: {
tabs: [
{
id: 1,
name: '首页',
isActive: true
}, {
id: 2,
name: '原创',
isActive: false
}, {
id: 3,
name: '分类',
isActive: false
}, {
id: 4,
name: '关于',
isActive: false
}
]
}
})
父组件json
{
"usingComponents": {
"Tabs": "../../components/Tabs/Tabs"
}
}
父组件页面
<!--pages/demoComponent/demoComponent.wxml-->
<view>pages/demoComponent/demoComponent.wxml</view>
<view>1.父组件(页面)向子组件传递数据通过标签属性的方式来传递</view>
<Tabs tabs="{{tabs}}"></Tabs>
子组件js
// components/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
//要接收的数据的名称
tabs: {
type: Array, //要接收的数据类型
value: []
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 1.页面.js文件中存放事件的回调函数的时候 存放在data的同层级下!!
* 2.组件.js文件中存放事件的回调函数的时候 必须要存放在methods中!
*/
methods: {
}
})
子组件页面
<!--components/Tabs.wxml-->
<view class="tabs">
<view class="tabs_title">
<view
wx:for="{{tabs}}"
wx:key="id"
data-index="{{index}}"
class="title_item {{item.isActive?'active':''}}"
bindtap="handleItemTap">{{item.name}}</view>
</view>
<view class="tabs_content">内容</view>
</view>
10.3 子组件往父组件传值
子组件wxml页面:
<!--components/Tabs.wxml-->
<view class="tabs">
<view class="tabs_title">
<view
wx:for="{{tabs}}"
wx:key="id"
data-index="{{index}}"
class="title_item {{item.isActive?'active':''}}"
bindtap="handleItemTap">{{item.name}}</view>
</view>
<view class="tabs_content">内容</view>
</view>
子组件js
// components/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
//要接收的数据的名称
tabs: {
type: Array, //要接收的数据类型
value: []
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 1.页面.js文件中存放事件的回调函数的时候 存放在data的同层级下!!
* 2.组件.js文件中存放事件的回调函数的时候 必须要存放在methods中!
*/
methods: {
/*
* 1.绑定点击事件,需要在methods中绑定
* 2.获取被点击的索引
* 3.获取原数组
* 4.对数组循环
* 4.1给每一个循环项选中属性改为false
* 4.2给当前选中项的选中属性改为true
* */
handleItemTap(e){
console.log('handleItemTap')
console.log(e.currentTarget.dataset);
//获取被点击的索引
const {index} = e.currentTarget.dataset;
//点击事件触发的时候
//触发父组件中的自定义事件,同时传递数据给 父组件
//this.triggerEvent('父组件定义事件的名称', 要传递的参数)
this.triggerEvent('itemChange', {index});
}
}
})
父组件json
{
"usingComponents": {
"Tabs": "../../components/Tabs/Tabs"
}
}
父组件页面
<!--pages/demoComponent/demoComponent.wxml-->
<view>pages/demoComponent/demoComponent.wxml</view>
<view>1.父组件(页面)向子组件传递数据通过标签属性的方式来传递</view>
<Tabs tabs="{{tabs}}" binditemChange="handleItemChange"></Tabs>
父组件js
// pages/demoComponent/demoComponent.js
Page({
data: {
tabs: [
{
id: 1,
name: '首页',
isActive: true
}, {
id: 2,
name: '原创',
isActive: false
}, {
id: 3,
name: '分类',
isActive: false
}, {
id: 4,
name: '关于',
isActive: false
}
]
},
handleItemChange(e){
console.log('handleItemChange')
console.log(e)
console.log(e.detail.index)
const {index} = e.detail;
let {tabs} = this.data;
tabs.forEach((v,i)=> {
i === index ? v.isActive = true : v.isActive = false;
})
this.setData({
tabs
})
}
})