>

这是三个零器件,营造自身的UI库

- 编辑:至尊游戏网站 -

这是三个零器件,营造自身的UI库

微信小程序开采04-构建自身的UI库

2018/08/04 · 底工本领 · 小程序

原稿出处: 叶小钗   

Wechat小程序开拓03-那是五个构件

2018/08/02 · 根底能力 · 小程序

原来的书文出处: 叶小钗   

前言

github地址:

接上文继续,大家后面学习了小程序的生命周期、小程序的竹签、小程序的体裁,后边大家写了叁个简易的loading组件,明显她是个半成品,我们在做loading组件的时候发掘到二个主题素材:

小程序的零部件事实上是标签 大家平昔不办法获得标签的实例,起码作者暂风尚未章程所以那么些前提让我们对标签的认知有非常的大的差别,完毕小程序特有的UI库,那么就须要从标签出发 那其间关怀的点从js中的实例形成了wxml中的属性

1
2
3
4
小程序的组件事实上是标签
我们没有办法获得标签的实例,至少我暂时没有办法
所以这些前提让我们对标签的认识有很大的不同,完成小程序特有的UI库,那么就需要从标签出发
这里面关注的点从js中的实例变成了wxml中的属性

我们今日尝试做几个零件,然后先做未成功的loading,然后做信息类弹出组件,然后做日历组件,作者愿目的在于这一个进程中,我们形成生龙活虎套可用的系列,这里涉及了组件体系,大家可能需求整治下流程:

① 首先我们这边做的构件其实是“标签”,这时候将在思谋引进时候的怎么管理了

