這是 Jerry 2021 年的第 36 篇文章,也是汪子熙公衆號總共第 312 篇原創文章。css
Jerry 以前寫的 SAP Fiori Elements 系列文章:前端
關於 List Report 模板裏 Smart Table 控件裏不一樣列項目的寬度問題,也有不少朋友私下裏問我: canvas
好比這個問題:服務器
「當我生成頁面的時候,column 沒有用光控件的空間,在傳統開發上,咱們能夠操控 column 的 width 屬性。可是在Fiori Elements 開發中並無碰到相應的參數。 請問您知道我能夠經過什麼參數控制嘛?」框架
由於我平常工做用的是 Angular 而非 SAP Fiori Elements,因此這些問題只有業餘時間研究。此類問題我一般的作法是,在設法尋找解決方案以前 (如何經過代碼調整 Smart Table 列項目的寬度),先作一些調研,搞清楚當前行爲的實現原理。這樣下次遇到新的列項目寬度的相關需求,以前調研學到的知識說不定可以重用。函數
Jerry 以前的文章 SAP Fiori Elements 框架裏 Smart Table 控件的工做原理介紹,向你們揭祕了 Smart Table 控件裏的列項目,來自 OData 元數據裏擁有 com.sap.vocabiularies.UI.LineItem 註解的模型字段。可是當時咱們沒有關於列項目的寬度 (width) 進行討論。工具
在 Chrome 開發者工具裏,查看任意兩個列項目的寬度,發現單位均爲 rem:編碼
px, em 和 rem 都是 css 的長度單位,其中 px 即像素,相對於顯示器屏幕分辨率而言,在互聯網早期應用裏使用得比較多。而 em 和 rem 是相對長度單位,前者相對於其父元素,後者相對於文檔根元素,在響應式頁面設計裏普遍使用。spa
經過 Jerry 以前這篇文章 Jerry的Fiori原創文章合集 裏介紹的調試技巧,我成功找到了 Smart Table 運行時計算列項目寬度的代碼位置。簡言之,Fiori Elements List Report 模板裏 Smart Table 每一個列項目的初始寬度,一樣取決於其 OData 元數據。設計
打開 Chrome 開發者工具,切換到 Sources 標籤頁,快捷鍵 Ctrl + O,在彈出對話框裏輸入 SmartTable,這樣能夠快速打開其實現文件 SmartTable.js:
該文件第 3817 行,_calcCoumnWidth 函數, 即 Smart Table 列項目寬度的計算實現源代碼。
從源代碼裏的註釋可知,Fiori Elements 基於 OData 元數據裏的屬性來計算列項目的寬度 (Calculates the column width from the metadata attributes).
The optimal column width is calculated with creating the longest possible sample of the created model type.
根據模型字段的類型,構造出該類型容許的最長內容的例子數據,便可計算出該列理論上的寬度。
計算列項目寬度函數 calcCoumnWidth 的輸入參數:
這個函數實現代碼裏信息量很大:
計算寬度使用的配置對象,mConfig 的值,是在代碼裏以近似硬編碼的方式填充的。從上圖可以看出,Fiori Elements Smart Table 的列項目寬度,最大值爲 19;若是計算時不考慮額外屬性,最小寬度值爲 2,不然爲 1;若是 OData 元數據裏提供的屬性,不足以計算出一個合適的寬度值,則使用代碼第 3822 行維護的默認寬度:在考慮額外屬性狀況下,默認寬度爲 4,不然爲 8;單位爲 rem.
接下來爲計算列項目寬度作準備。
第 3833 行的字符 w, 是爲了針對字段元數據類型爲 Edm.String, 即字符串類型的列項目作準備的。此類型字段,在元數據裏還有另外一個屬性 MaxLength, 即字符串最大長度。
例如一個 MaxLength 爲 40 的字符串類型字段,Smart Table 計算其寬度的邏輯就是,運行時生成一個由 40 個 w 字符組成的字符串,計算其渲染出來後佔據的寬度,將該寬度值做爲此列項目最終顯示在界面上的寬度。
字段類型不一樣,其理論上最長的可能值也不一樣。好比上圖第 3842 行開始的代碼提到,類型 Edm.Int16, 理論的最長值爲 32768, 佔據 5 個字符的位置;Edm.Int32 則理論最多佔據 9 個字符位,由於其最大值爲 2147483648. 依次類推。
下圖的 4 個 IF-ELSE 分支,分別對應着類型爲 Byte, Time, Boolean 和 String 字段的寬度計算。下面咱們來了解最簡單的字符串類型的列項目寬度計算邏輯。
下圖三個標號處的主要邏輯:字段 MainProductCategory, 類型爲 Edm.String, 最大長度爲 40 個字符,所以標號 3 處,將變量 sChar 表明的字符 w,重複 40 次後生成一個新的字符串,而後調用函數 measureText, 計算該字符串渲染出來的寬度。
在 measureText 函數內部,第 3792 行動態建立一個 canvas 標籤,該標籤經常使用於 JavaScript 動態繪製圖形的場景。拿到 canvas 的 2d 上下文後,調用其原生 API,measureText,獲得在該 canvas 上渲染長度爲 40 的字符串須要佔據的寬度,單位爲 px,最後再除以 baseFontSize, 換算成 rem 單位。
計算出來的列項目寬度,會存儲在 column 對象實例裏,並在最終的 HTML 代碼渲染過程裏,交給 TableRenderer 進行 width 渲染。這就是咱們在本文開始的 Chrome 開發者工具裏,觀察到 HTML 源代碼裏 th 元素的 CSS style 面板裏的 width 屬性。
至此,本文介紹了 SAP Fiori Elements List Report Smart Table 列項目的初始寬度計算邏輯。從以上邏輯你們不難發現,寬度計算是根據字段元數據的 MaxLength 屬性,而不是運行時該字段實際的顯示值,於是會出現某些朋友抱怨的「雖然某列顯示的內容不多,但仍是佔據了很寬的空間,致使屏幕空間利用率不夠"的問題, 以下圖所示:
另外,咱們點擊 Settings 按鈕進行個性化設置:
讓 Smart Table 運行時只顯示兩列:
以後顯示的頁面,確實只包含咱們在個性化設置裏選擇的 Image 和 Product 兩列,然而它們的寬度,和個性化以前相比並未發生變化,所以頁面很是難看:
Jerry 後續的 SAP Fiori Elements 系列文章,會介紹如何解決這個寬度沒可以動態更新的問題,敬請期待。
更多閱讀
更多Jerry的原創文章,盡在:"汪子熙":