【momo·taro实战指南】基于taro的bem规范实践及checkbox组件的案例

516 阅读4分钟

我正在参加「掘金·启航计划」

前言:很难受距离上一篇文章已经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 文档) image.png

  在我们拿到的设计稿中,设计稿的宽度是375px,高度是812px。taro默认会在使用750px作为设计稿标尺,因此我们需要进行比例的配置:设计稿宽度的配置和设计稿的转换比例。

image.png

image.png   以小程序为例,通过进行转换后,className为me且宽度为375px的盒子的宽度将会自动转换成小程序的750rpx。

image.png

基于sass的bem编写

  taro是支持sass的,可以根据相关的配置进行安装sass并使其生效,这里就不再进行赘述。BEM布局布局也有很多文章对其进行描述,其他人的描述可能会更加详细,我谨在此发表一孔之见。

  对于BEM布局,我们并不需要将其束之高阁,或者理解得很难,其实往简单看,他就是一种css命名规则:

  1. block:块,例如table、input等语义上唯一的块;
  2. element:元素,主要是块的子项;
  3. 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选项,填充相关资源。

image.png   taro可以支持单文件注入、多文件注入的情况,此外,还可以传入相关的字符串进行变量定义,这个时候,通过在scss项定义的全局变量是优先级最高的。 scss编译配置详情 | Taro 文档

checkbox案例的实现———Mocheckbox组件!!!

  到了实战环节了,也是本文出现的原因,如图所示,设计稿中的checkbox在现在的组件库中找不到相似度大的,因此我们需要自己去自定义一个。

image.png

checkbox主要是inputtype=checkbox的时候得到的元素。很多实现方案,如果想简单一点进行应用,或许不需要使用input而使用切换图片的方法。label连接了inputText。(注意:在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得到的样式:

image.png

实现方式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得到的样式:

image.png

由于水平有限,如果有错漏希望大家批评指正。

image.png