内容简介:小程序点睛系列写到第三篇,我才在昨夜临睡前想到这个名字。官方文档讲过的东西我不重复,我只在你会写的基础上,帮你画上点睛一笔。这一篇,是我与小程序鏖战半年苦心孤诣的成果,满满干货。从基础库 1.6.3 开始支持,用来抽象功能组件,以便在多个页面复用。如果你有小程序吸收了
小程序点睛系列写到第三篇,我才在昨夜临睡前想到这个名字。官方文档讲过的东西我不重复,我只在你会写的基础上,帮你画上点睛一笔。这一篇,是我与小程序鏖战半年苦心孤诣的成果,满满干货。
自定义组件
从基础库 1.6.3 开始支持,用来抽象功能组件,以便在多个页面复用。如果你有 React
或 Vue
等前端类库的开发经验,对自定义组件一定不会陌生。
小程序吸收了 Vue
的模板语法, React
的状态管理方式,再加上 Web Component
的 Shadow DOM
残缺版本,总之就是一边抄一点,形成了独具特色的小程序风格组件。这使得你之前在其它类库上获得的经验不能完全适用。
接下来,我们就一起聊聊小程序组件的奇技淫巧。
JavaScript 部分
小程序将组件数据分为父组件传递来的 properties
和自身持有的 data
,这点与主流前端框架类似,我们重点关注 properties
。
组件的 property 接收 type
、 value
、 observer
三个参数
type: 属性类型,目前支持 String
, Number
, Boolean
, Object
, Array
, null
从 .wxml
传递过来的值到 .js
之前会先经过类型转换。如果想传递混合类型值(如既可能是 String
也可能是 Number
的值),可以将 type
设置为 null
,可以避免默认的类型转换。
value: 默认值
如果不设置 value
的值,那该 property
的默认值就是其类型的零值。对应如下:
String => '' Number => 0 Boolean => false Object => {} Array => [] null => null 复制代码
observer: 属性被改变后执行的函数
由于小程序自身不支持 watch
,故而无法监听 data
中某一项的改变。但与 React
不同的是,组件的 properties
在组件运行时会被整合入 data
中,通过 this.data
获取,并且可以调用 this.setData
改动 properties
的值。 因此可以将需要监听的 data
放于 properties
中,利用 observer
监听。同时,为表示其为内部状态,建议以下划线(_)开头,且不再外部设置其值。
observer
还可以用来减少 .wxml
模板的重复代码。例如父组件传递了一个 source 对象,要求组件显示其姓名与年龄
// component.js Component({ properties: { source: Object, } }) 复制代码
<!-- component.wxml --> <view>{{ source.name }}</view> <view>{{ source.age }}</view> 复制代码
利用 observer 可以写成
// component.js Component({ properties: { source: { type: Object, observer(val) { this.setData(val) } } } }) 复制代码
<!-- component.wxml --> <view>{{ name }}</view> <view>{{ age }}</view> 复制代码
这对体量较大的组件犹为有效。同时,将 source 封装为 behavior
,可以最大限度的减少冗余代码
// sourceBehavior.js export default Behavior({ properties: { source: { type: Object, observer(val) { this.setData(val) } } } }) // component.js import sourceBehavior from 'path/to/sourceBehavior.js' Component({ behaviors: [sourceBehavior] }) 复制代码
WXML 部分
.wxml
模块与 Vue
模板大同小异,唯一值得了解的是由于小程序不完全实现了 Shadow DOM
, Vue
中 <template>
标签只能有一个根节点的限制是不存在的。因此在大多数情况下,你都不需要给 .wxml
额外添加根节点。
<!-- good.wxml --> <view>{{ name }}</view> <view>{{ age }}</view> <!-- bad.wxml --> <view> <view>{{ name }}</view> <view>{{ age }}</view> </view> 复制代码
WXSS 部分
inherit
关键字
我们可以通过将属性值设置为 inherit
来有效减少代码冗余。如果你想保持节点属性与父节点一致,就应当使用这个关键字。
回想一下 小程序点睛之二:小程序使用 Iconfont 的正确姿势
,默认 Iconfont 下载的 CSS 文件中定义了 .iconfont
类的字体大小为 16px
,如果你不想每次更新改动这一值,那么可以在组件样式表中添加
.iconfont { font-size: inherit; } 复制代码
组件样式表的优先级要高过外部引入的样式表,所以原本的 font-size: 16px
就会被覆盖, .iconfont
的字体大小就会跟其父节点一致。
注意:这里 .iconfont
的父节点并不是逻辑上的父节点,而是 shadow-root
。
:host
选择器
你可以在开发者 工具 中看到每个自定义组件的 shadow-root
,其默认是行内元素,你可以在组件样式表中通过 :host
选择器修改它的样式
:host { display: block; background: red; } 复制代码
外部样式表所有的属性都是直接作用在 shadow-root
(而非模板中的根节点)上,例如
<!-- iconfont.wxml --> <text class="iconfont icon-{{icon}}"></text> <!-- page.wxml --> <iconfont class="icon" icon="upload"></iconfont> 复制代码
/* page.wxss */ .icon { color: green; } /* iconfont.wxml */ .iconfont { color: red; } 复制代码
你会发现图标的颜色是红色而不是绿色。因为 .icon
是样式作用于 shadow-root
, .iconfont
是其子节点,继承其 color
属性,但由于 .iconfont
优先级更高,所以颜色是为红色。
优先级关系为 :host
选择器 < 外部样式 < 子节点样式。利用这个特点,配合 CSS 变量,可以达到意想不到的效果。
CSS 变量
现阶段支持各浏览器的支持度并不高,版本稍旧的浏览器就会遇到问题。但小程度已经完全支持了这个特性。
由于小程序使用了 Shadow DOM
,因此在组件内是无法使用全局定义的样式类的。 但是
,CSS 是可继承并且是全局可用的。因此,我们可以将常用的样式定义在 app.wxss
内,并在任意页面或组件内使用
/* app.wxss */ page { --primary-color: #aabbcc; --accent-color: #ddeeff; --spacing: 32rpx; } /* other.wxss */ .component { background: var(--primary-color); padding: var(--spacing); } 复制代码
如此,你只需要对 app.wxss
稍作修改,就可以改变整个小程序样式。
除此之外,我们还可以利用这个特性,优化组件定义。例如,我们需要一个圆形组件,常规的做法是定义相等的宽高,再设定 border-radius: 50%
。我们来看看高级的写法
/* circle.wxss */ :host { /* 默认直径为 32rpx */ --diameter: 32rpx; width: var(--diameter); height: var(--diameter); border-radius: 50%; } /* outer.wxss */ .circle { /* 将 circle 组件的直径设置为 64rpx */ --diameter: 64rpx; } 复制代码
还记得我刚刚说的优先级规则吗?外部样式的优先级高于 :host
选择器,因此 circle 组件的直径会被设置为 64rpx
。
不只如此,通过自定义属性,我们还可以修改嵌套较深的组件样式
<!-- component.wxml --> <view class="this"> <view class="is"> <view class="a"> <view class="embed-component"></view> </view> </view> </view> 复制代码
/* component.wxss */ :host { --embed-color: red; } .embed-component { color: var(--embed-color); } /* outer.wxss */ .component { --embed-color: blue; } 复制代码
Bingo,借助 CSS 属性,我们获得了改动后代节点样式的能力。你大可以说同样的功能使用 externalClasses
或者 addGlobalClass
也可以做到。但是对于组件来说,外部传入的样式可知,处理起来心智负担更小,更符合 高内聚,低耦合
的标准。同时,建议将可改动的自定义 CSS 变量以注释的形式写在 component.js
中,方便其他人理解你的组件。
用 em
而不是 rpx
为了保持组件可扩展性,应当尽可能的使用 em
作为字体大小单位。我之前用一个小程序解析 markdown
的组件库,其中将所有字体大小都写死为 rpx
,例如
/* markdown.wxss */ .h1 { font-size: 32rpx; } .h2 { font-size: 28rpx; } .h3 { font-size: 24rpx; } 复制代码
如此固然能实现需求,但却失去了外部改变字体大小的能力。作为一个组件,应该适应更多的可能性,改为 em
作为字体大小单位就能很好的解决这一问题
.h1 { font-size: 2em; } .h2 { font-size: 1.8em; } .h3 { font-size: 1.4em; } 复制代码
数值仅为举例
大胆使用新特性
小程序对 CSS 3 新特性的支持比较完善, vw
, vh
, flex
, calc
,CSS variables 等等只要你想到,你可以大胆地使用,完全不需要考虑兼容性问题,这简直就是前端梦寐以求的试验田。所以,好好学习,大胆使用吧!
后记
写了这么多,自己都忘了要写些什么。本来是准备日更的,但是这两天一直在忙社保的事。刚刚从公司离职,办理灵活就业人员耽误了不少时间。感谢各位耐心阅读至此,这都是我工作半年以来的经验之谈,希望可以对你们有一点帮助。
如果你也想发布小程序的组件, 官方模板
虽不失为一个选择,但我也要强推一下我写的脚手架工具 tacer
,只需一行 npx tarcer wx-component
就可以开始你的项目了哦!
小程序点睛系列还剩下一篇,最后一篇,我们单纯聊 JavaScript
,关注我哟。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- WebSSH 画龙点睛之 lrzsz 上传下载文件
- React 组件模式-有状态组件 x 无状态组件、容器组件 x 展示组件、高阶组件 x 渲染回调(函数作为子组件)
- Serverless 组件开发尝试:全局变量组件和单独部署组件
- angular自定义组件-UI组件篇-switch组件
- React Hooks 源码解析(一):类组件、函数组件、纯组件
- Vue动态组件和异步组件
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。