② 因为写作业页面包车型客车同事(写page的同事卡塔 尔(阿拉伯语:قطر‎,供给在json配置中引进必要动用的价签:

"usingComponents": { "ui-loading": "/components/ui-loading" }

1
2
3
"usingComponents": {
  "ui-loading": "/components/ui-loading"
}

因为无法动态插入标签,所以供给一方始就把标签归入页面wxml中:

<ui-loading is-show="{{isLoadingShow}}"></ui-loading>

1
<ui-loading is-show="{{isLoadingShow}}"></ui-loading>

③ json中的配置一时半刻只能拷贝,不过我们能够提供多个ui-set.wxml来动态引进一些组件,如全局使用的loading弹出类提醒框

④ 像日历类组件恐怕日常用的比比较少的弹出层组件便要求自身在页面中引进了,事业量貌似十分的小,后续看看动静,如何优化

⑤ 我们那边给各种组件设置三个behaviors,behaviors原则只设置黄金年代层(这里有一点点世袭的关系卡塔尔,层级多了变比较复杂了,弹出层类是一个、日常类一个(用于日历类组件卡塔尔国

有了上述专门的职业,大家这里先来改换我们的loading组件

⑥ 私下认可全部的构件前期WXSS直接设置为走避

编写组件

改造loading

这里首先更换掸出层都要三回九转的behaviors behavior-layer:

const util = require('../utils/util.js') module.exports = Behavior({ properties: { //首要属性,各种组件必带,定义组件是或不是出示 isShow: { type: String } }, //这里设置弹出层必需带有多少个蒙蔽层,所以每一个弹出层都自然有着有个z-index属性 data: { maskzIndex: util.getBiggerzIndex(), uiIndex: util.getBiggerzIndex() }, attached: function() { console.log('layer') }, methods: { } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const util = require('../utils/util.js')
module.exports = Behavior({
  properties: {
    //重要属性,每个组件必带,定义组件是否显示
    isShow: {
      type: String
    }
  },
  //这里设置弹出层必须带有一个遮盖层,所以每个弹出层都一定具有有个z-index属性
  data: {
    maskzIndex: util.getBiggerzIndex(),
    uiIndex: util.getBiggerzIndex()
  },
  attached: function() {
    console.log('layer')
  },
  methods: {
  }
})

说不上大家退换下大家的mask组件:

let LayerView = require('behavior-layer') Component({ behaviors: [LayerView], properties: { //唯有mask的z-index属性需求被调用的弹出层动态设置 zIndex: { type: String } }, data: { }, attached: function () { console.log('mask') }, methods: { onTap: function() { this.trigger伊夫nt('customevent', {}, {}) } } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let LayerView = require('behavior-layer')
Component({
  behaviors: [LayerView],
  properties: {
    //只有mask的z-index属性需要被调用的弹出层动态设置
    zIndex: {
      type: String
    }
  },
  data: {
  },
  attached: function () {
    console.log('mask')
  },
  methods: {
    onTap: function() {
      this.triggerEvent('customevent', {}, {})
    }
  }
})

WXML不做更动,便一蹴即至了大家的代码,并且协会关系就像是尤其清晰了,不过作为loading组件其实是有个难题的,举个例子点击隐瞒层要不要关张全数组件,像雷同这种点击掩盖层要不要关门全部组件,其实该是三个集体属性,所以大家对大家的layer、mask继续扩充改换(这里具体请看github代码卡塔尔:

const util = require('../utils/util.js') module.exports = Behavior({ properties: { //主要属性,各种组件必带,定义组件是或不是出示 isShow: { type: String } }, //这里设置弹出层必得含有叁个遮掩层,所以每一种弹出层都一定有着有个z-index属性 data: { maskzIndex: util.getBiggerzIndex(), uiIndex: util.getBiggerzIndex(), //默许点击掩盖层不关门组件 clickToHide: false }, attached: function() { console.log('layer') }, methods: { } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const util = require('../utils/util.js')
module.exports = Behavior({
  properties: {
    //重要属性,每个组件必带,定义组件是否显示
    isShow: {
      type: String
    }
  },
  //这里设置弹出层必须带有一个遮盖层,所以每个弹出层都一定具有有个z-index属性
  data: {
    maskzIndex: util.getBiggerzIndex(),
    uiIndex: util.getBiggerzIndex(),
    //默认点击遮盖层不关闭组件
    clickToHide: false
  },
  attached: function() {
    console.log('layer')
  },
  methods: {
  }
})

methods: { onMaskEvent: function (e) { console.log(e); //假若设置了点击隐瞒层关闭组件则关闭 if (this.data.clickToHide) this.setData({ isShow: 'none' }); } }

1
2
3
4
5
6
7
8
9
10
methods: {
  onMaskEvent: function (e) {
    console.log(e);
    //如果设置了点击遮盖层关闭组件则关闭
    if (this.data.clickToHide)
      this.setData({
        isShow: 'none'
      });
  }
}

其不时候,点击要不要关张,基本就在组件里面安装二个性能就可以,可是大家以此作为了个中属性,未有自由出去,这时我们兴许发掘了别的贰个相比有趣的光景了:

咱俩因为没办法获取多少个标签的实例,所以大家供给在页面里面动态调用:

onShow: function() { let scope= this; this.setData({ isLoadingShow: '' }); //3秒后关门loading setTimeout(function () { scope.setData({ isLoadingShow: 'none' }); }, 3000); },

1
2
3
4
5
6
7
8
9
10
11
12
onShow: function() {
  let scope= this;
  this.setData({
    isLoadingShow: ''
  });
  //3秒后关闭loading
  setTimeout(function () {
    scope.setData({
      isLoadingShow: 'none'
    });
  }, 3000);
},

能够见见,标签接入到页面后,调节标签事实上是动态操作他的性质,也正是说操作页面包车型地铁场馆数据,页面包车型地铁UI变化所有是数额触发,那样的逻辑会让分界面变得黑白分明,但是作为全局类的loading这种参数,笔者并不想放到各样页面中,因为如此会招致众多种复代码,于是作者在utils目录中新建了二个ui-util的工具类,作为一些大局类的ui公共库:

//因为小程序页面中各类页面应该是单独的效果域 class UIUtil { constructor(opts) { //用于存款和储蓄各样暗许ui属性 this.isLoadingShow = 'none'; } //产出页面loading必要的参数 getPageData() { return { isLoadingShow: this.isLoadingShow } } //须求传入page实例 showLoading(page) { this.isLoadingShow = ''; page.setData({ isLoadingShow: this.isLoadingShow }); } //关闭loading hideLoading(page) { this.isLoadingShow = 'none'; page.setData({ isLoadingShow: this.isLoadingShow }); } } //间接再次来到二个UI工具了类的实例 module.exports = new UIUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//因为小程序页面中每个页面应该是独立的作用域
class UIUtil {
  constructor(opts) {
    //用于存储各种默认ui属性
    this.isLoadingShow = 'none';
  }
  //产出页面loading需要的参数
  getPageData() {
    return {
      isLoadingShow: this.isLoadingShow
    }
  }
  //需要传入page实例
  showLoading(page) {
    this.isLoadingShow = '';
    page.setData({
      isLoadingShow: this.isLoadingShow
    });
  }
  //关闭loading
  hideLoading(page) {
    this.isLoadingShow = 'none';
    page.setData({
      isLoadingShow: this.isLoadingShow
    });
  }
}
 
//直接返回一个UI工具了类的实例
module.exports = new UIUtil

index.js使用上发出一些改动:

//获取公共ui操作类实例 const uiUtil = require('../../utils/ui-util.js'); //获取使用实例 const app = getApp() Page({ data: uiUtil.getPageData(), onShow: function() { let scope= this; uiUtil.showLoading(this); //3秒后关门loading set提姆eout(function () { uiUtil.hideLoading(scope); }, 3000); }, onLoad: function () { } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//获取公共ui操作类实例
const uiUtil = require('../../utils/ui-util.js');
//获取应用实例
const app = getApp()
Page({
  data: uiUtil.getPageData(),
  onShow: function() {
    let scope= this;
    uiUtil.showLoading(this);
    //3秒后关闭loading
    setTimeout(function () {
      uiUtil.hideLoading(scope);
    }, 3000);
  },
  onLoad: function () {
  }
})

像这种类型,大家将页面里面要用以操作组件的数额总体放松权利了多个util类中,那样代码会变得胸有成竹一些,组件管理也置于了三个地方,只是命名标准一定要安规则来,就像到此地,我们的loading组件改革终结了,这里却有多个主题材料,大家在ui-util类中贮存的实在是页面级的多寡,在那之中饱含是组件的图景,可是真实意况大家点击掩没层关闭组件,根本不会通报page层的数目,这时候大家loading的来得状态搞不佳是呈现,而真正的零件已经关闭了,如何确认保障状态统风姿浪漫大家后边点再说,作者近日尚未想到好的方式。

主干组织

接上文:Wechat小程序开辟02-小程序基本介绍

大家今天先来兑现那么些弹出层:

图片 1

前边这一个组件是三个器皿类组件,弹出层可设置载入的html结构,然后再安装各类风云就能够,这种组件有二个特色:

① 只提供Header部分以至容器部分

② 容器部分的HTML结构由业务层提供

③ 容器部分对应样式由业务层提供

小编们假如要在小程序中贯彻那类组件,意味着大家须求往小程序中动态插入WXML结构,大家这里先做个demo,试试往动态插入WXML是否立竿见影

this.setData({'wxml': ` <my-component> <view>动态插入的节点</view> </my-component> `});

1
2
3
4
5
this.setData({'wxml': `
  <my-component>
  <view>动态插入的节点</view>
  </my-component>
`});

图片 2

小程序对应安装的数据开展了转义,所以并不可能动态拆解分析,假设站在品质角度出主意,不开展动态分析亦非错误的;其他方面,大器晚成旦小程序能动态深入分析wxml,那么大概会自可是然各个草式用法,调整力会下降,那么我们这里怎么减轻这么些难题吧?

自身想的是,直接将业务级wxml结构放到页面里面,掩盖起来,需要使用弹出层的时候,直接将之装载进去,我们来会见是还是不是有效,大家将我们供给体现的组织放到叁个模板当中:

<template name="searchbox"> <my-component> <view>动态组件部分</view> </my-component> </template>

1
2
3
4
5
<template name="searchbox">
  <my-component>
      <view>动态组件部分</view>
  </my-component>
</template>

然后,大家在大家主分界面中载入模板:

<import src="mod.searchbox.wxml"/> <view> <my-component> <!-- 那大器晚成都部队分剧情将被停放在组件 <slot> 之处上 --> <view>这里是插入到零器件slot中的内容</view> </my-component> </view> <view> <template is="searchbox" /> </view>

1
2
3
4
5
6
7
8
9
10
<import src="mod.searchbox.wxml"/>
<view>
   <my-component>
     <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
      <view>这里是插入到组件slot中的内容</view>
   </my-component>
</view>
<view>
   <template is="searchbox" />
</view>

图片 3

注重结构放到页面中,大家传入数据模型也许决定显示就可以,看起来是平价的,于是我们先达成我们基本的体裁,因为事情模块的标准应该由职业提供,所以对应样式写到index.wxss里面:

.btn-primary { background-color: #00b358; color: #fff; border: 0 none; } .btn, .btn-primary, .btn-secondary, .btn-sub { line-height: 88rpx; height: 88rpx; padding: 0 20rpx; display: inline-block; vertical-align: middle; text-align: center; border-radius: 8rpx; cursor: pointer; font-size: 32rpx; -webkit-box-sizing: border-box; box-sizing: border-box; } .full-width { width: 100%; -webkit-box-sizing: border-box; box-sizing: border-box; } .c-row { width: auto; display: -webkit-box; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -webkit-box-pack: justify; -webkit-box-align: stretch; -webkit-box-lines: single; display: -webkit-flex; -webkit-flex-direction: row; -webkit-justify-content: space-between; -webkit-align-items: strecth; -webkit-align-content: flex-start; -webkit-flex-wrap: nowrap; padding: 20rpx 40rpx; } .c-span3 { width: 25%; -webkit-box-flex: 3; -webkit-flex: 3 3 auto; } .c-span9 { width: 75%; -webkit-box-flex: 9; -webkit-flex: 9 9 auto; } .search-line { position: relative; height: 96rpx; line-height: 96rpx; font-size: 30rpx; font-weight: 600; border-bottom: 1rpx solid #e6e6e6; } .search-line::after { content: ""; display: inline-block; vertical-align: middle; width: 20rpx; height: 20rpx; border-top: 4rpx solid #00b358; border-right: 4rpx solid #00b358; position: absolute; right: 60rpx; top: 50%; margin-top: -4rpx; -webkit-transform: rotate(45deg) translateY(-50%); transform: rotate(45deg) translateY(-50%); -webkit-box-sizing: border-box; box-sizing: border-box; } .search-line-txt { text-align: right; padding-right: 60rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
.btn-primary {
    background-color: #00b358;
    color: #fff;
    border: 0 none;
}
.btn, .btn-primary, .btn-secondary, .btn-sub {
    line-height: 88rpx;
    height: 88rpx;
    padding: 0 20rpx;
    display: inline-block;
    vertical-align: middle;
    text-align: center;
    border-radius: 8rpx;
    cursor: pointer;
    font-size: 32rpx;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
.full-width {
    width: 100%;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
 
 
.c-row {
    width: auto;
    display: -webkit-box;
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
    -webkit-box-pack: justify;
    -webkit-box-align: stretch;
    -webkit-box-lines: single;
    display: -webkit-flex;
    -webkit-flex-direction: row;
    -webkit-justify-content: space-between;
    -webkit-align-items: strecth;
    -webkit-align-content: flex-start;
    -webkit-flex-wrap: nowrap;
    padding: 20rpx 40rpx;
}
 
.c-span3 {
    width: 25%;
    -webkit-box-flex: 3;
    -webkit-flex: 3 3 auto;
}
 
.c-span9 {
    width: 75%;
    -webkit-box-flex: 9;
    -webkit-flex: 9 9 auto;
}
 
.search-line {
    position: relative;
    height: 96rpx;
    line-height: 96rpx;
    font-size: 30rpx;
    font-weight: 600;
    border-bottom: 1rpx solid #e6e6e6;
}
 
.search-line::after {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 20rpx;
    height: 20rpx;
    border-top: 4rpx solid #00b358;
    border-right: 4rpx solid #00b358;
    position: absolute;
    right: 60rpx;
    top: 50%;
    margin-top: -4rpx;
    -webkit-transform: rotate(45deg) translateY(-50%);
    transform: rotate(45deg) translateY(-50%);
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
 
.search-line-txt {
    text-align: right;
    padding-right: 60rpx;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

<template name="searchbox"> <view class="c-row search-line" data-flag="start"> <view class="c-span3"> 出发</view> <view class="c-span9 js-start search-line-txt"> 请选拔出发地</view> </view> <view class="c-row search-line" data-flag="arrive"> <view class="c-span3"> 达到</view> <view class="c-span9 js-arrive search-line-txt"> 请选用到达地</view> </view> <view class="c-row " data-flag="arrive"> <span class="btn-primary full-width js_search_list">查询</span> </view> </template>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template name="searchbox">
  <view class="c-row search-line" data-flag="start">
      <view class="c-span3">
          出发</view>
      <view class="c-span9 js-start search-line-txt">
          请选择出发地</view>
  </view>
  <view class="c-row search-line" data-flag="arrive">
      <view class="c-span3">
          到达</view>
      <view class="c-span9 js-arrive search-line-txt">
          请选择到达地</view>
  </view>
  <view class="c-row " data-flag="arrive">
      <span class="btn-primary full-width js_search_list">查询</span>
  </view>
</template>

图片 4

如此一来,我们着力的弹出层样式就七七八八了,这里可以看来有个别表征:小程序与一直大家的体裁差别一点都不大,稍微改点就能够用,以至能一向通用;另一面,大家也急需考虑一个主题素材:公共部分的CSS该怎么管理?其实笔者这边须求消弭的不只是集体的样式部分,还索要化解国有的机件部分。

自己这里想的是将享有国有部分的CSS放到二个大局的文本global.wxss中,然后在每一种业务级页面import就能够,所以大家这里供给产生贰个国有的WXSS库,这几个与纯web映射起来就可以,大家这里便不深远。

toast组件

我们未来先接二连三作toast组件,toast组件同样包括四个掩没层,然则点击的时候可以关闭隐讳层,展现3秒后关门,呈现多久关闭的属性应该是足以安顿的(作为质量传递卡塔 尔(阿拉伯语:قطر‎,所以大家新增加组件:

图片 5

const util = require('../utils/util.js'); let LayerView = require('behavior-layer'); Component({ behaviors: [ LayerView ], properties: { message: { type: String } }, data: { }, attached: function () { console.log(this) }, methods: { onMask伊夫nt: function (e) { console.log(e); //假设设置了点击隐讳层关闭组件则关闭 if (this.data.clickToHide) this.setData({ isShow: 'none' }); } } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const util = require('../utils/util.js');
let LayerView = require('behavior-layer');
 
Component({
  behaviors: [
    LayerView
  ],
  properties: {
    message: {
      type: String
    }
  },
  data: {
  },
  attached: function () {
    console.log(this)
  },
  methods: {
    onMaskEvent: function (e) {
      console.log(e);
      //如果设置了点击遮盖层关闭组件则关闭
      if (this.data.clickToHide)
        this.setData({
          isShow: 'none'
        });
    }
  }
})

图片 6

完整代码请各位在git上边去看,这里也唤起了有的题材:

① 笔者的组件如何居中?

② 平时的话toast消失的时候是能够定制化二个事变回调的,我们那边怎么落实?

此地我们先抛开居中难点,大家先来解决第四个难题,因为小程序中从不add伊夫ntListener这一个法子,所以可以纠正组件性情的法子只剩余多少操作,回想大家这里能够唤起组件掩瞒的点唯有:

① toast中的点击弹出层时改动呈现属性

onMaskEvent: function (e) { console.log(e); //假若设置了点击蒙蔽层关闭组件则关闭 if (this.data.clickToHide) this.setData({ isShow: 'none' }); }

1
2
3
4
5
6
7
8
onMaskEvent: function (e) {
  console.log(e);
  //如果设置了点击遮盖层关闭组件则关闭
  if (this.data.clickToHide)
    this.setData({
      isShow: 'none'
    });
}

② 然后正是页面中动态校勘多少属性了:

onShow: function() { let scope= this; uiUtil.showToast(this, '我是雅观动人的toast'); //3秒后关门loading setTimeout(function () { uiUtil.hideToast(scope); }, 3000); },

1
2
3
4
5
6
7
8
onShow: function() {
  let scope= this;
  uiUtil.showToast(this, '我是美丽可爱的toast');
  //3秒后关闭loading
  setTimeout(function () {
    uiUtil.hideToast(scope);
  }, 3000);
},

此间,大家只能管理从前的数目同步难题了,大家应当给toast提供二个平地风波性质可定义的点,点击遮掩层的实在管理逻辑要求停放page层,其实认真动脑筋下,标签就活该很纯粹,不该与专门的工作相关,只要求提供钩子,与作业有关的是page中的业务,此时大家能够见到大家代码之间的涉及是何其的纷纷了:

① 页面index.js依赖于index.wxml中组件的竹签,并且信赖于uiUtil这么些工具类

② 单单多个toast组件(标签卡塔 尔(阿拉伯语:قطر‎便依靠了mask标签,一个工具栏,还会有功底的layer behavior

③ 因为不能够博得实例,所以组件直接通讯只可以通过标签的bindevent的做法,让情状变得更为奇怪

从今以后间看起来,调用情势也着实太复杂了,而这还仅仅是三个轻巧的零部件,这一个是否我们写法有标题吧?答案是!小编的思路依旧以在此之前做js的机件的笔触,但是小程序暂且不扶持动态插入标签,所以我们不该有过多的持续关系,此中的mask是尚未供给的;另一方面,每一种页面要动态引进ui-utils那一个莫名其妙的构件库,如同也很别扭,所以大家这里准备开展改换,裁减不供给的复杂度

公家组件库

要拉长开垦功用的第二个前提正是要有丰裕多的UI组件,小程序本人提供了某个定制化的零器件,大家依然会用到的机件有:

① alert类弹出层

② loading类弹出层

③ 日历组件

④ toast&message类提示弹出组件

⑤ 容器类组件

⑥ ……

事先的做法,是大家将html实体和零器件达成直接放到一齐,css放到大局global里面去,未来小程序并不扶持动态体现wxml,所以动态插入的艺术行不通了,大家必要将零零件的wxml放到页面里面做预加载,这里本人想的是提供贰个通用global.ui.wxml文件用以装载全体的wxml实体,常用的零部件我们暗中认可全局引进,大家这里先挑点软红嘟嘟来捏,大家先达成四个alert类弹出层组件。

咱俩将原先弹出层类会用到的CSS全体翻译为WXSS,放入global.wxss中:

图片 7

接下来我们每一种组件都会有三个原则性的生命周期:创立->呈现->隐蔽,那个生命周期是各种组件都有着的表征,所以我们这里应该引进继承概念完结组件,不过小程序合法提供的Components并未提供后续概念,而是提供了behaviors概念,用以将构件间的共用部分管理掉,所以大家这里也应用behaviors,因为无法操作dom,大家的组件抽象会变得相对简便易行,不用记录太多dom节点了,其余小程序的零零器件与大家事先的“组件”从概念到应用上有十分大的不一致,以前我们是以js作为调控器,未来是以标签wxml作为调节器,根本未有章程在js中获得实例,而小程序组件的生命周期并不包涵展现隐瞒生命周期,所以他的零部件和我们感到的组件有非常大的不等

自己探究了下何以小程序中,js不可能获取组件的实例,这里得出的结论是:

小程序中装有的WXML必得在页面中张开预加载逻辑,不能动态插入DOM的章程插入WXML,所以小程序未有提供组件实例给大家决定 所以在小程序中想做到组件库,那么便只可以把组件做标签使用(并且是js不能拿到的价签卡塔 尔(英语:State of Qatar),并不是js组件,那样会卓有作用帮助我们理解

1
2
小程序中所有的WXML必须在页面中进行预加载逻辑,不能动态插入DOM的方式插入WXML,所以小程序没有提供组件实例给我们控制
所以在小程序中想完成组件库,那么便只能把组件做标签使用(而且是js不能获取的标签),而不是js组件,这样会有效帮助我们理解

我们那边品尝达成一个掩没层的竹签(这里起初不用组件这一个词,以为很有歧义卡塔 尔(英语:State of Qatar):

图片 8

代码十分轻松:

<view class="cm-overlay"></view>

1
<view class="cm-overlay"></view>

.cm-overlay { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; }

1
2
3
4
5
6
7
8
.cm-overlay {
    background: rgba(0, 0, 0, 0.5);
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

let LayerView = require('behavior-layer-view') Component({ behaviors: [LayerView], data: { myData: {} }, attached: function () { }, methods: { } })

1
2
3
4
5
6
7
8
9
10
11
12
let LayerView = require('behavior-layer-view')
 
Component({
  behaviors: [LayerView],
 
  data: {
    myData: {}
  },
  attached: function () { },
  methods: {
  }
})

能够看出,那一个掩盖层mask没有怎么意义,何况貌似的话mask也不会单独存在,平日是三个构件(举个例子弹出层的loading卡塔尔会含有一个遮掩层,所以大家这里要改换下Mask的构造,让他得以装载组件,大家从js组件逻辑来讲是mask应该是loading的叁个实例,但是我们站在标签角度来说,他们八个应该是独立的:

<view class="cm-overlay"> <slot></slot> </view>

1
2
3
<view class="cm-overlay">
  <slot></slot>
</view>

大家那边落成一个loading的组件(PS:CSS3动漫稍稍要做点协作调节和测量试验卡塔尔国:

图片 9

loading样式

.spinner { width: 140rpx; height: 140rpx; position: fixed; align-items: center; display: flex; top: 50%; left: 50%; margin-left: -70rpx; margin-top: -70rpx; } .container1 > view, .container2 > view, .container3 > view { width: 24rpx; height: 24rpx; background-color: #00b358; border-radius: 100%; position: absolute; -webkit-animation: bouncedelay 1.2s infinite ease-in-out; animation: bouncedelay 1.2s infinite ease-in-out; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .spinner .spinner-container { position: absolute; width: 66%; height: 66%; top: 10%; left: 10%; } .container2 { -webkit-transform: rotateZ(45deg); transform: rotateZ(45deg); } .container3 { -webkit-transform: rotateZ(90deg); transform: rotateZ(90deg); } .circle1 { top: 0; left: 0; } .circle2 { top: 0; right: 0; } .circle3 { right: 0; bottom: 0; } .circle4 { left: 0; bottom: 0; } .container2 .circle1 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .container3 .circle1 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } .container1 .circle2 { -webkit-animation-delay: -0.9s; animation-delay: -0.9s; } .container2 .circle2 { -webkit-animation-delay: -0.8s; animation-delay: -0.8s; } .container3 .circle2 { -webkit-animation-delay: -0.7s; animation-delay: -0.7s; } .container1 .circle3 { -webkit-animation-delay: -0.6s; animation-delay: -0.6s; } .container2 .circle3 { -webkit-animation-delay: -0.5s; animation-delay: -0.5s; } .container3 .circle3 { -webkit-animation-delay: -0.4s; animation-delay: -0.4s; } .container1 .circle4 { -webkit-animation-delay: -0.3s; animation-delay: -0.3s; } .container2 .circle4 { -webkit-animation-delay: -0.2s; animation-delay: -0.2s; } .container3 .circle4 { -webkit-animation-delay: -0.1s; animation-delay: -0.1s; } @-webkit-keyframes bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0.0) } 40% { -webkit-transform: scale(1.0) } } @keyframes bouncedelay { 0%, 80%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 40% { transform: scale(1.0); -webkit-transform: scale(1.0); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
.spinner {
  width: 140rpx;
  height: 140rpx;
  position: fixed;
  align-items: center;
  display: flex;
  top: 50%;
  left: 50%;
  margin-left: -70rpx;
  margin-top: -70rpx;
}
.container1 > view, .container2 > view, .container3 > view {
  width: 24rpx;
  height: 24rpx;
  background-color: #00b358;
  border-radius: 100%;
  position: absolute;
  -webkit-animation: bouncedelay 1.2s infinite ease-in-out;
  animation: bouncedelay 1.2s infinite ease-in-out;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.spinner .spinner-container {
  position: absolute;
  width: 66%;
  height: 66%;
  top: 10%;
  left: 10%;
}
.container2 {
  -webkit-transform: rotateZ(45deg);
  transform: rotateZ(45deg);
}
.container3 {
  -webkit-transform: rotateZ(90deg);
  transform: rotateZ(90deg);
}
.circle1 { top: 0; left: 0; }
.circle2 { top: 0; right: 0; }
.circle3 { right: 0; bottom: 0; }
.circle4 { left: 0; bottom: 0; }
.container2 .circle1 {
  -webkit-animation-delay: -1.1s;
  animation-delay: -1.1s;
}
.container3 .circle1 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}
.container1 .circle2 {
  -webkit-animation-delay: -0.9s;
  animation-delay: -0.9s;
}
.container2 .circle2 {
  -webkit-animation-delay: -0.8s;
  animation-delay: -0.8s;
}
.container3 .circle2 {
  -webkit-animation-delay: -0.7s;
  animation-delay: -0.7s;
}
.container1 .circle3 {
  -webkit-animation-delay: -0.6s;
  animation-delay: -0.6s;
}
.container2 .circle3 {
  -webkit-animation-delay: -0.5s;
  animation-delay: -0.5s;
}
.container3 .circle3 {
  -webkit-animation-delay: -0.4s;
  animation-delay: -0.4s;
}
.container1 .circle4 {
  -webkit-animation-delay: -0.3s;
  animation-delay: -0.3s;
}
.container2 .circle4 {
  -webkit-animation-delay: -0.2s;
  animation-delay: -0.2s;
}
.container3 .circle4 {
  -webkit-animation-delay: -0.1s;
  animation-delay: -0.1s;
}
 
@-webkit-keyframes bouncedelay {
  0%, 80%, 100% { -webkit-transform: scale(0.0) }
  40% { -webkit-transform: scale(1.0) }
}
@keyframes bouncedelay {
  0%, 80%, 100% {
    transform: scale(0.0);
    -webkit-transform: scale(0.0);
  } 40% {
    transform: scale(1.0);
    -webkit-transform: scale(1.0);
  }
}

<ui-mask z-index="{{maskzIndex}}" ></ui-mask> <view class="spinner" style="z-index: {{meIndex}}"> <view class="spinner-container container1"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> <view class="spinner-container container2"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> <view class="spinner-container container3"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> </view>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ui-mask z-index="{{maskzIndex}}" ></ui-mask>
<view class="spinner" style="z-index: {{meIndex}}">
  <view class="spinner-container container1">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
  <view class="spinner-container container2">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
  <view class="spinner-container container3">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
</view>

const util = require('../utils/util.js'); let LayerView = require('behavior-layer-view'); Component({ behaviors: [LayerView], data: { maskzIndex: util.getBiggerzIndex(), meIndex: util.getBiggerzIndex() }, attached: function () { console.log('loading') }, methods: { } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const util = require('../utils/util.js');
let LayerView = require('behavior-layer-view');
 
Component({
  behaviors: [LayerView],
 
  data: {
    maskzIndex: util.getBiggerzIndex(),
    meIndex: util.getBiggerzIndex()
  },
  attached: function () {
    console.log('loading')
  },
  methods: {
  }
})

index调用情状:

<import src="./mod.searchbox.wxml" /> <view> <template is="searchbox" /> <ui-loading></ui-loading> </view>

1
2
3
4
5
6
<import src="./mod.searchbox.wxml" />
 
<view>
  <template is="searchbox" />
  <ui-loading></ui-loading>
</view>

图片 10

咱俩继续将全体的品类代码放到github上去,这里便继续代码了

组件改变

透过寻思,大家这里筹划做以下优化(PS:小编小程序也是上星期最早读书的,须要逐步搜索卡塔尔:

① 保留mask组件,不过去除toast、loading类组件与其关联,将WXML以至体制直接内联,使用空间复杂度减弱代码复杂度

② 裁撤ui-uitil攻击类,转而达成叁个page基类

咱俩这边先重新实现toast组件:

//behavior-layer const util = require('../utils/util.js') module.exports = Behavior({ properties: { //首要属性,每一个组件必带,定义组件是或不是出示 isShow: { type: String } }, //这里设置弹出层必需带有三个隐瞒层,所以每种弹出层都必然有全部个z-index属性 data: { maskzIndex: util.getBiggerzIndex(), uiIndex: util.getBiggerzIndex(), //默许点击隐讳层不闭馆组件 clickToHide: true }, attached: function() { console.log('layer') }, methods: { onMask伊夫nt: function (e) { this.trigger伊芙nt('maskevent', e, {}) } } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//behavior-layer
const util = require('../utils/util.js')
module.exports = Behavior({
  properties: {
    //重要属性,每个组件必带,定义组件是否显示
    isShow: {
      type: String
    }
  },
  //这里设置弹出层必须带有一个遮盖层,所以每个弹出层都一定具有有个z-index属性
  data: {
    maskzIndex: util.getBiggerzIndex(),
    uiIndex: util.getBiggerzIndex(),
    //默认点击遮盖层不关闭组件
    clickToHide: true
  },
  attached: function() {
    console.log('layer')
  },
  methods: {
    onMaskEvent: function (e) {
      this.triggerEvent('maskevent', e, {})
    }
  }
})

 

.cm-overlay { background: rgba(0, 0, 0, 0.5); position: fixed; top: 0; right: 0; bottom: 0; left: 0; } .cm-modal { background-color: #fff; overflow: hidden; width: 100%; border-radius: 8rpx; } .cm-modal--toast { width: auto; margin-top: -38rpx; background: rgba(0, 0, 0, 0.7); color: #fff; padding: 20rpx 30rpx; text-align: center; font-size: 24rpx; white-space: nowrap; position: fixed; top: 50%; left: 50%; } .cm-modal--toast .icon-right { display: inline-block; margin: 10rpx 0 24rpx 10rpx; } .cm-modal--toast .icon-right::before { content: ""; display: block; width: 36rpx; height: 16rpx; border-bottom: 4rpx solid #fff; border-left: 4rpx solid #fff; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); -webkit-box-sizing: border-box; box-sizing: border-box; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.cm-overlay {
    background: rgba(0, 0, 0, 0.5);
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
 
.cm-modal {
  background-color: #fff;
  overflow: hidden;
  width: 100%;
  border-radius: 8rpx;
}
 
.cm-modal--toast {
  width: auto;
  margin-top: -38rpx;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: 20rpx 30rpx;
  text-align: center;
  font-size: 24rpx;
  white-space: nowrap;
  position: fixed;
  top: 50%;
  left: 50%;
 
}
.cm-modal--toast .icon-right {
  display: inline-block;
  margin: 10rpx 0 24rpx 10rpx;
}
.cm-modal--toast .icon-right::before {
  content: "";
  display: block;
  width: 36rpx;
  height: 16rpx;
  border-bottom: 4rpx solid #fff;
  border-left: 4rpx solid #fff;
  -webkit-transform: rotate(-45deg);
          transform: rotate(-45deg);
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
}

<section class="cm-modal cm-modal--toast" style="z-index: {{uiIndex}}; display: {{isShow}}; "> {{message}} </section> <view class="cm-overlay" bindtap="onMaskEvent" style="z-index: {{maskzIndex}}; display: {{isShow}}" > </view>

1
2
3
4
5
<section class="cm-modal cm-modal--toast" style="z-index: {{uiIndex}}; display: {{isShow}}; ">
  {{message}}
</section>
<view class="cm-overlay" bindtap="onMaskEvent" style="z-index: {{maskzIndex}}; display: {{isShow}}" >
</view>

const util = require('../utils/util.js'); let LayerView = require('behavior-layer'); Component({ behaviors: [ LayerView ], properties: { message: { type: String } }, data: { }, attached: function () { console.log(this) }, methods: { } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const util = require('../utils/util.js');
let LayerView = require('behavior-layer');
Component({
  behaviors: [
    LayerView
  ],
  properties: {
    message: {
      type: String
    }
  },
  data: {
  },
  attached: function () {
    console.log(this)
  },
  methods: {
  }
})

页面层的利用不必变化就早就焕然风度翩翩新了,那个时候我们伊始做ui-util与page关系的改建,看看能还是不可能让我们的代码变得轻易,作者这里的思绪是设计贰个国有的abstract-view出来,做有所页面的基类:

图片 11

class Page { constructor(opts) { //用于底子page存款和储蓄各类私下认可ui属性 this.isLoadingShow = 'none'; this.isToastShow = 'none'; this.toastMessage = 'toast提醒'; //通用方法列表配置,暂且约定用于点击 this.methodSet = [ 'onToastHide', 'showToast', 'hideToast', 'showLoading', 'hideLoading' ]; //当前page对象 this.page = null; } initPage(pageData) { //debugger; let _pageData = {}; //为页面动态增加操作组件的诀要 Object.assign(_pageData, this.getPageFuncs(), pageData); //生成真正的页面数据 _pageData.data = {}; Object.assign(_pageData.data, this.getPageData(), pageData.data || {}); console.log(_pageData); return _pageData; } //当关闭toast时接触的风云 onToastHide(e) { this.hideToast(); } //设置页面或然使用的不二秘诀 getPageFuncs() { let funcs = {}; for (let i = 0, len = this.methodSet.length; i < len; i++ ) { funcs[this.methodSet[i]] = this[this.methodSet[i]]; } return funcs; } //产出页面组件要求的参数 getPageData() { return { isLoadingShow: this.isLoadingShow, isToastShow: this.isToastShow, toastMessage: this.toastMessage } } showToast(message) { this.setData({ isToastShow: '', toastMessage: message }); } hideToast() { this.setData({ isToastShow: 'none' }); } //需求传入page实例 showLoading() { this.setData({ isLoadingShow: '' }); } //关闭loading hideLoading() { this.setData({ isLoadingShow: 'none' }); } } //间接重回三个UI工具了类的实例 module.exports = new Page abstract-view

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class Page {
    constructor(opts) {
        //用于基础page存储各种默认ui属性
        this.isLoadingShow = 'none';
        this.isToastShow = 'none';
        this.toastMessage = 'toast提示';
 
        //通用方法列表配置,暂时约定用于点击
        this.methodSet = [
            'onToastHide', 'showToast', 'hideToast', 'showLoading', 'hideLoading'
        ];
 
        //当前page对象
        this.page = null;
    }
    initPage(pageData) {
        //debugger;
 
        let _pageData = {};
 
        //为页面动态添加操作组件的方法
        Object.assign(_pageData, this.getPageFuncs(), pageData);
 
        //生成真实的页面数据
        _pageData.data = {};
        Object.assign(_pageData.data, this.getPageData(), pageData.data || {});
 
        console.log(_pageData);
        return _pageData;
    }
    //当关闭toast时触发的事件
    onToastHide(e) {
        this.hideToast();
    }
    //设置页面可能使用的方法
    getPageFuncs() {
        let funcs = {};
        for (let i = 0, len = this.methodSet.length; i < len; i++ ) {
            funcs[this.methodSet[i]] = this[this.methodSet[i]];
        }
        return funcs;
    }
    //产出页面组件需要的参数
    getPageData() {
        return {
            isLoadingShow: this.isLoadingShow,
            isToastShow: this.isToastShow,
            toastMessage: this.toastMessage
        }
    }
    showToast(message) {
        this.setData({
            isToastShow: '',
            toastMessage: message
        });
    }
    hideToast() {
        this.setData({
            isToastShow: 'none'
        });
    }
    //需要传入page实例
    showLoading() {
        this.setData({
            isLoadingShow: ''
        });
    }
    //关闭loading
    hideLoading() {
        this.setData({
            isLoadingShow: 'none'
        });
    }
}
//直接返回一个UI工具了类的实例
module.exports = new Page
 
abstract-view

此间还提供了贰个国有模板用于被页面include,abstract-view.wxml:

<ui-toast bindonToastHide="onToastHide" is-show="{{isToastShow}}" message="{{toastMessage}}"></ui-toast>

1
<ui-toast bindonToastHide="onToastHide" is-show="{{isToastShow}}" message="{{toastMessage}}"></ui-toast>

页面调用时候的代码产生了不小的变通:

<import src="./mod.searchbox.wxml" /> <view> <template is="searchbox" /> </view> <include src="../../utils/abstract-page.wxml"/>

1
2
3
4
5
<import src="./mod.searchbox.wxml" />
<view>
  <template is="searchbox" />
</view>
<include src="../../utils/abstract-page.wxml"/>

//获取公共ui操作类实例 const _page = require('../../utils/abstract-page.js'); //获取使用实例 const app = getApp() Page(_page.initPage({ data: { ttt: 'ttt' }, // methods: uiUtil.getPageMethods(), methods: { }, onShow: function () { let scope = this; this.showToast('小编是倾城倾国摄人心魄的toast'); // 3秒后关门loading // setTimeout(function () { // scope.hideToast(); // }, 3000); }, onLoad: function () { // this.setPageMethods(); } }))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//获取公共ui操作类实例
const _page = require('../../utils/abstract-page.js');
//获取应用实例
const app = getApp()
 
Page(_page.initPage({
  data: {
    ttt: 'ttt'
 
  },
  // methods: uiUtil.getPageMethods(),
  methods: {
  },
  onShow: function () {
     let scope = this;
     this.showToast('我是美丽可爱的toast');
     // 3秒后关闭loading
    //  setTimeout(function () {
    //    scope.hideToast();
    //  }, 3000);
  },
  onLoad: function () {
    // this.setPageMethods();
  }
}))

如此那般大家一定于变相给page赋能了,详细情形请各位看github上的代码:,那个时候,大家要为toast组件增加关闭时候的事件回调,就变得相对简便易行了,事实上大家能够看见这么些作为早已跟组件自身未有太多涉及了:

showToast(message, callback) { this.toastHideCallback = null; if (callback) this.toastHideCallback = callback; let scope = this; this.setData({ isToastShow: '', toastMessage: message }); // 3秒后关闭loading setTimeout(function () { scope.hideToast(); }, 3000); } hideToast() { this.setData({ isToastShow: 'none' }); if (this.toastHideCallback) this.toastHideCallback.call(this); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
showToast(message, callback) {
  this.toastHideCallback = null;
  if (callback) this.toastHideCallback = callback;
  let scope = this;
  this.setData({
    isToastShow: '',
    toastMessage: message
  });
 
  // 3秒后关闭loading
  setTimeout(function () {
    scope.hideToast();
  }, 3000);
}
hideToast() {
  this.setData({
    isToastShow: 'none'
  });
  if (this.toastHideCallback) this.toastHideCallback.call(this);
}

this.showToast('作者是天香国色摄人心魄的toast', function () { console.log('实施回调')} );

1
this.showToast('我是美丽可爱的toast', function () { console.log('执行回调')} );

理之当然这里能够做得更加的人性化,举例显示时间是根据message长度动态设置的,大家这里先这么。

加上事件

于是乎,大家最初加多事件了,这里足够三个点击掩瞒层关闭全部组件的效果与利益,这里有个难点是,大家点击隐瞒层事实上关闭的是覆盖以至loading四个标签,而小编辈这里的isShow属性便派上了用项,大家明天page中设置下属性:

<ui-loading is-show="{{isLoadingShow}}"></ui-loading>

1
<ui-loading is-show="{{isLoadingShow}}"></ui-loading>

onShow: function() { this.setData({ isLoadingShow: '' }); },

1
2
3
4
5
onShow: function() {
  this.setData({
    isLoadingShow: ''
  });
},

然后大家退换mask以至loading增加事件:

<view class="cm-overlay" style="z-index: {{zIndex}}; display: {{isShow}}" bindtap="onTap"> </view>

1
2
<view class="cm-overlay" style="z-index: {{zIndex}}; display: {{isShow}}" bindtap="onTap">
</view>

let LayerView = require('behavior-layer-view') Component({ behaviors: [LayerView], data: { myData: {} }, attached: function () { console.log('mask') }, methods: { onTap: function() { this.triggerEvent('customevent', {}, {}) } } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let LayerView = require('behavior-layer-view')
 
Component({
  behaviors: [LayerView],
 
  data: {
    myData: {}
  },
  attached: function () {
    console.log('mask')
  },
  methods: {
    onTap: function() {
      this.triggerEvent('customevent', {}, {})
    }
  }
})

<ui-mask z-index="{{maskzIndex}}" is-show="{{isShow}}" bindcustomevent="onMaskEvent"></ui-mask> <view class="spinner" style="z-index: {{meIndex}}; display: {{isShow}}; "> <view class="spinner-container container1"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> <view class="spinner-container container2"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> <view class="spinner-container container3"> <view class="circle1"></view> <view class="circle2"></view> <view class="circle3"></view> <view class="circle4"></view> </view> </view>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ui-mask z-index="{{maskzIndex}}" is-show="{{isShow}}" bindcustomevent="onMaskEvent"></ui-mask>
<view class="spinner" style="z-index: {{meIndex}}; display: {{isShow}}; ">
  <view class="spinner-container container1">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
  <view class="spinner-container container2">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
  <view class="spinner-container container3">
    <view class="circle1"></view>
    <view class="circle2"></view>
    <view class="circle3"></view>
    <view class="circle4"></view>
  </view>
</view>

const util = require('../utils/util.js'); let LayerView = require('behavior-layer-view'); Component({ behaviors: [LayerView], data: { maskzIndex: util.getBiggerzIndex(), meIndex: util.getBiggerzIndex() }, attached: function () { console.log('loading') }, methods: { onMaskEvent: function (e) { console.log(e); this.setData({ isShow: 'none' }); } } })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const util = require('../utils/util.js');
let LayerView = require('behavior-layer-view');
 
Component({
  behaviors: [LayerView],
 
  data: {
    maskzIndex: util.getBiggerzIndex(),
    meIndex: util.getBiggerzIndex()
  },
  attached: function () {
    console.log('loading')
  },
  methods: {
    onMaskEvent: function (e) {
      console.log(e);
      this.setData({
        isShow: 'none'
      });
    }
  }
})

其不经常候,当大家点击隐蔽层的时候,我们全体组件便百货店破产了。

alert类组件

本篇篇幅已经相比较长了,我们最后落成一个alert组件便甘休几天前的学习,今天重要完结日历等零部件,alert组件平常是三个带显著框的提醒弹出层,有相当的大希望有多个开关,这三个场地要多少复杂点,大家这里依旧为其新扩张组件结构wxml甚至wxss:

//获取公共ui操作类实例 const _page = require('../../utils/abstract-page.js'); //获取使用实例 const app = getApp() Page(_page.initPage({ data: { }, // methods: uiUtil.getPageMethods(), methods: { }, onShow: function () { global.sss = this; let scope = this; this.showMessage({ message: '作者是二个规定框', ok: { name: '明确', callback: function () { scope.hideMessage(); scope.showMessage('笔者选拔了规定'); } }, cancel: { name: '裁撤', callback: function () { scope.hideMessage(); scope.showToast('小编选拔了收回'); } } }); }, onLoad: function () { // this.setPageMethods(); } }))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//获取公共ui操作类实例
const _page = require('../../utils/abstract-page.js');
//获取应用实例
const app = getApp()
 
Page(_page.initPage({
  data: {
  },
  // methods: uiUtil.getPageMethods(),
  methods: {
  },
  onShow: function () {
    global.sss = this;
    let scope = this;
    this.showMessage({
      message: '我是一个确定框',
      ok: {
        name: '确定',
        callback: function () {
          scope.hideMessage();
          scope.showMessage('我选择了确定');
        }
      },
      cancel: {
        name: '取消',
        callback: function () {
          scope.hideMessage();
          scope.showToast('我选择了取消');
        }
      }
    });
 
  },
  onLoad: function () {
    // this.setPageMethods();
  }
}))

图片 12

图片 13

图片 14

总结

我们明天花了累累素养写多个loading,开掘小程序中的组件事实上是标签,大家没有办法使用js获取到我们“组件”的实例,所以接收上有超级大的界别,不过怎么着都不能够阻碍我们写通用组件的狠心,于是我们前几天来写一些通用的构件库,而且产生几个小程序的系列,这里想的是有:

① 消息框

② toast提示

③ 日历组件

④ 然后再做一个亟需稳固的气泡组件

1 赞 收藏 评论

图片 15

结语

github地址:

明日大家就像是找到了叁个合乎小程序的组件编写情势,前些天大家后续产生都部队分零器件,组件完毕后大家便初步写实际业务代码了

1 赞 收藏 评论

图片 16

本文由技术教程发布,转载请注明来源:这是三个零器件,营造自身的UI库