开发实战篇之七

  • 前言
  • 0、知识点补充
    • 0.1 $emit()函数
    • 0.2 wxs
    • 0.3 ⚡组件间关系
  • 1、steps进度条组件
    • 1.1、step进度条单元的骨架文件wxml
    • 1.2、step进度条单元的js
    • 1.3、step进度条单元的样式文件wxss

前言

实战篇内容参考:
1、Lin Ui开源组件源码分析。https://doc.mini.talelin.com/
2、开发过程遇到问题。

0、知识点补充

0.1 $emit()函数

// 点击遮罩层关闭popuponClose() {// 父组件通知close事件this.$emit('close');}

0.2 wxs

1、每一个.wxs文件和<wxs>标签都是一个单独的模块。
2、每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
3、一个模块要想对外暴露其内部的私有变量与函数,只能通过module.exports实现。

  • ⚠️即使将wxs写在wxml中,使用时仍需要使用内置的module对象exports
  • wxs可以写在<wxs></wxs>包裹中和.wxs文件中。
<!-- 导出状态可以被使用 -->
module.exports = {setStatus:setStatus,statusStyle:statusStyle,dotStyle:dotStyle,isReverse:isReverse
}

0.3 ⚡组件间关系

详情请参照微信小程序官方文档—组件间关系:
组件间关系详解

⚠️组件间关系可以通过data-传递数据,但是要进行更复杂的联系,就需要使用组件的relations属性。例如下面的steps进度条组件中的子组件step进度条元素。

<x-steps direction="column" step-min-height="160"><x-step title="已支付" describe="11:30"></x-step><x-step title="备餐中" describe="12:30"></x-step><x-step title="已出餐" describe="13:30"></x-step>
</x-steps>

使用relations属性解决stepsstep之间的关系:

