组件开发指南
组件分类
首先应了解组件分类。
原子组件:
- 仅通过传参方式改变自身状态的组件,都属于原子组件。
- 原子组件往下可以按功能性划分出:布局组件、容器组件、样式组件等等。
- 原子组件一般都是函数式组件以适应 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
## 设计稿 - 截图预览

## 设计稿 - 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();
代替。