目录
1、向组件传递数据 — properties
2、向组件传递样式 — externalClasses
3、组件向外传递事件 — 自定义事件
4、页面直接调用组件修改数据/方法 — this.selectComponent
5、组件的插槽 — slot
6、自定义组件练习 — tab-control
很多情况下,组件内展示的内容(数据、样式、标签)并不是在组件内写死的,而且由使用者(引用组件的页面)来决定,这样就可以做到类似于 vue 的父子组件传值,组件还可以定义自定义事件向页面发送信息,示意图如下:
大部分情况下,组件只负责布局和样式,内容是由使用组件的对象来决定,所以,我们经常需要从外部传递数据给组件,让组件来进行展示。向组件传递数据 — 使用 properties 属性:
{{title}}
我是组件的内容/view>
Component({
properties:{
//title:String,
title:{
type:String,
value:'默认犬种'
},
observer:function(neVal,oldVal){
console.log(newVal,oldVal);
}
},
data:{}
methods:{}
})
有时候,我们不希望将样式在组件内固定不变,而是外部可以决定样式,这个时候,我们可以使用 externalClasses 属性:(1)在 Component 对象中,定义 externalClasses 属性(2)在组件内的 wxml 中使用 externalClasses 属性中的 class(3)在页面中传入对应的 class,并且给这个 class 设置样式。
我是组件
我是组件的内容/view>
Component({
properties:{},
externalClasses:['titleclass'],
data:{}
methods:{}
})
有时候是自定义组件内部发生了事件,需要告知使用者(引用组件的页面),这个时候可以使用自定义事件:(1)监听组件的点击,为其绑定点击函数(2)在组件的 js 文件定义点击函数,并通过:this.triggerEvent('increment',{name:'erha'},{}); 的方式向外传递事件(3)在页面的的组件占位符上对组件发射出来的事件进行监听,并在页面的 js 文件对鉴定事件进行定义(4)在页面的 js 文件中可以通过 event 参数拿到组件传递过来的 payload 参数。
Component({
methods:{
handleIncrement(){
this.triggerEvent('increment',{name:'erha'},{});
}
}
})
Page({
data:{
counter:0;
},
handleIncrement(event){
console.log(event);
this.setData({
counter: this.data.counter + 1;
})
}
})
在页面或者别的组件中,可以通过 selectComponent() 方法获取指定的 id 或 class 的组件对象(推荐使用 id 的方式),然后通过该组件对象即可直接调用该组件内的数据和方法,不推荐直接修改组件中的数据,而是调用组件内的方法修改组件内的数据。
组件内的计数:{{counter}} {
"components":true;
Component({ }
data:{ counter:0 },
methods:{ increment(num){ this.setData({counter:this.data.counter + num}) }
})
-----------------------------------------------------------------------------------------------------------------
Page({ "usingComponents":{ "my-sel":"/components/my-sel/my-sel" }
handleIncrementCpn(){
const my_sel_class = this.selectComponent('.sel-class');
const my_sel_id = this.selectComponent('#sel-id');
my_sel_id.setData({
counter: my_sel.data.counter + 20;
})
my_sel_id.increment(10);
}
})
5.1、slot 插槽的定义:在生活中很多地方都有插槽,电脑的 USB 插槽,插板当中的电源插槽。插槽的目的是让原来的设备具备更多的扩展性,比如电脑的 USB 插槽就可以插入U盘、硬盘、手机、音响、键盘、鼠标等等。组件的 slot 插槽也是为了让我们封装的组件更加具有扩展性,使用者可以决定组件内部的一些内容到底展示什么。
5.2、单个插槽的使用
除了组件的内容和样式可能由外界决定之外,显示的方式也可由外界决定,比如一个组件定义了头部和尾部,但是中间的内容可能是一段文字,也可能是一张图片,或者是一个进度条。在不确定外界想插入什么的前提下,我们可以在组件内预留 slot 插槽。
组件头部 {
"components":true;
组件尾部 }
-----------------------------------------------------------------------------------------------------------------
"usingComponents":{ "my-slot":"/components/my-slot/my-slot" }
5.3、多个插槽的使用
有时候为了让组件更加灵活,需要定义多个插槽,为了区分它们,需要给每一个组件 name 属性,而且还必须在组件的 Component 对象中添加一个选项:options:{ multipleSlots:true }。
组件头部 {
"components":true;
}
组件尾部 Component({
options:{
multipleSlots:true
}
})
-----------------------------------------------------------------------------------------------------------------
"usingComponents":{ "my-slots":"/components/my-slots/my-slots" }
需求:开发一个 tabcontrol 自定义控制导航组件,如下图所示,为了提高该组件的复用性,要求导航中的文字不能在组件中写死,而是由外界页面传递进去的,而且在点击该组件时需要向外界发送自定义事件,告知外界页面导航中的哪个模块被点击了。
开发前准备:需要在根目录下新建 components\tab-control 组件,tab-control 组件的 json 文件中,有一个 "component":true 标识,只有加上这行代码,当前的文件夹才是一个组件。然后到 home.json 文件中对该组件进行注册:{"usingComponents":{"tab-control":/component/tab-control/tab-control}},然后再到 home.wxml 通过
{{item}}
.tab-control{ .tab-item{ .active{ .active text{
display:flex; flex:1; color:red; border-bottom:6rpx solid red;
height:88rpx; text-align:center; } padding:26rpx 16rpx;
line-height:88rpx; } }
}
Component({ {
properties:{ "component":true
titles:{ }
type:Array,
value:[]
}
},
data:{ currentIndex:0 }
methods:{
handleItemclick(event){
const index = event.currentTarget.dataset.index;
this.setData({ currentIndex:index; });
this.triggerEvent('itemclick',{index,title:this.properties.titles[index]},{});
}
}
}
-----------------------------------------------------------------------------------------------------------------
"usingComponents":{ "tab-control":"/components/tab-control/tab-control" }
Page({
handleTabClick(event){
console.log(event);
}
})