组件是写项目时常用的,那么如何自定义一个组件呢,下面我就大概描述一下:
大概效果如图,假设我要自定义一个弹窗组件
如上图,我想自定义一个弹窗组件,方便复用节省代码,那么让我们首先了解一下components
官方文档微信小程序components
1. 首先我们先在项目中创建组件的文件夹
components文件夹下是我写的所有的组件
接下来我给弹窗组件起个名字 tipModel,在components下的tipModel上右键,选择新建Component就会自动生成4个文件。
2.在生成的文件中写出我们要的效果(组件)
tipModel.wxml
<!--components/tipModel/tipModel.wxml-->
<view class="box" wx:if="{{isShow}}">
<view class="tire" bindtap="cancle"></view>
<view class="tip_box center f-28">
<image src="../../assets/images/icon.png"></image>
<view class="box_con cl333">{{content}}</view>
<view class="btn clearfix">
<view class="cancle fl center cl666" bindtap="cancle">取消</view>
<view class="sure fr center clfff" bindtap="sure">确认</view>
</view>
</view>
</view>
- 像写页面一样去写就行了,需要父组件传的值或方法在上面代码中已经写了,isShow,content,cancle等等,下面会介绍如何传值,如何子组件执行父组件的方法
tipModel.wxss
/* components/tipModel/tipModel.wxss */
.content_box {
height: 100%;
}
.Iphone_bottom {
padding-bottom: 50rpx;
}
view {
box-sizing: border-box;
}
.f-20 {
font-size: 20rpx;
}
.f-22 {
font-size: 22rpx;
}
.f-24 {
font-size: 24rpx;
}
.f-28 {
font-size: 28rpx;
}
.f-32 {
font-size: 32rpx;
}
.f-36 {
font-size: 36rpx;
}
.f-40 {
font-size: 40rpx;
font-weight: 700;
}
.center {
text-align: center;
}
.block {
display: block;
}
.inBlock {
display: inline-block;
}
.fl {
float: left;
}
.fr {
float: right;
}
.clearfix {
clear: both;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
visibility: hidden;
clear: both;
}
.clFFB33A {
color: #eb7851;
}
.cl333 {
color: #333;
}
.cl666 {
color: #666;
}
.cl999 {
color: #999;
}
.cl000 {
color: #000;
}
.clccc {
color: #ccc;
}
.clfff {
color: #fff;
}
.bgfff {
background-color: #fff;
}
.tire {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 101;
}
.tire_white {
background-color: transparent;
}
.text_overflow {
white-space: nowrap;
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
.more_textOverflow {
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.box_shadow {
box-shadow: -1px 0px 6px 1px rgba(117, 117, 117, 0.08);
}
.border_bottom {
border-bottom: 1px solid #e5e5e5;
}
.box {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 100;
}
.tip_box {
width: 75%;
padding: 60rpx 40rpx 40rpx;
background-color: #fff;
border-radius: 10rpx;
z-index: 1000;
}
.tip_box image{
width: 104rpx;
height: 104rpx;
}
.tip_box .box_con{
padding: 60rpx 0 80rpx;
}
.tip_box .btn>view{
width: 47%;
height: 64rpx;
line-height: 64rpx;
}
.tip_box .btn>view.cancle{
border: 1px solid #D8D8D8;
}
.tip_box .btn>view.sure{
background-color: #EB7851;
box-shadow:0px 2px 4px 0px rgba(207,57,7,0.47);
}
tipModel.json
{
"component": true,
"usingComponents": {}
}
tipModel.js
// components/tipModel/tipModel.js
Component({
/**
* 组件的属性列表
*/
properties: {
content:{
type:String
},
isShow:{
type:Boolean,
default:false
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
cancle:function(){
this.triggerEvent('cancle')
},
sure: function () {
this.triggerEvent('modelSure')
}
}
})
这边我来简单介绍一下组件的js里面的内容(如果对组件有了解可以忽略不看)
- Component 构造器可用于定义组件,调用 Component 构造器时可以指定组件的属性、数据、方法等。
- properties:组件的对外属性,是属性名到属性设置的映射表,简单来说,其实就是父组件传到子组件的值,我们需要在properties定义一下才能接收到父组件传过来的值,定义方式如下:
// 属性定义
properties: {
myProperty: { // 属性名
type: String,
value: ''
},
myProperty2: String // 简化的定义方式
},
- data:组件的内部数据,和 properties 一同用于组件的模板渲染,跟页面中的data作用一样
- observers:组件数据字段监听器,用于监听 properties 和 data 的变化,好像类似vue中的watch
使用数据监听器
有时,在一些数据字段被 setData 设置时,需要执行一些操作。
例如, this.data.sum 永远是 this.data.numberA 与 this.data.numberB 的和。此时,可以使用数据监听器进行如下实现。
Component({
attached: function() {
this.setData({
numberA: 1,
numberB: 2,
})
},
observers: {
'numberA, numberB': function(numberA, numberB) {
// 在 numberA 或者 numberB 被设置时,执行这个函数
this.setData({
sum: numberA + numberB
})
}
}
})
- methods:组件中的方法
- created:组件生命周期函数-在组件实例刚刚被创建时执行,注意此时不能调用 setData
还有很多属性,可以去参考文档,这边不全部列举了。参考链接
3.在页面中引入组件
1.index.json
首先我们在json文件中写出引入组件
{
"usingComponents": {
"tip-model": "/components/tipModel/tipModel"
},
"navigationBarTitleText": "首页"
}
2.index.wxml
然后在页面中引入,上面json文件中起的名字,就是标签的名字: “tip-model”
<button bindtap="showAlert">显示弹窗</button>
<tip-model is-show="{{alert_show}}" content="{{tipContent}}" bindcancle="cancle" bindmodelSure="delGood"></tip-model>
因为需要从父组件传值到子组件,传值方式如上所示,注意:
- 从父组件传到子组件的值,子组件需要在js文件中properties里面定义一下
- 子组件中变量驼峰命名的变量。父组件要用横线替换,例如 isShow 要替换成 is-show
- 子组件要调用父组件的方法,如上 cancle方法,子组件用**this.triggerEvent(‘cancle’)**去接收父组件的方法,父组件要在标签上,用 bindcancle = “父组件方法” 去传方法
3.index.js
Page({
data: {
alert_show:false,
},
// 删除商品弹窗
showAlert:function(e){
this.setData({
alert_show:true,
})
},
cancle:function(){
this.setData({
alert_show: false
})
},
sure:function(){
console.log('点击确认')
},
})
这样一个组件就完成了。
4.子组件传值给父组件
下面代码是以上面代码为基础修改的:
上面我们写的用的都是父组件传值给子组件,那子组件怎么传值给父组件呢,下面我来介绍一下:
子传父需要手动操作,假设我们点击子组件cancle方法时,需要传值给父组件,我们在cancle方法里面加上一个值
tipModel.js
cancle:function(){
this.triggerEvent('cancle','这是子组件的值')
},
然后父组件绑定的cancle方法里面用下面语句接收:
index.js
cancle:function(e){
console.log(e.detail);//这就是子组件传过来的值
this.setData({
alert_show: false
})
},