共计 1244 个字符,预计需要花费 4 分钟才能阅读完成。
前言
最近在使用 Vue+TypeScript 鼓捣自己的组件库,期间参考不少(抄????)element,iview的源码。发现了一些常用的功能的背后,往往是复杂的实现。于是准备写一系列文章,介绍这些组件背后的原理。今天是第二篇,手把手带你实现 Grid 组件。
API 设计
按照惯例我们首先参考一下 iview 和 element 组件的接口设计, 栅格组件主要分为两个部分,行(Row)和列(Col)。
Row 组件 Props | 解释 |
---|---|
gutter | 每一列之间的间距,指定像素。 |
Col 组件 Props | 解释 |
---|---|
span | 列的宽度,通常是 1~24 之间的数字 |
offset | 指定列的偏移量 |
Row
模版设计
没什么好说的,直接使用 slot 插槽,用来替换插入的 Col 组件。
Props.gutter
Props.gutter 是每一列的栅格间距,按道理说每一列的栅格间距应该是 Col 的属性,但是为了方便起见,不可能为每一个 Col 组件设置 gutter 的属性。所以统一设置在 Row 组件上,那我们如何将 Row 上的属性,设置到 Col 上呢?
我们首先定义两个工具函数,代码如下:
findChildsComponentByLevel,会查找指定组件的指定名称的子组件,并且可以指定查找的层级 。
findChildsComponentByLevel 方法主要利用的是组件实例的 $children 属性,和 $options.name 属性。$children 属性表示 ** 当前实例的直接子组件 **。而 $options.name 则表示组件初始化时指定的 name 属性。在工具函数的内部利用 递归 的形式,向下按层级查找特定名称的子组件。
findChildsComponentByFirstLevel 方法则是对 findChildsComponentByLevel 方法的封装,用来查找第一层子组件。
我们在组件内部定义了 handleGutterChange 方法,并使用 watch 监听 gutter 属性的变化,每一次 gutter 变化的时候,都会通过 handleGutterChange 方法,将 gutter 属性更新到 col 组件上。
Col
模版设计
比较简单这里不在赘述
Data.gutter
我们在 Row 组件中,通过查找 $children 的方法,将 gutter 属性更新到了 Row 组件上。
在 Row 组件内部,利用计算属性,监听缓存计算 gutter 属性。并将对应 gutter 转换为对应的样式,更新到 Row 组件的:style 属性上。实现 gutter 功能。
offset, span
offset, span 的实现,是单纯依靠 css 实现的。使用 less 的循环递归
形成 row-span-1, row-span-2, row-span-3, row-span-4…… 的 css 类。然后使用 less 内置 percentage 函数,动态的生成 css 的 width 属性。
最后我们只需要通过计算属性,动态的生成 col 的 css 类名,与 row-span-1,row-span-2,row-span-3…… 对应上即可
参考
- iview 源码
- element 源码