Skip to content

组件开发指南

组件分类

首先应了解组件分类。

原子组件:

  • 仅通过传参方式改变自身状态的组件,都属于原子组件。
  • 原子组件往下可以按功能性划分出:布局组件、容器组件、样式组件等等。
  • 原子组件一般都是函数式组件以适应 Vue 和 React 环境。

高级组件:

  • 高级组件目的是通过深度组合各种原子组件,覆盖更高一层的使用场景。
  • 高级组件一般会有很多交互逻辑,且可能会对上下文造成影响,产生一定的副作用 (Effects)。
  • 高级组件需要使用很多框架特性,因此在适配 Vue 和 React 时,内部代码实现一般不同。

注意 YTUI 的高级组件,与 React 的高阶组件概念不同,二者不相等。

基本规范

每个组件都要遵循的基本规范。

  • 在设计上符合 YTUI 设计原则及规范。
  • 支持日间和暗黑两种模式。
  • 支持横纵布局。
  • 可在 React 和 Vue 两种环境下使用。

原型设计

使用 Figma 进行构思并建立组件原型。遵循以下规范:

  • 每个组件单独一个 Figma Design Page。
  • 各图层必须命名,使用小写加横杠(与 CSS 命名规则一致),对后期写样式代码起到指导作用。
  • 在用于汇总演示的 Page - Overview 加入该组件的引用。

样式要求

  • 每个组件独立样式文件。样式文件放组件自己的文件夹内,统一命名为 index.suffix,例如 TheComponent/index.less
    • 局部作用域的样式文件,在自己的组件 vue/js/jsx 文件内 import
    • 全局公开的样式,必须在 styles/index.less 统一 import,保证只引入一次。
  • 使用 BEM 命名法。块(block)、元素(element)、修饰符(modifier)。
  • 用 > 号精准地定义子元素样式,任何情况下(例如没 scoped)都不会出现样式污染。
  • 支持横纵两种布局的组件样式,对应命名 block--x block--y 其中 x 指横向 y 指纵向。使用 x/y 比 v/h 更直观,因为我们中国人从小就接触数学的 x/y 坐标轴了,深深地刻在脑海里,x 就是横的,y 就是竖的,不需思考。
  • 不用 fixed 定位。fixed 的元素会直接脱离整个组件,挂到文档上,使组件的适应性变弱。我们应通过布局的手段分割各个区域,实现顶栏侧栏等元素的固定效果。
  • 颜色统一用 rgb() 利于在 CSS 预处理器中做运算。

横纵布局

纵向布局,一般在宽度有限的情况下使用。
横向布局,一般在高度有限的情况下使用。

全局有一个关于横纵布局的断点,用于组件的布局自适应功能。

对于独占整个父元素宽/高的块级别组件:

  • 按移动优先的原则,默认适配纵向布局的环境。能在有限宽度的条件下显示优良;同时在宽度富裕时即使会被拉伸,但依然能正常工作。
  • 部分组件有适配横纵两种布局,默认使用纵向布局。可通过组件参数 layout 选择要使用 x/y 哪种布局。若 layout="auto" 则为布局自适应,会根据全局的横纵布局断点启用指定布局。

行内级别的组件:

  • 身材上的天生优势,几乎可适应任何布局情况。
  • 部分组件提供 block 参数,可使其变为简单的块元素以撑满父元素宽/高,使其在纵向布局环境中可用性更佳。

组件默认开启自适应功能,有特殊需要时可通过传参来固定横/纵布局的显示。

组件源码要求

为方便其它项目以源码方式使用YTUI,各组件内部间的 import 引用应使用相对路径,不使用 @root 等的 alias。
同时,使用了 alias 也会对 IDE 的代码提示等功能产生影响。

子组件应严格不修改 props 并且不要监听 props 的变化。

  • 你的 Vue 子组件几乎没有任何理由要监听 Props 的变化,因为 Props 本来就是自上而下传递的,上层的传参有变化,下层不需要知道。Vue 子组件只需要在各个生命周期钩子中,根据当前的 props 管理好自己即可。应保始终持该关于 props 的简单逻辑不变,即把 props 理解为函数的输入(传参),彻底与组件生命周期分开来理解,切忌混淆。
  • YTUI 的组件必须能适应 Vue 和 React 两个框架。由于 React 中没有原生支持类似 Vue 的 watch props 机制,你的代码逻辑将无法适应 react 环境,让兼容 react 变得困难。最终需要做很多额外工作,甚至要为组件额外开发一套独立的 react 版本,得不偿失,难以维护。
  • 保持 props 机制的简单顺畅,有利于 YTUI 核心 UI 链的实现。

文档要求

  • YTUI 非常重视文档的编写,详细文档是一切的前提,不可马虎。
  • 侧栏的标题要和文档大标题 # Title 完全一致。与此同时,页面的 <title> 标签也是根据该大标题动态生成的,因此保持标题的一致性非常必要。
  • 为方便查阅文档,所有组件文档必须展示大纲(将 frontmatter 内指定 aside 为 true):
    md
    ---
    aside: true
    ---
  • 设计相关的文档不需展示大纲。

组件文档目录结构(以 Button 组件为例)

  • root/ 源码根目录
    • docs/components/button/ 组件文档主目录
      • design.md 设计,必须有
      • doc.md 主文档,必须有
      • react-demo.md 演示 (React 环境)
      • vue-demo.md 演示 (Vue 环境)

design.md 模板

md
---
aside: false
---

# 设计 Design

## 设计稿 - 截图预览

![](design.svg)

## 设计稿 - Figma 原件

<iframe class="figma" src="https://www.figma.com/embed?embed_host=share&url=xxx" allowfullscreen></iframe>

doc.md 模板

md
---
aside: true # 文档需有大纲,方便查阅
---

<script setup>
import Example from './example.jsx'
</script>

## API

::: table

| Name | Desc | Type | Default | Vue Only | React Only |
| ---- | ---- | ---- | ------- | -------- | ---------- |

:::

<!-- 标题上方空两行,方便阅读 -->
## Usage

<Example />

<<< example.jsx

命名规范

  • 目录名称统一用 abc 小写,连字符使用 - 横杠。

JSX 在 Vue 与 React 的兼容性注意事项

事件名不一致

以鼠标事件为例,React 是事件名所有单词首字母大写 onMouseEnter,Vue 是事件名全小写 onMouseenter

浏览器兼容性

应兼容全部国内主流 Browser 的最新版。

PC 端:

  • Chrome
  • Edge

移动端:

  • 夸克
  • Chrome
  • Safari

注意事项:

  • 移动端夸克不支持单独的 translate: x y z; 属性,必须用 transform: translate(); 代替。