queryui是我们在项目中沉淀的小程序组件库,汲取了jquery的一些特性,使小程序更易于开发(微信原生)
小程序demo
queryui中ui-item/ui-list/ui-tree这三个非常重要的组件,我们称之为超级组件,超级组件依据标准化的数据,产出标准化的结构,赋予其样式形成不同的组件,queryui的绝大部分组件均由超级组件构成。
超级组件ITEM
item组件为组件的最小单位
wxml
<ui-item item="{{config}}" />
js
Pager({
data: {
config: {
id: '',
...
}
}
})
属性
下列说明
‘S’代表String
'A'代表Array
'O'代表Object
'F'代表Function
'b'代表bind
'c'代表catch
| 名称 | 类型 | 说明 |
|---|---|---|
| id | S | 容器id |
| ?id | S | 实例名称 |
| title | S/O/A | 标题 |
| url | S | 链接 |
| type | O | 容器类型 |
| img | S/O/A | 定义图片 |
| itemClass | S | 样式类 |
| itemStyle | S | 内联样式 |
| attr | O | data-*属性 |
| body | A | 子容器 |
| footer | A | 子容器 |
| dot | A | 特殊子容器 |
| methods | O | 实例属性方法 |
| tap | S/F | b:tap |
| aim | S/F | c:tap |
| longtap | S/F | longtap |
| longpress | S/F | longpress |
| touchstart | S/F | touchstart |
| touchmove | S/F | touchmove |
| touchend | S/F | touchend |
| catchlongtap | S/F | c:tap |
| catchlongpress | S/F | c:longpress |
API
| 名称 | 说明 |
|---|---|
| show | 显示 |
| hide | 隐藏 |
| toggle | 切换显示隐藏 |
| getData | 当前数据 |
| attr | 当前data-*数据 |
| mount | 绑定id实例 |
| parent | 查找父级 |
| siblings | 查找兄弟 |
| addClass | 追加样式类 |
| hasClass | 是否有样式类 |
| removeClass | 删除样式类 |
| toggleClass | 切换样式类 |
| css | 设置内联样式 |
| update | 设置内联样式 |
| reset | 恢复初始值 |
| find | 查找子元素 |
| hooks | 钩子方法 |
使用说明
一个ITEM就是一个View
item组件会自动生成view包裹里面的内容
示例一
config = {
itemClass: 'boxer'
}
生成如下
<view class="boxer"></view>
示例二
config = {
title: '123'
itemClass: 'boxer'
}
生成如下
<view class="boxer">
<text>123</text>
</view>
示例三
config = {
title: '123'
itemClass: 'boxer',
aim: 'onAim?id=xxx' // aim为catch:tap的别名, tap为bind:tap的别名
}
生成如下
<view class="boxer" catch:tap="onAim?id=xxx">
<text>123</text>
</view>
示例四
config = {
title: '123'
itemClass: 'boxer',
aim: 'onAim?id=xxx', // aim为catch:tap的别名, tap为bind:tap的别名
body: [
{
title: 'sub-title-123',
itemClass: 'sub-boxer',
tap: 'onSubTap'
}
]
}
上例生成如下
<view class="boxer" catch:tap="onAim?id=xxx">
<text>123</text>
<view class='hbody'>
<ui-item>
<view class='sub-boxer' bind:tap="onSubTap">
<text>sub-title-123</text>
</view>
</ui-item>
</view>
</view>
设置item样式
item由view组件构建而成,样式被应用在view上
config = {
title: '标题',
itemClass: 'class-name', // view容器的样式类
itemStyle: 'color: red; font-size: 18px;' // view容器的内联样式
}
设置title
设置标题,段落
设置标题
config = {
itemClass: 'class-name', // view容器样式类
title: '标题',
}
定制标题样式
config = {
itemClass: 'class-name' // view容器样式类,作用于item容器view上
title: {
title: '标题',
itemClass: 'class-name-sub' // class-name-sub直接作用于标题的容器view上
},
}
标题组
config = {
itemClass: 'class-name' // view容器样式类,作用于item容器view上
title: [
'标题-1',
'标题-2'
]
}
定制标题组
config = {
itemClass: 'class-name' // view容器样式类,作用于item容器view上
title: [
{title: '标题', itemClass: 'title-caption'},
{title: '描述', itemClass: 'title-descript'},
]
}
嵌套item使用
config = {
itemClass: 'class-name',
title: { // title为object时,由item组件重新构建
title: '标题',
itemClass: 'class-name-sub'
},
}
// title由数组构建时
config = {
itemClass: 'class-name' // view容器样式类,作用于item容器view上
title: [
'标题', // text构建
{title: '标题', itemClass: 'title-caption'}, // 由item组件构建
{title: '描述', itemClass: 'title-descript'}, // 由item组件构建
]
}
设置超链
当设置url属性后,使用navigate来构建item组件
注意query和hash的区别,这里将hash转换为navigate的配置参数 url需要配合title一起使用
不支持extra-data参数
url与title组合,queryui内核会自动将其转化为navigator标签,可以用来做跳转链接
小程序内跳转链接
config = {
title: '跳转到B页'
url: '../demos/b'
}
带参数跳转
config = {
title: '跳转到B页'
url: '../demos/b?id=xxx&usr=yyy'
}
小程序间跳转
config = {
title: '标题',
url: '#target=miniProgram&app-id=xxx&path=???'
}
通过hash设置navigator的参数
config = {
title: '跳转到B页'
url: '../demos/b?id=xxx&usr=yyy#app-id=xxxx&hover-class=???'
}
注意:不能设置extra-data参数,只能够设置字符串/数字/布尔类型的参数
设置图片
通过img属性,我们可以为item添加图片、图片组
一般设置
config = {
img: '/images/xxx.jpg'
}
定制图片
config = {
itemClass: 'item-class', // 定制item的view容器样式类
img: {
src: '/images/xxx.jpg',
itemClass: 'img-class', // 为image指定独立的样式类名
mode: 'widthFix',
... // 更多原生images组件的参数配置
}
}
图片组
config = {
img: [
{src: '/images/xxx.jpg'},
{src: '/images/yyy.jpg'},
{src: '/images/zzz.jpg'},
]
}
配置data-*属性
设置attr属性
config = {
title: '标题',
attr: {
id: 'attr-id', // 作为data-id
more: '...' // 不会在wxml结构上显示
}
}
注意: 只有attr.id属性作为参数显示在wxml的结构上,其他属性可以通过实例方法instance.attr()获取
定义item事件
config = {
title: '标题',
tap(e, param, inst){ // tap=bind:tap, aim=catch:tap, 其他事件方法与官方一致
// param 在这里没有用到
console.log(inst) // inst为item组件本身实例
}
}
定义组件内方法
设置methods属性,可以定义组件内的方法
config = {
title: '标题',
tap: 'onTap?id=xxx&name=yyy',
methods: {
onTap(e, param, inst){
console.log(param) // {id: 'xxx', name: 'yyy'}
console.log(inst) // 为item实例本身
},
funName(){}, //实例api方法
funName1(){}, //实例api方法
}
}
获取实例
设置?id值,可以在Pager环境中取到ITEM实例
config = {
?id: 'item-uniq-id'
}
Pager({
onReady(){
let instance = this.getElementsById('item-uniq-id')
console.log(instance)
}
})
API方法说明
parent(param)
当item作为子集时可用,这里的父级必须是queryui的组件而不是原生组件
一个参数,String类型,可为空,为空时表示直接父级,当指定param时,会自动向上找寻样式类名为param的父级
siblings(param)
当item作为子集时可用,这里的父级必须是queryui的组件而不是原生组件
一个参数,String类型,可为空,为空时表示返回所有兄弟对象,当指定param时,会在已查找到的兄弟中匹配样式类为param的兄弟
addClass(param)
一个参数,String类型,添加样式类,可同时添加多个样式类,使用空格区隔
removeClass(param)
一个参数,String类型,移除样式类,可同时删除多个样式类,使用空格区隔
toggleClass(param)
一个参数,String类型,切换样式类,支持同时切换多个样式类,使用空格区隔
css(param)
一个参数,String类型,设置item容器的内联样式
update(param, cb)
两个参数,param为Object类型,cb为Function类型,直接更新item属性,queryui内部使用setData来更新
hooks
作为item实例的钩子方法集合,本事是一个实例,具有一下api方法
数据部分
-
setItem
存储数据到key -
getItem
取得key的数据 -
append
为key数据追加数据 -
delete
删除key数据 -
getInfo
获取说有数据存储的对象
方法部分
-
on
挂载方法到key,类似于jquery的on方法 -
one
挂载方法到key,只能被执行一次,之后被删除 -
once
挂载方法到key,该key有且只有一个挂载的方法,取决于最后挂载的方法 -
off
取消挂载在key上的方法,允许指定取消非匿名函数方法 -
emit
执行挂载到key的所有方法 -
fire
执行挂载到key的所有方法,之后清除所有该key下挂载的方法 -
clear
清空所有数据,方法,key
配置说明
定义查找实例id,容器id
config = {
?id: 'uniq-id',
id: 'container-id' //作为view容器的id
}
onReady(){
let $inst = this.getElementsById('uniq-id')
console.log($inst)
}
下面demo实例中直接使用$inst表示为item组件的实例名
定义查找作为子集的item实例-1
config = {
?id: 'father-uniq-id',
title: '标题',
body: [
{?id: 'sub-uniq-id', title: '子标题'}
]
}
onReady(){
let $subinst = this.getElementsById('sub-uniq-id')
console.log($subinst)
}
定义查找作为子集的item实例-2
config = {
?id: 'father-uniq-id',
title: '标题',
body: [
{?id: 'sub-uniq-id', title: '子标题', itemClass: 'sub-class-name'}
]
}
onReady(){
let $inst = this.getElementsById('father-uniq-id')
let $sub = $inst.find('.sub-class-name')
}
定义查找作为子集的item实例-3
config = {
?id: 'father-uniq-id',
title: '标题',
body: [
{?id: 'sub-uniq-id',id: 'xxx', title: '子标题', itemClass: 'sub-class-name'}
]
}
onReady(){
let $inst = this.getElementsById('father-uniq-id')
$inst.children.forEach(item=>{
let itemData = item.getData()
if (itemData.id === 'xxx') {
console.log(item)
}
})
}
type定义容器类型
通过设置type,item可以将容器类型定义为view和scroll-view两种类型
暂时type只支持定义scroll-view类型,其他类型view容器暂不支持
config = {
type: {
'is': 'scroll',
'scroll-y': true
... // 其他scroll-view的属性
}
}
制作一个简单的加载按钮
methods属性的使用
config = {
title: '点我loading',
tap: 'tapme',
itemClass: '.item-btn',
methods: {
tapme(e, param, inst){
if (!inst.hasClass('loading')) {
inst.update({title: '隐藏loading'})
} else {
inst.update({title: '点我loading'})
}
inst.toggleClass('loading')
}
}
}
加载按钮简化版
直接定义tap, aim(catchtap)方法
config = {
title: '点我loading',
itemClass: '.item-btn',
tap(e, param, inst){
if (!inst.hasClass('loading')) {
inst.update({title: '隐藏loading'})
} else {
inst.update({title: '点我loading'})
}
inst.toggleClass('loading')
}
}
使用body属性制作一个简单下拉框
使用body属性为item组件增加一组下拉菜单
该例中使用siblings方法操作兄弟集合
body属性类型为数组(Array)类型,该数组由item组件构成,且被包裹在className为hbody的view容器中,可以支持丰富的结构
config = {
title: '简单下拉框',
aim: 'tapdd', //弹开、关闭下拉菜单
body: [
{title: '下拉选项一', aim: 'tapop?bodyIndex=1'}, // 选中项
{title: '下拉选项二', aim: 'tapop?bodyIndex=2'},
{title: '下拉选项三', aim: 'tapop?bodyIndex=3'},
],
itemClass: 'item-dropdown',
methods: {
tapdd(e, param, inst){
inst.toggleClass('active')
},
tapop(e, param, inst){
Pager.alert('选择了:'+param.bodyIndex.toString())
inst.siblings().removeClass('selected') // 兄弟元素去除选中样式
inst.addClass('selected') // 当前元素增加选中样式
setTimeout(() => {
this.toggleClass('active')
}, 3000);
}
}
}
使用dot属性添加小红点
使用dot属性为item组件添加小红点
dot属性类型为数组(Array)类型,该数组由item组件构成,支持丰富的结构,dot属性与body和footer属性不同在于,dot的子元素没有包裹容器,item容器作为其第一级父级,当父级容器属性position:relative时,子元素可以在父级中随意定位
config = {
title: '♻︎',
itemClass: 'item-reddot' // 父级样式类
dot: [
{ title: 99, itemClass: 'reddot'} // 父级为item-reddot
],
}
update更新内容
使用update实例方法更新item组件的内容
onReady(){
$inst.udpate({
title: '新的标题'
})
$inst.udpate({
img: 'a image path'
})
$inst.udpate({
body: [ ... ]
})
}
reset重置内容
使用实例方法reset使被修改过的当前实例恢复到修改之前的数据及状态
onReady(){
$inst.reset()
}
使用实例钩子(hooks)
组件间交互,可以通过钩子来触发更改状态,hooks必须在有实例的状态下定义
wxml
<ui-item item="{config1}" />
<ui-item item="{config2}" />
js
config1 = { ?id: 'id-1' }
config2 = { ?id: 'id-2', tap: 'onTap' }
Pager({
onTap(e, param, inst){
// param和inst由queryui内部传递
// 这里的inst === $inst2
// 参数option为key-name方法的参数,
// 参数context为key-name方法的上下文
$inst1.emit('key-name', option, context)
},
onReady(){
const $inst1 = this.getElementsById('id-1')
const $inst2 = this.getElementsById('id-2')
$inst1.hooks.on('key-name', function(option){
$inst1.update({title: '新标题'})
})
}
})
补充说明
methods的__ready方法
method用于定义item组件的内部方法,__ready方法比较特殊,会在组件mounted后自动执行
config = {
title: '标题',
methods: {
__ready(){
console.log('===== 0000')
}
}
}
事件穿透
item组件在queryui中是最小组件,经常被作为子组件使用,组件层次有时候会非常深,queryui的内核会将深层item组件的事件方法一层一层透传到page层,可在父级拦截事件,如果不设拦截方法则page层设置的方法将响应事件
借用react-fiber的图片,在queryui中父子之间的关系也是如图所示
在queryui中,我们使用Pager替代Page来使用,Pager方法是Page的封装,使用方法完全一致,但包含了queryui组件的上下文环境
config = { // 第一层
title: '标题',
body: [ // 第二层
{title: [ // 第三层
{?id: 'three-level-item', title: '第三层item组件', aim: 'onTap'},
{?id: 'three-level-item', title: '第三层item组件', aim: 'myTap'}
]}
],
methods: {
myTap(){
// 父级劫持了其子组件方法
}
}
}
Pager({
data: {
config: config
},
onTap(){
// 子组件方法被透传到page层中
}
})
自定义排序
配置支持图文排序,通过指定属性的顺序渲染结构,如下例
{title, img}
{img, title}
上述将渲染为文-图、图-文两种不同的结构
// 复杂一点,更多属性
{img, body, title, footer},
{body, img, footer, title}
最终渲染结构顺序,取决于属性在定义时的位置顺序