内容简介:小程序点睛系列写到第三篇,我才在昨夜临睡前想到这个名字。官方文档讲过的东西我不重复,我只在你会写的基础上,帮你画上点睛一笔。这一篇,是我与小程序鏖战半年苦心孤诣的成果,满满干货。从基础库 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动态组件和异步组件
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML Dog
Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99
For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!