国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Babel 在提升前端效率的實踐

chanthuang / 3018人閱讀

摘要:經過一周左右的時間完成了基礎組件的編寫。配置涵蓋了目前的業務場景的基本需求,但是可擴展性很低。最終決定采用的生態鏈來解決上述遇到的問題。在指定的路徑下寫入對應的文件。

大綱

    遇到的問題場景及解決方案對比

    什么是babel?

    解決過程

    目前遺留的問題

    目前實現功能API

    參考

遇到的問題場景及解決方案對比

我們目前采用的是antd + react(umi)的框架做業務開發。在業務開發過程中會有較多頻繁出現并且相似度很高的場景,比如基于一個table的基礎的增刪改查,這個相信大家都非常熟悉。在接到一個新的業務需求的時候,相信有不少人會選擇copy一份功能類似的代碼然后基于這份代碼去改造以滿足當前業務,當然我目前也是這樣做的~

其實想把這塊功能提取成一個公共組建的想法由來已久,最近開始做基礎組件,便拿這個下手了。經過一周左右的時間完成了基礎組件的編寫。

查看基礎支持的功能點API。

基本的思路是通過json生成一些抽象配置,然后通過解析json的抽象配置+渲染器最終生成頁面。json配置涵蓋了目前80%的業務場景的基本需求,但是可擴展性很低。比如一些復雜的業務場景:表單的關聯校驗數據關聯顯示多級列表下鉆等等功能。雖然通過一些較為復雜的處理可以把這些功能融入進來,但最終組件將會異常龐大難以維護。

所以,我能不能通過這些json配置通過某種工具生成對應的代碼?這樣一來以上提到的問題就完全不存在了,因為這和我們自己寫的代碼完全一樣,工具只是幫我們完成初始化的過程。所以后來想了很多辦法,最初采用template string的方式,這種方式較為簡單粗暴,無非通過string中嵌套變量的判斷來輸出code。但是在實際寫的時候發現很多問題,比如

    function的輸出(JSON.stringify會將function忽略)

    多層函數嵌套之后怎么獲取最終渲染的節點code

    嵌入變量怎么實現、umi-models-effects/reducer中額外的字典查詢怎么生成等等..

最終學習了一些生成代碼的工具比如angular-cli以及一些關于js生成代碼的文章,主要是通過知乎上的這篇討論了解到了大家是怎么處理這種問題的。最終決定采用babel的生態鏈來解決上述遇到的問題。

我們目前采用的方式是基于antd+react(umi)編寫通用的CRUD模板,然后通過代碼生成器解析json中的配置生成對應的代碼,大致的流程是:

React --> JavaScript AST ---> Code Generator --> Compiler --> Page

目前功能只是完成了初步版本,待應用在項目中使用一段時間穩定之后將會開源~

什么是babel?

Babel是一個工具鏈,主要用于編譯ECMAScript 2015+代碼轉換為向后兼容的可運行在各種瀏覽器上的JavaScript。主要功能:

    語法轉換

    環境中缺少的Polyfill功能

    源代碼轉換

    查看更多Babel功能

Understanding ASTs by Building Your Own Babel Plugin

如上提供了babel基本的流程及一篇介紹AST的文章。

我的理解中比如一段string類型code,首先通過babel.transform會將code轉為一個包含AST(Abstract Syntax Tree)的Object,同樣可以使用@babel/generator將AST轉為code完成逆向過程。 例如一段變量聲明代碼:

const a = 1;

在解析之后的結構為:

{ "type": "Program", "start": 0, "end": 191, "body": [ { "type": "VariableDeclaration", "start": 179, "end": 191, "declarations": [ { "type": "VariableDeclarator", "start": 185, "end": 190, "id": { "type": "Identifier", "start": 185, "end": 186, "name": "a" }, "init": { "type": "Literal", "start": 189, "end": 190, "value": 1, "raw": "1" } } ], "kind": "const" } ], "sourceType": "module" }

首先類型為VariableDeclaration,首先他的類型是const,可以通過點擊查看api其它還有letvar的值。其次是聲明declarations部分,這里值為數組,因為我們可以同時定義多個變量。數組中值的類型為VariableDeclarator,包含idinit兩個參數,分別為變量名稱以及變量值。id的類型為Identifier,譯為修飾符即是變量名稱。init類型為Literal,即是常量,一般常用的有stringLiteralnumericliteralbooleanliteral等。此時即完成了變量賦值的過程。

當然這只是很簡單的語法轉換,如果大家想學習更多關于轉換及類型的知識,可參考如下兩個官方鏈接:

