小程序开发组件概述_小程序开发教程

小程序开发组件概述_小程序开发教程编写组件基本结构接上文:微信小程序开发02-小程序基本介绍我们今天先来实现这个弹出层:之前这个组件是一个容器类组件,弹出层可设置载入的html结构,然后再设置各种事件即可,这种组件有一个特点:

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

编写组件

基本结构

接上文:微信小程序开发02-小程序基本介绍

我们今天先来实现这个弹出层:

小程序开发组件概述_小程序开发教程

之前这个组件是一个容器类组件,弹出层可设置载入的html结构,然后再设置各种事件即可,这种组件有一个特点:

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

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

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

我们如果要在小程序中实现这类组件,意味着我们需要往小程序中动态插入WXML结构,我们这里先做个demo,试试往动态插入WXML是不是可行

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

小程序开发组件概述_小程序开发教程

小程序对应设置的数据进行了转义,所以并不能动态解析,如果站在性能角度思考,不进行动态解析也不是错误的;另一方面,一旦小程序能动态解析wxml,那么可能会涌出各种花式用法,控制力会减低,那么我们这里如何解决这个问题呢?

我想的是,直接将业务级wxml结构放到页面里面,隐藏起来,需要使用弹出层的时候,直接将之装载进去,我们来看看是否可行,我们将我们需要展示的结构放到一个模板当中:

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

然后,我们在我们主界面中载入模板:

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

小程序开发组件概述_小程序开发教程

主体结构放到页面中,我们传入数据模型或者控制显示即可,看起来是可行的,于是我们先实现我们基本的样式,因为业务模块的样子应该由业务提供,所以对应样式写到index.wxss里面:

小程序开发组件概述_小程序开发教程
小程序开发组件概述_小程序开发教程

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

View Code

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

小程序开发组件概述_小程序开发教程

如此一来,我们基本的弹出层样式就七七八八了,这里可以看出一些特点:小程序与平时我们的样式差距不大,稍微改点就能用,甚至能直接通用;另一方面,我们也需要思考一个问题:公共部分的CSS该怎么处理?其实我这里需要解决的不只是公共的样式部分,还需要解决公共的组件部分。

我这里想的是将所有公共部分的CSS放到一个全局的文件global.wxss中,然后在每个业务级页面import即可,所以我们这里需要形成一个公共的WXSS库,这个与纯web映射起来即可,我们这里便不深入。

公共组件库

要提高开发效率的第一个前提就是要有足够多的UI组件,小程序本身提供了一些定制化的组件,我们仍然会用到的组件有:

① alert类弹出层

② loading类弹出层

③ 日历组件

④ toast&message类提示弹出组件

⑤ 容器类组件

⑥ ……

之前的做法,是我们将html实体和组件实现直接放到一起,css放到全局global里面去,现在小程序并不支持动态展示wxml,所以动态插入的方式行不通了,我们需要将组件的wxml放到页面里面做预加载,这里我想的是提供一个通用global.ui.wxml文件用以装载所有的wxml实体,常用的组件我们默认全局引入,我们这里先挑点软柿子来捏,我们先实现一个alert类弹出层组件。

我们将原来弹出层类会用到的CSS全部翻译为WXSS,放入global.wxss中:

小程序开发组件概述_小程序开发教程

然后我们每个组件都会有一个固定的生命周期:创建->显示->隐藏,这个生命周期是每个组件都具有的特性,所以我们这里应该引入继承概念实现组件,但是小程序官方提供的Components并没有提供继承概念,而是提供了behaviors概念,用以将组件间的公共部分处理掉,所以我们这里也使用behaviors,因为不能操作dom,我们的组件抽象会变得相对简单,不用记录太多dom节点了,另外小程序的组件与我们之前的“组件”从定义到使用上有很大的不同,之前我们是以js作为控制器,现在是以标签wxml作为控制器,根本没有办法在js中获取实例,而小程序组件的生命周期并不包含显示隐藏生命周期,所以他的组件和我们以为的组件有很大的不同

我思考了下为什么小程序中,js不能获取组件的实例,这里得出的结论是:

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

我们这里尝试实现一个遮盖层的标签(这里开始不用组件这个词,感觉很有歧义):

小程序开发组件概述_小程序开发教程

代码非常简单:

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

可以看到,这个遮盖层mask没有什么意义,而且一般来说mask也不会单独存在,一般是一个组件(比如弹出层的loading)会包含一个遮盖层,所以我们这里要改造下Mask的结构,让他可以装载组件,我们从js组件逻辑来说是mask应该是loading的一个实例,但是我们站在标签角度来说,他们两个应该是独立的:

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

