【小程序】自定义组件之component
2019-01-19 本文已影响0人
嘻洋洋
1.自定义组件用做什么?
- 可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用。
- 也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。
2.应用场景
- 底部的Tab栏,顶部的标题栏
- 在不同的页面中,有时候会用到相同的功能模块,此时我们就可以将这些相同的部分提取出来并且单独设为一个"页面",然后在要应用到它的地方引用就可以了。
3.具体应用
3.1组件定义需要做的重点工作。
页面部分要素:属性(properties)、方法、slot(插入的内容)
<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
{{innerText}}
<button bindtap='customMethod'>点击</button>
<slot></slot>
</view>
- wxml的slot
一个组件的wxml中只能有一个slot。需要使用多slot时,可以在组件js中声明启用。
<!--
页面框架
1. 首部
2. 主体内容
3. 底部导航
-->
<import src="../../plugin/confirm/confirm.wxml" />
<view class="container" style="padding-bottom:{{paddingBottom}}; {{style}}">
<!--<image src="{{loggifsrc}}" style="display:none"></image>-->
<slot name="header"></slot>
<slot name="body"></slot>
<slot name="bottom"></slot>
<!-- 已经到底了 -->
<block wx:if="{{showDeadline}}">
<view class="usermotto" style="{{deadLineStyle}}">
<!-- <text class="user-motto line" decode='true'>        </text> -->
<text class="user-motto text" > 哇哦,已经到最后咯~</text>
<!-- <text class="user-motto line" decode='true' >        </text> -->
</view>
</block>
<!-- 滚动到顶部 -->
<block wx:if="{{toTop}}">
<view class="back-top" bindtap="scrolltop">
<image src="https://image.hh.com/wechat/wxmp/order/arrow.png"></image>
<text>顶部</text>
</view>
</block>
<!-- 页面弹窗模板 -->
<template is="confirmbox" wx:if="{{showComfirmBox}}"data="{{confirmBox:confirmBox}}"/>
</view>
- 组件的对外属性
properties:组件的对外属性,结合data属性一同用于组件的模版渲染。都是用于渲染,区别在于组件的属性存放公共数据的地方,可以供调用方传递数据,而data是私有属性的地方,data中的数据只有组件可以访问,外部无法访问。
如何定义属性:属性设置中可包含三个字段
, type 表示属性类型、 value 表示属性初始值、 observer 表示属性值被更改时的响应函数
properties: {
myProperty: { // 属性名
type: String, // 类型,目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
observer: function(newVal, oldVal, changedPath) {
// 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
// 通常 newVal 就是新设置的数据, oldVal 是旧数据
}
},
myProperty2: String // 简化的定义方式
},
当然了也可以简化:
//--------调用页面-------
data () {
return {
//短信验证码
info: {
sms_gb: 50
}
}
<!--短信验证码弹框-->
<verificode id="verificode" info="{{info}}" bind:onSmsValid="onSmsValid" bind:onCloseSms="onCloseSms" wx:if="{{isShowSmsSend}}"></verificode>
</view>
//-------------组件页面---------------
//info属性
properties () {
return {
info: Object
}
}
使用 this.data 可以获取内部数据和属性值,但不要直接修改它们,应使用 setData 修改
let { rtnCode, rtnMsg, validateCode } = await that.API.sendSms(phone, this.data.info.sms_gb)
**注意:属性名应避免以 data 开头,即不要命名成 dataXyz 这样的形式,因为在 WXML 中, data-xyz="" 会被作为节点 dataset 来处理,而不是组件属性**
- 组件的方法
组件的方法,包括事件响应函数和任意的自定义方法都必须写在methods方法里面。
//组件里面页面元素的事件。比如说button、view元素绑定的事件。
<view class="btn-group">
<view class="btn-cancle" bindtap="onBindCancel">取消</view>
<view class="btn-sure" bindtap="onBindOK">确定</view>
</view>
//定义事件
methods() {
return {
/*
*@description:确定事件处理
*/
async onBindOK () {
if (this.data.inputCode.valid) {
this.triggerEvent("onSmsValid");
}
},
async onBindCancel () {
this.triggerEvent("onCloseSms");
},
}
}
自定义组件可以触发任意的事件,通过triggerEvent方法触发,引用组件的页面可以监听这些事件。如:
//myevent:引用组件页面定义的监听事件
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
//引用组件页面监听事件
Page({
onMyEvent: function(e){
e.detail // 自定义组件触发事件时提供的detail对象
}
})
//组件事件
methods() {
return {
// 点击跳转到商品详情页面
onGoodsDetail (e) {
this.triggerEvent("onGoodsClick", e.currentTarget.dataset.skuid);
}
}
}
//引用组件页面监听事件
async onGoodsDetail (e) {
this.WXX.navigateTo("../detail/detail", {
skuid: e.detail
});
}
3.2页面如何运用组件
(1)在页面上使用组件,首先两个步骤
- 引入组件
在页面对应的json文件中引入
"usingComponents": {
"container": "../../components/container/container",
"verificode": "../../../components/verificode/verificode"
}
- 页面放置组件
在wxml文件中放置组件,具体工作:
1、定义id:id是引入时定义的。
2、定义属性:页面把数据传递给组件使用,如info
3、定义组件触发父级的绑定事件:组件可以触发任意的父级事件。通过triggerEvent方法触发,如onSmsValid,onCloseSms等。组件进行某种操作后,父级页面根据情况做下一步操作。
<!--短信验证码弹框-->
<verificode id="verificode" info="{{info}}" bind:onSmsValid="onSmsValid"
bind:onCloseSms="onCloseSms" wx:if="{{isShowSmsSend}}"></verificode> </view>
3.3组件初始化事件
组件和page不一样,没有onload时间,与之对应的attached,ready事件。
async ready () {
this.onGetVerificationCode();
}
attached事件
/*
*@description:初始化
*@date: 2019-12-19 16:02:24
*/
lifetimes () {
return {
attached () {
this.init();
wx.getSystemInfo({
success: (res) => {
this.setData({ pixelRatio: res.pixelRatio, windowWidth: res.windowWidth })
this.windowHeight = res.windowHeight;
}
})
}
}
}
4.0 通过组件的对外属性,外部可以改变内部私有属性。
组件内部
data () {
return {
paddingBottom: "0rpx",// 需要底部拉长的页面需要单独加padding
showDeadline: false, // 没有更多
toTop: false, // 返回顶部回顶部
showComfirmBox: false, // 显示弹窗
}
}
properties () {
let _this = this;
return {
opts: {
type: Object,
observer: function parseOpts (opts, oldOpts) {
/**
* 外部接收到opts的值,传递进来,
* 根据不同的需要进行不同的设置
* 判断opts.type,判断弹窗类型
* 其余则为内置的控件显示
*/
if (opts != null) {
switch (opts.type) {
case 'alert':
case 'toast':
case 'confirm':
case 'logistics':
ConfirmBox[opts.type](this, opts.content);
return;
default:
}
//把外部获取的属性存放在内部属性上
this.setData(opts);
}
}
},
}
}
这种方式可以把多个属性合并成一个外部属性,在外部可以局部改变某个属性,其他属性不影响。
//解决iphone X底部遮挡问题
getApp().globalData.iphoneBottom && _this.setData({
"BottomBtn.bottomCss": "isIPX",
opts: {
paddingBottom: "140rpx"
}
});
//这时候仅仅改变的是paddingBottom属性,其他showDeadline等属性不变。