babel-types

ast轉換工具

解決過程

首先定義目錄結構:

. ├── genCode // 代碼生成器 | ├── genDetail // 需要新頁面打開時多帶帶的detail目錄 | └── genIndex // 首頁 | └── genModels // umi models | └── genServices // umi services | └── genTableFilter // table篩選區域 | └── genTableForm // 非新頁面模式,新增/更新模態框 | └── genUpsert // 新頁面模式下,新增/更新頁面 | └── genUtils // 生成工具類 ├── schema // 模型定義文件 | ├── table // 當前要生成的模型 | └── ├──config.js // 基礎配置 | └── └──dataSchema.js // 列表、新增、更新配置 | └── └──querySchema.js // 篩選項配置 ├── scripts // 生成腳本 | ├── generateCode.js // 生成主文件 | └── index.js // 入口 | └── utils.js // 工具類 ├── toCopyFiles // 生成時需要拷貝的文件,比如less └── index.js // 主入口

主體流程為:

    指定要生成代碼的路徑。

    根據schema中當前json配置路徑,依次調用genCode目錄中各個模塊的代碼生成方法獲取對應code。

    在指定的路徑下寫入對應的文件。

    執行eslint ${filePath} --fix格式化生成的代碼。

    根據配置對應復制toCopyFiles文件夾中依賴的less等文件到對應的文件夾。

其中主要模塊為genCode文件夾中根據json配置生成代碼的過程。 以genModels為例,首先提取可以使用template string完成的部分,減少代碼解析的工作量。

module.exports = (tableConfig) => { return ` import { message } from "antd"; import { routerRedux } from "dva/router" import { parse } from "qs" ${dynamicImport(dicArray, namespace)} export default { namespace: "${namespace}", state: { ... }, effects: { *fetch({ payload }, { call, put }) { const response = yield call(queryData, payload); if (response && response.errorCode === 0) { yield put({ type: "save", payload: response.data, }); } else { message.error(response && response.errorMessage || "請求失敗") } }, ..., ${dynamicYieldFunction(dicArray)} }, reducers: { save(state, action) { return { ...state, data: action.payload, }; }, ..., ${dynamicReducerFunction(dicArray)} }, }; ` }

因為列表數據可能有字典項從后臺獲取值來對應顯示,所以importeffectsreducers模塊均有需根據配置動態生成的代碼。 以dynamecImport為例:

