最近在使用Vue+TypeScript鼓搗本身的組件庫,期間參考很多(抄😂)element,iview的源碼。發現了一些經常使用的功能的背後,每每是複雜的實現。因而準備寫一系列文章,介紹這些組件背後的原理。今天是第二篇,手把手帶你實現Grid組件。css
按照慣例咱們首先參考一下iview和element組件的接口設計, 柵格組件主要分爲兩個部分,行(Row)和列(Col)。git
Row組件Props | 解釋 |
---|---|
gutter | 每一列之間的間距,指定像素。 |
Col組件Props | 解釋 |
---|---|
span | 列的寬度,一般是1~24之間的數字 |
offset | 指定列的偏移量 |
沒什麼好說的,直接使用slot插槽,用來替換插入的Col組件。github
Props.gutter是每一列的柵格間距,按道理說每一列的柵格間距應該是Col的屬性,可是爲了方便起見,不可能爲每個Col組件設置gutter的屬性。因此統一設置在Row組件上,那咱們如何將Row上的屬性,設置到Col上呢?緩存
咱們首先定義兩個工具函數,代碼以下:less
findChildsComponentByLevel,會查找指定組件的指定名稱的子組件,而且能夠指定查找的層級。 findChildsComponentByLevel方法主要利用的是組件實例的options.name屬性。iview
$children屬性表示當前實例的直接子組件。函數
而$options.name則表示組件初始化時指定的name屬性。工具
在工具函數的內部利用遞歸的形式,向下按層級查找特定名稱的子組件。spa
findChildsComponentByFirstLevel方法則是對findChildsComponentByLevel方法的封裝,用來查找第一層子組件。設計
咱們在組件內部定義了handleGutterChange方法,並使用watch監聽gutter屬性的變化,每一次gutter變化的時候,都會經過handleGutterChange方法,將gutter屬性更新到col組件上。
比較簡單這裏不在贅述
咱們在Row組件中,經過查找$children的方法,將gutter屬性更新到了Row組件上。
在Row組件內部,利用計算屬性,監聽緩存計算gutter屬性。並將對應gutter轉換爲對應的樣式,更新到Row組件的:style屬性上。實現gutter功能。
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...對應上便可