我正在参加「掘金·启航计划」
前言:很难受距离上一篇文章已经100天,经过和面试官的激情交流,终于进入理想的公司开始新的旅程。这段时间空闲下来,决定踩坑taro,于是乎故事开始了......
其实呢,本文的原由还是挺杂的,一开始是想去进行taro的学习,但是实践才是检验真理的唯一标准,后来就直接进行taro项目实战,进行项目的编写。在编写过程中,有需要对checkbox进行使用,而现有的checkbox样式多多少少不符合设计稿,能怎么办?只能手动封装一下,一不小心,就加了bem了。
taro的设计稿匹配
在公司的开发中,我们通常都会需要还原设计稿,要是还原度不高,视觉验收就不给过(那就寄了)。跟个人开发不同,我们平时自己的项目会使用rem、vw、vh去进行适配(有兴趣可以去看看rem、vw/vh的原理)。但是在我们的h5、web的设计稿一般都是px的单位,因此我们在项目的搭建中会使用px2rem等方案进行还原设计稿和屏幕适配。
值得安利的是,taro的开发中不需要安装插件进行适配,taro编译的时候会自动进行转换,但是需要我们进行配置的设定,使用px在小程序中会转换成rpx,在H5中会转换成rem,而Px则不会被转换。
下面是文档的图片(设计稿及尺寸单位 | Taro 文档)
在我们拿到的设计稿中,设计稿的宽度是375px,高度是812px。taro默认会在使用750px作为设计稿标尺,因此我们需要进行比例的配置:设计稿宽度的配置和设计稿的转换比例。
以小程序为例,通过进行转换后,className为me且宽度为375px的盒子的宽度将会自动转换成小程序的750rpx。
基于sass的bem编写
taro是支持sass的,可以根据相关的配置进行安装sass并使其生效,这里就不再进行赘述。BEM布局布局也有很多文章对其进行描述,其他人的描述可能会更加详细,我谨在此发表一孔之见。
对于BEM布局,我们并不需要将其束之高阁,或者理解得很难,其实往简单看,他就是一种css命名规则:
- block:块,例如table、input等语义上唯一的块;
- element:元素,主要是块的子项;
- modify:修改,一些其他的状态和样式
他们之间使用不同的连接符号进行连接:-顶级前缀和块相连、__块和子元素连接、_作为块及子元素的不同状态连接。
$namespace:'mo'!default; // 作为顶级符号
$block-sel:'-'!default;
$element-sel:'__'!default;
$mod-sel:'--'!default;
@mixin b($block) {
// 声明变量
$B:#{$namespace+$block-sel+$block};
.#{$B}{
@content;
}
}
@mixin e($element) {
// &表示父级元素,而$selector是变量命令
$selector:&;
// 因为有bem的存在,不需要.e .b{} 这样的写法,直接放在样式文件跟顶层
@at-root{
#{$selector + $element-sel + $element}{
@content;
}
}
}
@mixin m($modify) {
$selector:&;
@at-root{
#{$selector + $mod-sel + $modify}{
@content;
}
}
}
taro中配置bem(其实也就是配置sass)
taro对于sass其实还是非常友好的,我们能像在vite那样直接配置进行全局使用,而非用到的时候就引入相关的函数。
在src中,我新建了一个styles的文件夹,并将bem的命名规则写入BEM.scss的样式文件中。再在config/index.js
添加sass选项,填充相关资源。
taro可以支持单文件注入、多文件注入的情况,此外,还可以传入相关的字符串进行变量定义,这个时候,通过在scss项定义的全局变量是优先级最高的。 scss编译配置详情 | Taro 文档
checkbox案例的实现———Mocheckbox组件!!!
到了实战环节了,也是本文出现的原因,如图所示,设计稿中的checkbox在现在的组件库中找不到相似度大的,因此我们需要自己去自定义一个。
checkbox主要是input
的type=checkbox
的时候得到的元素。很多实现方案,如果想简单一点进行应用,或许不需要使用input
而使用切换图片的方法。label
连接了input
和Text
。(注意:在taro中使用原生的input标签需要进行相关的配置,怎么配置呢?“看文档!”)
const MoCheckbox = (customProps)=>{
return <label style={{position:"relative",width:"100%",height:"56px",display:"block"}}>
<input type="checkbox"
className={
`${customProps.checked?'mo-checkbox--active':''}
${customProps.disabled?'mo-checkbox--finish':''}
mo-checkbox`}/>
<Text>{customProps.label}</Text>
<img src={customProps.src} />
</label>
}
样式文件,有两种实现方式:
实现方式1.其实格子是text前面的content,通过props的相关属性切换content的内容:
@include b(checkbox) {
// 忽视了checkbox的显示
position: absolute;
visibility: hidden;
padding-left: 16px;
top: 0;
left: 0;
// 文本样式的内容
&+text {
position: absolute;
padding-left: 32px;
top: 16px;
left: 16px;
word-break:keep-all;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
/** 文本1 */
font-size: 16px;
font-weight: 500;
letter-spacing: 0px;
line-height: 24px;
color: rgba(0, 0, 0, 1);
text-align: center;
vertical-align: top;
}
// ✔的格子
&+text:before {
content: " ";
position: absolute;
width: 16px;
height: 16px;
left: 0;
top: 4px;
border-radius: 2px;
background: rgba(61, 182, 252, 1);
color: white;
}
&+text+img {
position: absolute;
left: 296px;
top: 20px;
width: 16px;
height: 16px;
display: inline;
}
// 完成时候文字的状态
@include m(finish){
&+text{
text-decoration-line: line-through;
color: rgba(0, 0, 0, 0.25);
}
}
// ✔的相关样式
@include m(active) {
&+text:before {
content: "\2714";
position: absolute;
left: 0;
top: 4px;
width: 16px;
height: 16px;
line-height: 16px;
}
}
}
通过方式1得到的样式:
实现方式2:方式1的checkbox貌似和input本身没多大的关系,其实确实没关系,而原生的封装的应该是这样的(这里没有使用bem,是另外使用html文档显示的,参考大佬的:纯粹的CSS自定义复选框样式 - 掘金 (juejin.cn))
//html标签
<label class="form-control">
<input type="checkbox" name="checkbox" />
Checkbox
</label>
// style样式
input[type='checkbox'] {
// 清除默认显示
appearance: none;
background-color: #fff;
margin: 0;
font: inherit;
color: currentColor;
width: 1.15em;
height: 1.15em;
border: 0.15em solid currentColor;
border-radius: 0.15em;
display: inline-flex;
place-content: center;
}
input[type='checkbox']::before {
margin-top: -50%;
content: '\2714';
width: 0.65em;
height: 0.65em;
transform: scale(0);
transition: 120ms transform ease-in-out;
box-shadow: inset 1em 1em var(--form-control-color);
}
input[type='checkbox']:checked::before {
transform: scale(1);
}
通过方式2得到的样式:
由于水平有限,如果有错漏希望大家批评指正。