function dynamicImport (dicArray, namespace) { // 基礎api import let baseImport = [ "queryData", "removeData", "addData", "updateData", "findById" ] // 判斷json數據中是否有需從后臺加載項 if (dicArray && dicArray.length) { baseImport = baseImport.concat(dicArray.map(key => getInjectVariableKey(key))) } // 遍歷生成依賴項 const _importDeclarationArray = map(specifier => ( _importDeclarationArray.push(t.importSpecifier(t.identifier(specifier), t.identifier(specifier))) )) // 定義importDeclaration const ast = t.importDeclaration( _importDeclarationArray, t.stringLiteral(`../services/${namespace}`) ) // 通過@babel/generator 將ast生成code const { code } = generate(ast) return code }

其它代碼生成邏輯類似,有不確定如何生成的部分可參考上方提供的鏈接完成代碼轉換再去生成。

若有通過babel轉換無法生成的代碼,可通過正則來完成。

例如以下umi-models代碼:

*__dicData({ payload }, { call, put }) { const response = yield call(__dicData, payload); if (response && response.errorCode === 0) { yield put({ type: "updateDic", payload: response.data, }); } else { message.error(response && response.errorMessage || "請求失敗") } }

基礎代碼可通過yieldExpression生成,但是轉換之后無function之后的*符號,反復查了文檔之后沒有解決辦法,最后只能將生成完的code利用正則替換來解決。 如果大家有遇到類似的問題歡迎討論~

問題

    目前使用的編輯器組件為braft-editor,但是結合antd使用initialValue不生效,必須使用setFieldsValue。但是使用useEffects時會默認添加props.form作為依賴并且props.form會不斷變化而觸發死循環,目前無奈只有禁用eslint react-hooks/exhaustive-deps。

useEffect(() => { props.form.setFieldsValue({ editorArea: BraftEditor.createEditorState(current.editorArea), editorArea2: BraftEditor.createEditorState(current.editorArea2) }); }, [current.editorArea, current.editorArea2]);

    生成的代碼怎么刪除未使用的依賴?使用eslint --fix不會刪除未使用的變量定義。

    初始化之后的代碼要修改怎么辦?因當前方法只會完成代碼初始化過程,以后修改的過程暫無思路解決。

功能API

參數規范參考react-antd-admin 功能配置包含三個基礎配置文件:

config.json配置基本屬性

dataSchema.json配置列表及新增修改字段

querySchema.json配置篩選區域字段

config.json

配置列表

參數 必填 類型 默認值 說明
namespace true string null 命名空間
showExport false boolean true 是否顯示導出
showCreate false boolean true 是否顯示創建
showDetail false boolean true 是否顯示查看
showUpdate false boolean true 是否顯示修改
showDelete false boolean true 是否顯示刪除
newRouterMode false boolean false 在新的頁面新增/編輯/查看詳情。若包含富文本編輯器,建議此值設為true,富文本在模態框展示不是非常美觀。
showBatchDelete false boolean true 是否顯示批量刪除,需multiSelection為 true
multiSelection false boolean true 是否支持多選
defaultDateFormat false string "YYYY-MM-DD" 日期格式
upload false object null 上傳相關配置,上傳圖片和上傳普通文件分別配置。 詳見下方upload屬性
pagination false object null 分頁相關配置, 詳見下方pagination屬性
dictionary false array null 需要請求的字典項,用于下拉框或treeSelect的值為從后端獲取的情況,可在dataSchema 和querySchema中使用, 詳見下方dictionary屬性

upload

參數 必填 類型 默認值 說明
uploadUrl false string null 默認的上傳接口.優先級image/fileApiUrl > uploadUrl > Global.apiPath
imageApiUrl false string null 默認的圖片上傳接口
fileApiUrl false string null 默認的文件上傳接口
image false string "/uploadImage" 默認的上傳圖片接口
imageSizeLimit false number 1500 默認的圖片大小限制, 單位KB
file false string "/uploadFile" 默認的上傳文件接口
fileSizeLimit false number 10240 默認的文件大小限制, 單位KB

pagination

參數 必填 類型 默認值 說明
pageSize false number 10 每頁顯示數量
showSizeChanger false boolean false 是否可以改變pageSize
pageSizeOptions false array ["10", "20", "50", "100"] 指定每頁可以顯示多少條
showQuickJumper false boolean false 是否可以快速跳轉至某頁
showTotal false boolean true 是否顯示總數

dictionary

參數 必填 類型 默認值 說明
key true string null 變量標識
url true string null 請求數據地址

dataSchema.json

配置列表

參數 必填 類型 默認值 說明
key true string null 唯一標識符
title true string null 顯示名稱
primary false boolean false 主鍵 如果不指定主鍵, 不能update/delete, 但可以insert;
如果指定了主鍵, insert/update時不能填寫主鍵的值;
showType false string input 顯示類型
input/textarea/inputNumber/datePicker/rangePicker/radio/select/checkbox/multiSelect/image/file/cascader/editor
disabled false boolean false 表單中這一列是否禁止編輯
addonBefore false string/ReactNode null showType 為input可以設置前標簽
addonAfter false string/ReactNode null showType 為input可以設置后標簽
placeholder false string null 默認提示文字
format false string null 日期類型的格式
showInTable false boolean true 這一列是否要在table中展示
showInForm false boolean true 是否在新增或編輯的表單中顯示
validator false boolean null 設置校驗規則, 參考https://github.com/yiminghe/async-validator#rules
width false string/number null 列寬度
options false array null format:[{ key: "", value: "" }]或string。showType為cascader時,此字段暫不支持Array,數據只能通過異步獲取。
min false number null 數字輸入的最小值
max false number null 數字輸入的最大值
accept false string null 上傳文件格式限制
sizeLimit false number 20480 上傳文件格式限制
url false string null 上傳圖片url。圖片的上傳接口, 可以針對每個上傳組件多帶帶配置, 如果不多帶帶配置就使用config.js中的默認值;如果這個url是http開頭的, 就直接使用這個接口; 否則會根據config.js中的配置判斷是否加上host
sorter false boolean false 是否排序
actions false array null 操作

actions

參數 必填 類型 默認值 說明
keys false array null 允許更新哪些字段, 如果不設置keys, 就允許更所有字段
name true string null 展示標題
type false string null update/delete/newLine/component

querySchema.json

配置列表

參數 必填 類型 默認值 說明
key true string null 唯一標識符
title true string null 顯示名稱
placeholder false string null 提示語
showType false string input 顯示類型, 一些可枚舉的字段, 比如type, 可以被顯示為單選框或下拉框
input, 就是一個普通的輸入框, 這時可以省略showType字段
目前可用的showType: input/inputNumber/datePicker/rangePicker/select/radio/checkbox/multiSelect/cascader
addonBefore false string/ReactNode null showType 為input可以設置前標簽
addonAfter false string/ReactNode null showType 為input可以設置后標簽
defaultValue false string/array/number null 多選的defaultValue是個數組
min false number null showType為 inputNumber 時可設置最小值
max false number null showType為 inputNumber 時可設置最大值
options false array null options的key要求必須是string, 否則會有warning
normal-format: [{"key": "", "value": ""}]
cascader-format: [{"value": "", "label": "", children: ["value": "", "label": "", children: []]}]
如果值為string,代表異步獲取的數據,則獲取當前命名空間下該key對應的值
defaultValueBegin false string null showType為 rangePicker 時可設置默認開始值
defaultValueEnd false string null showType為 rangePicker 時可設置默認結束值
placeholderBegin false string 開始日期 showType為 rangePicker 時可設置默認開始提示語
placeholderEnd false string 結束日期 showType為 rangePicker 時可設置默認結束提示語
format false string null 日期篩選格式
showInSimpleMode false boolean false 在簡單查詢方式下展示,若數據中有一項包含此字段且為true的值,則開啟簡單/復雜篩選切換

參考

react-antd-admin

AST語法轉換器

babel-types-api

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/6655.html

相關文章

  • babel提升前端效率實踐

    摘要:配置涵蓋了目前的業務場景的基本需求,但是可擴展性很低。最終決定采用的生態鏈來解決上述遇到的問題。在指定的路徑下寫入對應的文件。 大綱 遇到的問題場景及解決方案對比 什么是babel? 解決過程 目前遺留的問題 目前實現功能API 參考 遇到的問題場景及解決方案對比 我們目前采用的是antd + react(umi)的框架做業務開發。在業務開發過程中會有較多頻繁出現并且相似度很高的場...

    huayeluoliuhen 評論0 收藏0
  • Taro 簡介

    摘要:讓人又愛又恨的微信小程序自微信小程序以下簡稱小程序誕生以來,就伴隨著贊譽與爭議不斷。同時于開發者來說,小程序的生態不斷在完善,許多的坑已被踩平,雖然還是存在一些令人詬病的問題,但已經足見微信的誠意了。 Taro 介紹 在互聯網不斷發展的今天,前端程序員們也不斷面臨著新的挑戰,在這個變化多端、不斷革新自己的領域,每一年都有新的美好事物在發生。從去年微信小程序的誕生,到今年的逐漸火熱,以及...

    sixgo 評論0 收藏0
  • 《從零構建前后分離web項目》:前端了解過關了嗎?

    摘要:前端基礎架構和硬核介紹技術棧的選擇首先我們構建前端架構需要對前端生態圈有一切了解,并且最好帶有一定的技術前瞻性,好的技術架構可能日后會方便的擴展,減少重構的次數,即使重構也不需要大動干戈,我通常選型技術棧會參考以下三點一提出自身業務的需求是 # 前端基礎架構和硬核介紹 showImg(https://segmentfault.com/img/remote/146000001626972...

    lbool 評論0 收藏0
  • 《從零構建前后分離web項目》:前端了解過關了嗎?

    摘要:前端基礎架構和硬核介紹技術棧的選擇首先我們構建前端架構需要對前端生態圈有一切了解,并且最好帶有一定的技術前瞻性,好的技術架構可能日后會方便的擴展,減少重構的次數,即使重構也不需要大動干戈,我通常選型技術棧會參考以下三點一提出自身業務的需求是 # 前端基礎架構和硬核介紹 showImg(https://segmentfault.com/img/remote/146000001626972...

    cgspine 評論0 收藏0
  • 《從零構建前后分離web項目》:前端了解過關了嗎?前端基礎架構和硬核介紹

    摘要:前端準備前端了解過關了嗎前端基礎架構和硬核介紹技術棧的選擇首先我們構建前端架構需要對前端生態圈有一切了解,并且最好帶有一定的技術前瞻性,好的技術架構可能日后會方便的擴展,減少重構的次數,即使重構也不需要大動干戈,我通常選型技術棧會參考以下三 # 前端準備 :前端了解過關了嗎?前端基礎架構和硬核介紹 showImg(https://segmentfault.com/img/remote/...

    SwordFly 評論0 收藏0

發表評論

0條評論

chanthuang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<