选项 类型 是否必填 描述
type String 目标组件的相对关系,可选值为parent、child、ancestor、descendant
linked Function 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后
linkChanged Function 关系生命周期函数,当关系在页面节点树中时发生改变触发,触发时机在组件moved生命周期之后
unlinked Function 关系生命周期函数,当关系脱离页面节点树中时触发,触发时机在组件detached生命周期之后
// steps.js父组件
relations: {'../step/step': {type: 'child', // 关联的目标节点为子节点linked(target) { // 每次有step被插入时执行,target是子节点实例对象,this还是父组件实例对象,触发在该节点attached之后。this._initSteps(); // 调用初始化steps数据的方法。},unlinked(target) { // 每次有step被移除时执行,触发在该节点detached之后。this._initSteps();}},
},...
observers: {// 手动控制进度条的变化,需要更新每个step的状态,这就需要监听activeIndex的变化。'activeIndex': function () {this._initSteps();}
},/**
* 组件的方法列表*/
methods: {_initSteps() {// 1、获取自定义组件的实例对象const query = wx.createSelectorQuery().in(this);// 2、找到steps组件执行{...}中方法query.select('.steps-container').boundingClientRect().exec(res => { // 3、获取该steps下所有得到子节点steplet steps = this.getRelationNodes('../step/step');this.data.length = steps.length;if (this.data.length > 0) {// 4、调用子组件step中更新数据方法updateDataChange()// index为当前的step,不一定是active的stepsteps.forEach((step, index) => {// console.log(steps.length); // 3// console.log(res[0].width); // 375// console.log(this.data.status);step.updateDataChange({// 当前index会改变index,...this.data,stepsWidth: res[0].width});});}});}
}
// step.js子组件
relations: {// 绑定与steps的关系'../steps/steps': {type: 'parent'}
},
/*** 组件的方法列表*/
methods: {// 与父组件通信并绑定相关配置数据updateDataChange(options) {this.setData({...options});}
}

1、steps进度条组件

总体分析steps的编写思路:

  • 需求:进度条是由多个进度单元组成(个数应该由用户定制);并且每个进度单元样式应可以自定义;进度应该可以手动控制;数据绑定应该较为简单,尽可能封装样式和属性等,到组件中。
  • 采用整体steps父组件,传入进度条所需的整体大小、当前进度(activeIndex)、当前进度状态statusprocess还是error)、布局方向、进度条节点样式。子组件step主要进行数据绑定、根据父组件设置的布局、当前进度、进度条样式等属性进行设置布局和样式。

对steps父组件和step子组件进行详细分析:

  1. steps组件主要是一个布局steps-container,然后在布局中使用多插槽添加子组件step(⚠️slot非常灵活,可以很好的分割stepsstep,减少stepsstep的耦合度)。
  2. steps组件只用来控制step排列的方向。(flex布局的flex-direction: row-reverse或flex-direction: column-reverse来实现)。当然在step中需要对逆序之后的样式进行调整,具体就不展开说了。
  3. stepsstep的联系使用relations属性关联,数据传递在父组件中使用_initSteps()调用子组件的 updateDataChange()绑定数据。

1.1、step进度条单元的骨架文件wxml

  1. 整体布局:首先根据父组件传入的属性direction指定布局方向。如果是横向,就根据进度条宽度个数,平均分配宽度。纵向就设定最小高度。
  2. 整体基本由三个部分组成:进度条icon、进度条内容、进度条line
  3. 进度条icon可以由custom属性,控制是否自定义设置。如果不需要自定义设置,就按默认样式step-type step-icon,这里对每个step都需要判断当前的状态status,共有“process”、“wait”、“finish”和“error”四种状态,“error”是“process”等价,但由用户设定。

⚠️这里通过Mustache语法判断icon/dot样式,如果是icon是哪一种icon。具体逻辑是“如果设置了dot就按dot的样式,否则就设置成step-icon,空心圆圈的样式。”

{{dot && !icon?'step-dot-'+currentStatus.setStatus(activeIndex,index,status) + ' step-dot':'step-'+currentStatus.setStatus(activeIndex,index,status)+' step-icon'}}

⚠️这里就不得不提到获取状态的方法:setStatus(activeIndex, index, status)
写在<wxs>中的简单判断,如果当前位置index和当前进度位置activeIndex相同,那么,当前状态就是“process/error”。当index大于activeIndex时,那代表已完成进度“finish”,反之小于就是还没轮到处理,就是“wait”。
⚠️下面的逻辑就是有设置icon就按icon,没有就显示对应的序号

  1. 进度条内容title根据direction设定内容方向step-content-direction,然后是titledescribe部分。标题字体颜色,根据是否是activeIndex,置为step-title-processstep-title
  2. 进度条line根据direction设定line的方向step-line-direction,根据是否是最后一个step决定显示与否。
<!--components/step/step.wxml-->
<view class="step {{'step-'+direction}} x-class"style="{{direction==='row'?'width:'+(1/length)*stepsWidth+'px':'min-height:'+stepMinHeight+'rpx'}}"><!-- 进度条icon样式 --><view class="step-container x-step-class {{'step-container-'+direction}}"><!-- 进度条icon自定义样式 --><view wx:if="{{custom}}" class="step-custom"><slot name="dot" /></view><!-- 进度条icon样式---进度数字/icon选择 --><view wx:elseclass="x-step-class {{dot && !icon?'step-dot-'+currentStatus.setStatus(activeIndex,index,status) + ' step-dot':'step-'+currentStatus.setStatus(activeIndex,index,status)+' step-icon'}}"style="{{dot ? currentStatus.dotStyle(activeIndex,index,color) : currentStatus.statusStyle(activeIndex,index,color,status)}}"><x-icon wx:if="{{icon}}" name="{{icon}}" size="{{iconSize}}" color="{{(currentStatus.setStatus(activeIndex,index,status)==='process'?'#3963bc':iconColor)}}"/><block wx:if="{{!dot && !icon}}"><view wx:if="{{currentStatus.setStatus(activeIndex,index,status)==='error' || currentStatus.setStatus(activeIndex,index,status)==='finish'}}"class="iconfont icon-{{currentStatus.setStatus(activeIndex,index,status)}}"></view><block wx:else>{{index+1}}</block></block></view></view><!-- 进度条内容title --><view class="step-content {{'step-content-'+direction}}"><view class="x-title-class {{activeIndex===index?'step-title-process':'step-title'}}">{{title}}</view><view class="x-describe-class step-describe">{{describe}}<slot name="describe"/></view></view><!-- 进度条line --><view class="step-line x-line-class {{'step-line-'+ direction}} {{currentStatus.isReverse(reverse,activeIndex,index)?'step-line-finish':'step-line-wait'}}"style="{{activeIndex>index?('background-color:'+color):''}}"wx:if="{{reverse?(index!==0):(length!==index+1)}}"></view></view><!-- step status设置 -->
<wxs module="currentStatus">
var setStatus = function(activeIndex,index,status){if(activeIndex === index){return status || 'process'}else if(activeIndex > index){return 'finish'}else {return 'wait'}
}var statusStyle = function(activeIndex,index,color,status) {if(activeIndex == index){return status=='error'?'':('background-color:' + color)}else if(activeIndex > index){return ('border-color:' + color + ';color:' + color)}else {return ''}
}var dotStyle = function(activeIndex,index,color) {if(activeIndex>=index){return ('background-color:' + color)}else {return ''}
}var isReverse = function(reverse,activeIndex,index) {if(reverse){return (activeIndex>=index)}return (activeIndex>index)
}module.exports = {setStatus:setStatus,statusStyle:statusStyle,dotStyle:dotStyle,isReverse:isReverse
}
</wxs>

1.2、step进度条单元的js

// components/step/step.js
Component({/*** 组件的属性列表*/externalClasses: ['x-class','x-step-class','x-title-class','x-describe-class','x-line-class'],options: {multipleSlots: true},relations: {// 绑定与steps的关系'../steps/steps': {type: 'parent'}},properties: {icon: String,title: String,describe: String,iconSize: {type: Number,value: 24},iconColor: String,// 是否自定义步骤条元素stepcustom: Boolean},/*** 组件的初始数据*/data: {},/*** 组件的方法列表*/methods: {// 与父组件通信并绑定相关配置数据// 父组件调用绑定数据updateDataChange(options) {// console.log(options.status);this.setData({...options});}}
})

1.3、step进度条单元的样式文件wxss

/* components/step/step.wxss */
.step {display: flex;position: relative
}.step-custom {z-index: 2
}.step-row {flex-direction: column;align-items: center
}.step-column {flex-direction: row;padding-left: 30rpx;box-sizing: border-box
}.step-container {display: flex;justify-content: center;z-index: 2;align-items: center;background-color: #fff
}.step-container-row {width: 70rpx;height: 40rpx
}.step-container-column {height: 60rpx;width: 40rpx
}.step-icon {width: 40rpx;height: 40rpx;display: flex;align-items: center;justify-content: center;font-size: 22rpx;transition: .5s;box-sizing: border-box
}.step-process {color: #fff;background-color: #3963bc;border-radius: 50%
}.step-error {background-color: #fff;border: 1px solid #f4516c;color: #f4516c;border-radius: 50%
}.step-finish {background-color: #fff;color: #3963bc;border: 1px solid #3963bc;border-radius: 50%
}.step-wait {background-color: #fff;color: #c4c9d2;border: 1px solid #c4c9d2;border-radius: 50%
}.step-dot {width: 24rpx;height: 24rpx;border-radius: 50%;transition: .5s
}.step-dot-process {background-color: #3963bc
}.step-dot-wait {background-color: #c4c9d2
}.step-dot-error {background-color: #f4516c
}.step-dot-finish {background-color: #3963bc
}.step-line {background: #c4c9d2;transition: .5s;position: absolute;z-index: 0
}.step-line-row {height: 2rpx;width: 100%;left: 50%;top: 18rpx
}.step-line-column {width: 2rpx;height: 100%;top: 20rpx;left: 48rpx
}.step-line-wait {background-color: #e8e8e8
}.step-line-finish {background-color: #3963bc
}.step-content {display: flex;flex-direction: column
}.step-content-row {align-items: center;width: 100%
}.step-content-column {margin-left: 15rpx
}.step-title {color: #595959;font-size: 26rpx;line-height: 40rpx;margin: 10rpx 0
}.step-title-process {color: #333;font-size: 28rpx;line-height: 40rpx;margin: 10rpx 0
}.step-describe {color: #8c98ae;font-size: 22rpx
}@font-face {font-family: iconfont;src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAK8AAsAAAAABpQAAAJvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgp8gQsBNgIkAwwLCAAEIAWEbQc2G9EFyK4wbuGJaCgrSmkBCSe/ZeUtviBzEXztx/bd3f+oNEiuzaerJhKN6WQSJFqlZELxTOZqTS9l0hsflgVC/bD3z/dzv8lMXAksyeryeByfVkhgV93EvwdIwC+b/hetH5jPyAA+z+X0JtCBXONbltMcw496AcYBBbYnRoEEXEQBcAqyOwK15PsEmg2KiewMTy6yCoWzLBD3lqGwilJKUaRqo1C37C3iRaUxPaUnPMffj18LUUFSZc7a3bshnfV++DD/2GVISBPo4QoZU5hCXLeWThULiSvWbCrpb64VIS2VhYlVpqU+6B8vETWnsxWM0XLiI19G8OGABDKoy5VBzDRje98gRHertt+2fLx2cdC6ZJwcnK226Ifh0uzy4vzK8sLSytxprqHAHexGbz8/6za6C3ePjwW29viP3ailnm7Zz+SntAd5IV0IBHuvvy3Xd/41thTw/osdBRahcefh4Gepwb5iah13LrrKV9mRrBsIJKhCjvrnxLq9Trf0wb2ERn0TIg0GcmSNhsjCTqHSYgm1RutoNmnkcIseUrEoTZiwRRA63SBp94as0zNZ2BdU+v2h1hnFaHYczWe2GAmrakCiQqiDmgdLEz73vFSVdM+jkXUVWdTG/DLK0MpCOpGqVkfQR7nEhjBnZIg4cCk8GCaPoesKCKSwUaOESRS0J5O87UUJTXisyjYJKQjSAVUesGgEHw+Hk6ra5+chQ5ZLIXsEDfllSApZ44O0hBRAjph8SPAoz4RyDBmEcICTBA8YJrOQyyWAoH2WDWlIgjmhEGiXdAdx1JTY3uL93xFo5kzMkSJHUT+g+5BNxVpWMAYAAA==') format('woff2')
}// finish和error图标使用iconfont图标.iconfont {font-family: iconfont !important;font-size: 24rpx;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale
}.icon-finish:before {content: "\e600"
}.icon-error:before {content: "\e6cf"
}

微信小程序|开发实战篇之七-steps进度条组件相关推荐

  1. 微信小程序|开发实战篇之五-slide-view滑动菜单组件

    开发实战篇之五 前言 1.微信小程序操作dom元素 1.1 slide-view组件的wxml骨架文件 1.1.1 涉及movable-view组件属性 1.2 slide-view组件的js文件 1 ...

  2. 微信小程序|开发实战篇之二

    开发实战篇之二 前言 1.零碎知识点和优化点 1.1 ES6模板字符串 1.2 ES6扩展运算符 1.3 独立更新like组件状态 1.4 自定义组件支持hidden 2.音乐music组件开发 2. ...

  3. 微信小程序|开发实战篇之一

    开发实战篇之一 前言 1.通用方法的封装 2.数据获取方法的封装 2.1 抽离classic.js中的request()方法 2.2 组件数据传递 3.movie组件的创建 3.1 组件代码开发 3. ...

  4. 微信小程序|开发实战篇之四

    开发实战篇之四 前言 1.用户页面my的开发 1.1 my.wxml骨架文件 1.2 my页面的布局和样式分析 1.2.1 从原型页面来分析: 1.2.2 继续分析每个大组件中的小组件布局: 1.3 ...

  5. 微信小程序|开发实战篇之三

    开发实战篇之三 前言 1.使用Promise获取多个异步方法的结果 2.高阶组件-search 2.1 search组件的基本结构 2.1.1 search组件的骨架index.wxml文件 2.1. ...

  6. 微信小程序|开发实战篇之六-pagination分页组件

    开发实战篇之六 前言 1.分页组件pagination 2.pagination代码分析 2.1 wxml骨架文件 2.2 wxss样式 2.3 pagination的逻辑文件 前言 实战篇内容参考: ...

  7. 微信小程序|开发实战篇之request请求(单个、多个参数,json对象,header)

    开发实战篇之request请求 前言 1.发送单个.多个参数的request 2.发送JSON对象的request 3.发送header的request 前言 小程序发送网络请求常会遇到的问题: 请求 ...

  8. 微信小程序|开发实战篇之九-image-picker图片选择器组件及其子组件

    开发实战篇之九 前言 1.grid格子组件 1.1 grid骨架文件wxml 1.2 grid的js文件分析 1.3 grid-item的wxml文件分析 1.4 grid-item的wxss文件分析 ...

  9. 微信小程序|开发实战篇之八-list列表组件及其子组件

    开发实战篇之八 前言 1.list选择器组件 1.1 子组件---tag标签组件 1.1.1 tag的骨架文件wxml 1.1.2 tag的js文件 2.list选择器wxml骨架文件 3.list选 ...

最新文章

  1. Windows Server2008下MYSQL外网无法访问问题解决
  2. 带你从源码了解SpringBoot启动流程
  3. 深度学习基础1(神经网络)
  4. VUE2.x的浏览器兼容情况汇总
  5. 阿里云自动java和mysql数据库_阿里云服务器之基于Linux系统部署上线JavaWeb项目和连接MySQL数据库(从购买云服务器到发布JavaWeb项目全套详细流程)...
  6. DHCP服务器在企业里的各种应用方案
  7. LeetCode 117. 填充每个节点的下一个右侧节点指针 II
  8. Gradle学习总结——抓重点学Gradle
  9. MediaInfo使用简介(新版本支持HEVC)
  10. 在eclipse中修改android源码
  11. 《室内设计软件Sketch Up零初级入门视频教程》
  12. 【基础篇】SpringBoot 自定义 Banner
  13. 淘汰我们的不是这个时代,而是原地踏步的自己
  14. 如何策划新闻营销的主题?
  15. 高级转录组调控分析和R语言数据可视化第十三期 (线上线下开课)
  16. 关于数据治理的读书笔记 - 企业数据治理的“道、法、术、器”
  17. python词云分析--媒体近期的讨论热点
  18. 保姆级教程:基于Docker部署雨中冒险2服务器 雨中冒险2开服
  19. 数据结构笔记 —— 二叉树(前序、中序、后序遍历和查找)
  20. MAZAK手轮维修马扎克小巨人数控机床手柄操作器维修AV-EAHS-382-1

热门文章

  1. linux监控指定用户操作,Linux 用户行为轨迹监控
  2. centos7 环境搭建(LNMP)以及虚拟环境(python3)
  3. SqlServer Windows 可更新订阅立即更新启用分布式事务协调器(MSDTC)
  4. Mesos:数据库使用的持久化卷
  5. html元素两种分类。替换元素和不可替换元素;块级元素和行内元素
  6. Hibernate学习笔记--映射配置文件详解
  7. URAL 1233 Amusing Numbers 好题
  8. git commit撤销_Git commit 提交一堆记录?试试撤回 commit 操作,你会爱上它
  9. HBase之MVCC
  10. (6)SMC接口采集数据出现错误(学无止境)