内容简介:距离第一篇UI组件库文章发布已经过去3个月了,在此期间利用零零散散的时间持续更新owl-ui组件库,目前owl-ui移动端组件库已经更新我们从先看效果图。
距离第一篇UI组件库文章发布已经过去3个月了,在此期间利用零零散散的时间持续更新owl-ui组件库,目前owl-ui移动端组件库已经更新 3大类 (基础、表单、弹出层) 9种组件 (Button、Tabs、Input、Select、Switch、Drawer、Dialog、Picker、Toast)供使用。本篇文章主要讲述我在这3个月内开发UI组件的个人心得。如果想了解项目结构可以阅读上一篇文章,如果想了解实现原理可以阅读源码。 所有连接在文章的结尾处。
我们从 弹出层组件 讲起
前方多图预警
先看效果图。
我在选择写组件的时候,首先选择做弹出层部分。为什么呢?我列出以下几点。
- 共性高、可复用。
- 兼容性高。
- 快速出货,提升成就感。
先说第一点: 共性高、可复用
因为本人非常笨,所以做事之前需要构思很久,这样会减少之后重复性的工作。比如在做弹出层的时候,不少人会发现以上组件的共同点。没错,他们都是 显示 或 隐藏 (废话)。我们接着往下分析,除了显示或隐藏之外,他们大部分都有 遮罩层 部分。还有 动画效果 也一致。我们先根据这几点把功能抽象出来,如何做呢?
在vue和less中都有 mixins 方式,根据 mixins 我们很方便的将组件中的共性提取出来,达到代码精简的目的。以下代码就是弹出层组件中 显示 或 隐藏 功能的 mixins 文件。
// src/common/mixins/visibility.js const EVENT_TOGGLE = 'toggle' export default { model: { prop: 'visible', event: EVENT_TOGGLE }, props: { visible: { type: Boolean, default: false }, zIndex: { type: Number, default: 100 }, maskStyle: { type: Object, default: () => {} }, containerStyle: { type: Object, default: () => {} } }, data () { return { isVisible: false } }, methods: { hide () { this.isVisible = false }, show () { this.isVisible = true } }, watch: { isVisible (val) { this.$emit('update:visible', val) this.$emit('callback', val) if (this.lockScroll) { document.body.style.overflow = val ? 'hidden' : '' } }, visible: { handler (val) { this.isVisible = val } } }, beforeDestroy () { this.lockScroll && (document.body.style.overflow = '') } } 复制代码
上面主要做一件事,根据 visible 属性判断组件 展示 或 隐藏 。
使用方式如下:
// 组件文件 <script> import visibilityMixin from 'mixins/visibility' export default { mixins: [ visibilityMixin ] } </script> 复制代码
顺便说一下项目中运用到less的mixins运用,比如1px问题。
// src/styles/common/border.less .min-device-pixel-ratio(@scale2, @scale3) { @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) { transform: @scale2; } @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) { transform: @scale3; } } .border-1px(@color: #DDD, @radius: 2PX, @style: solid) { &::before { content: ""; pointer-events: none; display: block; position: absolute; left: 0; top: 0; transform-origin: 0 0; border: 1PX @style @color; border-radius: @radius; box-sizing: border-box; width: 100%; height: 100%; @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) { width: 200%; height: 200%; border-radius: @radius * 2; transform: scale(.5); } @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) { width: 300%; height: 300%; border-radius: @radius * 3; transform: scale(.33); } } } .border-top-1px(@color: #DDD, @style: solid) { &::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; border-top: 1Px @style @color; transform-origin: 0 0; .min-device-pixel-ratio(scaleY(.5), scaleY(.33)); } } 复制代码
该函数可以通过传参改变线的颜色和类型。
使用方式如下:
// src/styles/packages/dialog.less @import "../common/border"; @dialog-prefix-cls: ~"@{css-prefix}dialog"; .@{dialog-prefix-cls} { ... &-btns { ... .border-top-1px(); // Here } } 复制代码
合理的运用 mixins 可以使得项目结构清晰、减少冗余代码更利于后期维护。
优化方式有很多种,每个人有不同的编码习惯,因人而异。但是目标都是一致的,让自己的代码变得简洁、精炼和易读。
在弹出层中将公共部分抽象封装,比如 遮罩层
// src/common/components/popup-mask.vue <template> <div class="popup-mask" :style="{ ...maskStyle, zIndex: zIndex - 1 }" @click.stop.prevent="handleMask"></div> </template> <script> export default { props: { name: String, maskStyle: Object, zIndex: Number }, methods: { handleMask (event) { this.$emit('click', event) } } } </script> 复制代码
第二点:兼容性高
我在工作中接触的移动端需求比较多,PC端做过一些管理后台。移动端与PC端的项目,给我最最直观的感受是,移动端要求UI极其严格,一像素都不能差,而PC端差不多就可以了,UI设计师们也不会过多纠结PC端做出来的页面是否跟原型图完全吻合。
在移动端,有的产品特别喜欢更改UI设计,特别是有表单部分的页面,今天产品嫌弃字体小了,明天可能觉得字体又太大了;今天把输入框改成圆角,明天就喜欢直角。今天觉得横向布局好,没准明天就要试试纵向布局。产品觉得这么改不要紧,殊不知如果项目中运用了UI组件库,这么修改完后,代码冗余太多。都是为了更好的用户体验,慢慢也能理解。在那之后的几个移动端项目里,表单部分基本不会用到UI组件库。但是弹出层部分没有过多的限制,据我了解到的产品内部最统一的就是弹出层。如果有同学想用 owl-ui 的弹出层部分的话,可以放心用,支持按需加载。
第三点:快速出货,提升成就感
我喜欢把长期计划拆解成多个很小的事情来做,就是制定很多小目标。好比游戏进度条一样,使其量化。之所以这么做的原因是,我能周期性的看到我的工作成果,这样可以激励自己,提升信心。
在 弹出层 组件中, mixins 做好之后,像 toast、dialog、drawer 组件只剩下设计api部分而已。而 picker 组件是基于 drawer 组件来实现的内容部分而已。当 picker 组件实现完成,这时已经说明表单的 select 组件也已经完成了。说起来简单,其实做起来也不难。
最后在使用弹出层组件时,我想用api调用的方式来使用它。这里我借鉴了cube-ui的 vue-create-api ,但是因为部分方法不太适合我,所以我稍加改动,借鉴(抄)到自己的库中。
比如Toast组件,官网给出的使用方式如下:
const toast = this.$createToast({ time: 1000, txt: 'Toast time 1s' }) toast.show() 复制代码
我是个懒人,对我来说使用一个消息提醒要写这么多,我就觉得很烦恼,所以我在 owl-ui 中把 vue-create-api 稍加改造后, Toast 使用方式如下:
this.$toast('欢迎光临') 复制代码
清爽了很多。
其他类型组件使用情况,有人喜欢整套使用,有人喜欢部分使用。而我属于后者。
结语
我写组件库的目的就两点。第一点可以帮助我重新梳理一遍vue的知识体系,了解到自身的不足,不断的克服困难,让自己成长。第二点结识更多圈内的朋友,提高见识。我会持续更新迭代 owl-ui 组件库,欢迎喜欢技术的朋友多提建议。最后附上 吴军博士 说过话,这句话让我终身受益。
什么事情从0分做到50分靠常识,从50分做到90分靠技术,从90分做到100分靠的是艺术。做到90分我们可以通过努力能达到,至于是否能做到更好,就依人而定了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。