我们这里实现一个loading的组件(PS:CSS3动画稍微要做点兼容调试):

小程序开发组件概述_小程序开发教程

小程序开发组件概述_小程序开发教程
小程序开发组件概述_小程序开发教程

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

loading样式

 1 <ui-mask z-index="{{maskzIndex}}" ></ui-mask> 2 <view class="spinner" style="z-index: {{meIndex}}"> 3 <view class="spinner-container container1"> 4 <view class="circle1"></view> 5 <view class="circle2"></view> 6 <view class="circle3"></view> 7 <view class="circle4"></view> 8 </view> 9 <view class="spinner-container container2">10 <view class="circle1"></view>11 <view class="circle2"></view>12 <view class="circle3"></view>13 <view class="circle4"></view>14 </view>15 <view class="spinner-container container3">16 <view class="circle1"></view>17 <view class="circle2"></view>18 <view class="circle3"></view>19 <view class="circle4"></view>20 </view>21 </view>
 1 const util = require('../utils/util.js'); 2 let LayerView = require('behavior-layer-view'); 3  4 Component({ 5  behaviors: [LayerView], 6  7  data: { 8  maskzIndex: util.getBiggerzIndex(), 9  meIndex: util.getBiggerzIndex()10  },11 attached: function () { 12 console.log('loading')13  },14  methods: {15  }16 })

index调用情况:

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

小程序开发组件概述_小程序开发教程

我们后续将完整的项目代码放到github上去,这里便继续代码了

添加事件

于是,我们开始添加事件了,这里添加一个点击遮盖层关闭整个组件的功能,这里有个问题是,我们点击遮盖层事实上关闭的是遮盖以及loading两个标签,而我们这里的isShow属性便派上了用处,我们现在page中设置下属性:

<ui-loading is-show="{{isLoadingShow}}"></ui-loading>
1 onShow: function() { 2 this.setData({ 3 isLoadingShow: '' 4  }); 5 },

然后我们改造mask以及loading添加事件:

1 <view class="cm-overlay" style="z-index: {{zIndex}}; display: {{isShow}}" bindtap="onTap"> 2 </view>
 1 let LayerView = require('behavior-layer-view')  2  3 Component({  4  behaviors: [LayerView],  5  6  data: {  7  myData: {}  8  },  9 attached: function () { 10 console.log('mask') 11  }, 12  methods: { 13 onTap: function() { 14 this.triggerEvent('customevent', {}, {}) 15  } 16  } 17 })
 1 <ui-mask z-index="{{maskzIndex}}" is-show="{{isShow}}" bindcustomevent="onMaskEvent"></ui-mask>  2 <view class="spinner" style="z-index: {{meIndex}}; display: {{isShow}}; ">  3 <view class="spinner-container container1">  4 <view class="circle1"></view>  5 <view class="circle2"></view>  6 <view class="circle3"></view>  7 <view class="circle4"></view>  8 </view>  9 <view class="spinner-container container2"> 10 <view class="circle1"></view> 11 <view class="circle2"></view> 12 <view class="circle3"></view> 13 <view class="circle4"></view> 14 </view> 15 <view class="spinner-container container3"> 16 <view class="circle1"></view> 17 <view class="circle2"></view> 18 <view class="circle3"></view> 19 <view class="circle4"></view> 20 </view> 21 </view>
 1 const util = require('../utils/util.js');  2 let LayerView = require('behavior-layer-view');  3  4 Component({  5  behaviors: [LayerView],  6  7  data: {  8  maskzIndex: util.getBiggerzIndex(),  9  meIndex: util.getBiggerzIndex() 10  }, 11 attached: function () { 12 console.log('loading') 13  }, 14  methods: { 15 onMaskEvent: function (e) { 16  console.log(e); 17 this.setData({ 18 isShow: 'none' 19  }); 20  } 21  } 22 })

这个时候,当我们点击遮盖层的时候,我们整个组件便关闭了。

总结

我们今天花了很多功夫写一个loading,发现小程序中的组件事实上是标签,我们没法使用js获取到我们“组件”的实例,所以使用上有很大的区别,但是什么都不能阻碍我们写通用组件的决心,于是我们明天来写一些通用的组件库,并且形成一个小程序的体系,这里想的是有:

① 消息框

② toast提示

③ 日历组件

④ 然后再做一个需要定位的气泡组件

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/167024.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号