开发实战篇之八
前言
实战篇内容参考:
1、Lin Ui开源组件源码分析。https://doc.mini.talelin.com/
2、开发过程遇到问题。
1、list选择器组件
1.1 子组件—tag标签组件
1.1.1 tag的骨架文件wxml
<view style="display:flex">
<view class="x-tag {{type==='touch'?'x-tag-touch':''}} {{plain?'x-tag-plain-'+ size:'x-tag-'+size}} {{disable?'x-tag-disable':''}} {{select?'select x-select-class':'x-class'}} {{plain?'x-tag-plain':''}} {{'x-tag-'+size+'-'+ shape}}" style="{{height?'line-height:'+height+'rpx;height:'+height+'rpx;':''}}{{plain?'color:'+fontColor+';border-color:'+fontColor:'background-color:'+bgColor+';color:'+fontColor}}" mut-bind:tap="handleTap">
<view class="{{location==='left'?'content':'content-x'}}" style="{{iconName?'line-height:0':''}}">
<x-icon wx:if="{{icon}}" style="{{location==='left'?'margin-right:5rpx':'margin-left:5rpx'}}" name="{{icon}}" size="{{iconSize}}" color="{{iconColor}}"/>
<image style="{{location==='left'?'margin-right:5rpx':'margin-left:5rpx'}}" wx:if="{{image}}" src="{{image}}" class="{{'tag-image-'+size}} x-image-class"></image>
<slot/>
</view>
</view>
</view>
分析:
- 骨架文件主要是最外部一个
view
采用flex
布局; - 然后
view
作为整个标签的容器。可以设置该标签的type
类型;是否镂空plain
属性;是否禁用disable
;是否可以点击select
,与disable
的区别就是样式上还有参数名的不同;背景、字体的颜色、高度等; - 设置
mut-bind:tap
监听事件。表示互斥事件,与其他mut-bind:tap
函数不会同时响应。具体参考:互斥事件响应。 - 然后是一个
view
表示icon
组件容器。设置icon的类型、位置、颜色。
1.1.2 tag的js文件
import validator from "../behaviors/validator";
Component({
externalClasses: ["x-class", "x-select-class", "x-image-class"],
behaviors: [validator],
properties: {
// 标签传递内容 string
name: String,
// 标签传递内容为 object
cell: Object,
// 标签类型touch有最小宽度,reading宽度由文本长度决定
type: {
type: String,
value: "touch",
options: ["reading", "touch"]
},
bgColor: String,
fontColor: String,
disable: Boolean,
shape: {
type: String,
value: "square",
options: ["square", "circle"]
},
// 标签是否点击
select: Boolean,
// 标签是否镂空
plain: Boolean,
size: {
type: String,
value: "medium",
options: ["large", "medium", "mini", "super-mini"]
},
location: {
type: String,
value: "left",
options: ["left", "right"]
},
icon: String,
iconSize: {
type: String,
value: "20"
},
iconColor: {
type: String,
value: "#3683D6"
},
image: String,
iconStyle: {
type: String,
value: "size:20;color:#3683D6"
},
height: Number
},
methods: {
handleTap() {
// 禁用点击事件
if (this.data.disable) return;
let e = {
name: this.data.name,
cell: this.data.cell,
select: this.data.select
};
this.triggerEvent("tagtap", e, {
bubbles: !0,
composed: !0
})
}
}
});
2、list选择器wxml骨架文件
- list选择器主要功能是点击列表。主要由整体一个布局中,左侧布局、右侧布局组成。由于需要自定义的左右布局,因此将左右布局使用
template
来编写。可以进行复用。 - 其中主要包括
tag、badge、icon、image
组件。 - 包括一些外部样式、list组件的点击事件处理方法tapcell()。
(1)tag表示标记或选择的标签,体现为自定义可点击的颜色文本块。
(2)badge表示文字上方的提示标记。数字或是红点标记。
(3)icon即为图标。
<!--components/list/list.wxml-->
<view class="x-list x-class" hover-class="{{isHover?'x-list-hover':''}}" hover-start-time="20" hover-stay-time="50" style="{{gap?'padding:0 '+gap+'rpx;':''}} {{leftGap?'padding-left:'+leftGap+'rpx':''}} {{rightGap?'padding-right:'+rightGap+'rpx':''}}" mut-bind:tap="tapcell" data-url="{{url}}" data-link-type="{{linkType}}">
<!-- left -->
// 左侧文集徽标可选
<x-badge wx:if="{{(badgeCount > 0 || dotBadge ) && badgePosition ==='left'}}" value="{{badgeCount}}" dot="{{dotBadge}}" max-count="{{badgeMaxCount}}" number-type="{{badgeCountType}}">
<template is="cell-left-main" data="{{image,icon,title,desc,tagContent,tagPosition,tagColor,tagShape,tagPlain,iconSize,iconColor}}" />
</x-badge>
<template is="cell-left-main" data="{{image,icon,title,desc,tagContent,tagPosition,tagColor,tagShape,tagPlain,iconSize,iconColor}}" wx:else />
<!-- right -->
// 左侧文集徽标可选
<x-badge x-class="badge-right" wx:if="{{(badgeCount > 0 || dotBadge ) && badgePosition ==='right'}}" value="{{badgeCount}}" dot="{{dotBadge}}" max-count="{{badgeMaxCount}}" number-type="{{badgeCountType}}">
<template is="cell-right-main" data="{{rightDesc,tagContent,tagPosition,isLink,tagColor,tagShape,tagPlain}}" />
</x-badge>
<template is="cell-right-main" data="{{rightDesc,tagContent,tagPosition,isLink,tagColor,tagShape,tagPlain}}" wx:else />
</view>
// 左边布局的模板骨架文件
<template name="cell-left-main">
<view class="left-section ">
<image wx:if="{{image}}" class="x-image x-class-image x-image-class" src="{{image}}" mode="aspectFit|aspectFill|widthFix" />
<x-icon wx:elif="{{icon}}" x-class="x-icon x-class-icon x-icon-class" name="{{icon}}" size="{{iconSize}}" color="{{iconColor}}" />
<view class="x-text">
<view class="x-class-content x-content-class">{{title}}</view>
<view class="x-desc x-class-desc x-desc-class" wx:if="{{desc}}">{{desc}}</view>
</view>
<x-tag size="mini" shape="{{tagShape}}" bg-color="{{tagColor}}" x-class="cell-tag" wx:if="{{tagContent && tagPosition ==='left' && !tagPlain}}">{{tagContent}}</x-tag>
<x-tag size="mini" shape="{{tagShape}}" plain="{{tagPlain}}" font-color="{{tagColor}}" x-class="cell-tag" wx:elif="{{tagContent && tagPosition ==='left' && tagPlain}}">{{tagContent}}</x-tag>
<slot name="left-section"></slot>
</view>
</template>
// 右边布局的模板骨架文件
<template name="cell-right-main">
<view class="right-section x-class-right x-right-class">
<slot name="right-section"></slot>
<x-tag size="mini" shape="{{tagShape}}" bg-color="{{tagColor}}" x-class="cell-tag" wx:if="{{tagContent && tagPosition ==='right' && !tagPlain }}">{{tagContent}}</x-tag>
<x-tag size="mini" shape="{{tagShape}}" plain="{{tagPlain}}" font-color="{{tagColor}}" x-class="cell-tag" wx:if="{{tagContent && tagPosition ==='right' && tagPlain }}">{{tagContent}}</x-tag>
<view class="x-text" wx:if="{{rightDesc}}">{{rightDesc}}</view>
<x-icon x-class="x-link-icon-class" size="26" color="#8c98ae" name="right" wx:if="{{isLink}}" />
</view>
</template>
3、list选择器js代码
js代码主要是很多外部传入的properties
,以及列表点击事件处理tapcell
,点击之后跳转到指定的url
。
// components/list/list.js
import hover from '../behaviors/hover'
Component({
// 定义组件之间关系的,暂时用不到
relations: {
'../list/list': {
type: 'parent', // 关联的目标节点应为子节点
linked() {
// 每次有custom-li被插入时执行,target是该节点实例对象,触发在该节点attached生命周期之后
},
linkChanged() {
// 每次有custom-li被移动后执行,target是该节点实例对象,触发在该节点moved生命周期之后
},
unlinked() {
// 每次有custom-li被移除时执行,target是该节点实例对象,触发在该节点detached生命周期之后
}
}
},
options: {
multipleSlots: true
},
// 基本不使用外部样式
externalClasses: [
'x-class',
'x-class-icon',
'x-icon-class',
'x-class-image',
'x-image-class',
'x-class-right',
'x-right-class',
'x-class-content',
'x-content-class',
'x-class-desc',
'x-desc-class',
'x-link-icon-class'
],
/**
* 组件的属性列表
*/
properties: {
// 是否显示点击效果 默认开启
isHover: {
type: Boolean,
value: true
},
icon: String,
iconColor: {
// 默认橘色图标
type: String,
value: '#FFA020'
},
image: String,
// 定义该list标题
title: String,
// 定义底部的描述
desc: String,
tagPosition: {
type: String,
value: 'left'
},
tagContent: String,
tagShape: {
type: String,
value: 'square'
},
tagColor: String,
tagPlain: Boolean,
badgePosition: {
type: String,
value: 'left'
},
// 红点徽标
dotBadge: Boolean,
badgeCount: Number,
badgeMaxCount: {
type: Number,
value: 99
},
badgeCountType: {
type: String,
value: 'overflow'
},
// 右侧描述文本内容
rightDesc: String,
// 左右距离list两侧边界距离
gap: Number,
// 距离list边界左边距离
leftGap: Number,
rightGap: Number,
// 是否显示跳转图标
isLink: {
type: Boolean,
value: true,
},
// 跳转类型
linkType: {
type: String,
value: 'navigateTo'
},
// 跳转路径
url: String
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
tapcell: function (e) {
const {
linkType,
url
} = e.currentTarget.dataset;
if (url) {
wx[linkType]({
url
});
}
this.triggerEvent('listtap', {
e
}, { bubbles: true, composed: true });
}
}
})