亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Babel 在提升前端效率的實(shí)踐

chanthuang / 3099人閱讀

摘要:經(jīng)過(guò)一周左右的時(shí)間完成了基礎(chǔ)組件的編寫(xiě)。配置涵蓋了目前的業(yè)務(wù)場(chǎng)景的基本需求,但是可擴(kuò)展性很低。最終決定采用的生態(tài)鏈來(lái)解決上述遇到的問(wèn)題。在指定的路徑下寫(xiě)入對(duì)應(yīng)的文件。

大綱

    遇到的問(wèn)題場(chǎng)景及解決方案對(duì)比

    什么是babel?

    解決過(guò)程

    目前遺留的問(wèn)題

    目前實(shí)現(xiàn)功能API

    參考

遇到的問(wèn)題場(chǎng)景及解決方案對(duì)比

我們目前采用的是antd + react(umi)的框架做業(yè)務(wù)開(kāi)發(fā)。在業(yè)務(wù)開(kāi)發(fā)過(guò)程中會(huì)有較多頻繁出現(xiàn)并且相似度很高的場(chǎng)景,比如基于一個(gè)table的基礎(chǔ)的增刪改查,這個(gè)相信大家都非常熟悉。在接到一個(gè)新的業(yè)務(wù)需求的時(shí)候,相信有不少人會(huì)選擇copy一份功能類(lèi)似的代碼然后基于這份代碼去改造以滿足當(dāng)前業(yè)務(wù),當(dāng)然我目前也是這樣做的~

其實(shí)想把這塊功能提取成一個(gè)公共組建的想法由來(lái)已久,最近開(kāi)始做基礎(chǔ)組件,便拿這個(gè)下手了。經(jīng)過(guò)一周左右的時(shí)間完成了基礎(chǔ)組件的編寫(xiě)。

查看基礎(chǔ)支持的功能點(diǎn)API。

基本的思路是通過(guò)json生成一些抽象配置,然后通過(guò)解析json的抽象配置+渲染器最終生成頁(yè)面。json配置涵蓋了目前80%的業(yè)務(wù)場(chǎng)景的基本需求,但是可擴(kuò)展性很低。比如一些復(fù)雜的業(yè)務(wù)場(chǎng)景:表單的關(guān)聯(lián)校驗(yàn)、數(shù)據(jù)關(guān)聯(lián)顯示多級(jí)列表下鉆等等功能。雖然通過(guò)一些較為復(fù)雜的處理可以把這些功能融入進(jìn)來(lái),但最終組件將會(huì)異常龐大難以維護(hù)。

所以,我能不能通過(guò)這些json配置通過(guò)某種工具生成對(duì)應(yīng)的代碼?這樣一來(lái)以上提到的問(wèn)題就完全不存在了,因?yàn)檫@和我們自己寫(xiě)的代碼完全一樣,工具只是幫我們完成初始化的過(guò)程。所以后來(lái)想了很多辦法,最初采用template string的方式,這種方式較為簡(jiǎn)單粗暴,無(wú)非通過(guò)string中嵌套變量的判斷來(lái)輸出code。但是在實(shí)際寫(xiě)的時(shí)候發(fā)現(xiàn)很多問(wèn)題,比如

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

    多層函數(shù)嵌套之后怎么獲取最終渲染的節(jié)點(diǎn)code

    嵌入變量怎么實(shí)現(xiàn)、umi-models-effects/reducer中額外的字典查詢(xún)?cè)趺瓷傻鹊?.

最終學(xué)習(xí)了一些生成代碼的工具比如angular-cli以及一些關(guān)于js生成代碼的文章,主要是通過(guò)知乎上的這篇討論了解到了大家是怎么處理這種問(wèn)題的。最終決定采用babel的生態(tài)鏈來(lái)解決上述遇到的問(wèn)題。

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

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

目前功能只是完成了初步版本,待應(yīng)用在項(xiàng)目中使用一段時(shí)間穩(wěn)定之后將會(huì)開(kāi)源~

什么是babel?

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

    語(yǔ)法轉(zhuǎn)換

    環(huán)境中缺少的Polyfill功能

    源代碼轉(zhuǎn)換

    查看更多Babel功能

Understanding ASTs by Building Your Own Babel Plugin

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

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

const a = 1;

在解析之后的結(jié)構(gòu)為:

{ "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" }

首先類(lèi)型為VariableDeclaration,首先他的類(lèi)型是const,可以通過(guò)點(diǎn)擊查看api其它還有let、var的值。其次是聲明declarations部分,這里值為數(shù)組,因?yàn)槲覀兛梢酝瑫r(shí)定義多個(gè)變量。數(shù)組中值的類(lèi)型為VariableDeclarator,包含idinit兩個(gè)參數(shù),分別為變量名稱(chēng)以及變量值。id的類(lèi)型為Identifier,譯為修飾符即是變量名稱(chēng)。init類(lèi)型為Literal,即是常量,一般常用的有stringLiteralnumericliteral、booleanliteral等。此時(shí)即完成了變量賦值的過(guò)程。

當(dāng)然這只是很簡(jiǎn)單的語(yǔ)法轉(zhuǎn)換,如果大家想學(xué)習(xí)更多關(guān)于轉(zhuǎn)換及類(lèi)型的知識(shí),可參考如下兩個(gè)官方鏈接:

babel-types

ast轉(zhuǎn)換工具

解決過(guò)程

首先定義目錄結(jié)構(gòu):

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

主體流程為:

    指定要生成代碼的路徑。

    根據(jù)schema中當(dāng)前json配置路徑,依次調(diào)用genCode目錄中各個(gè)模塊的代碼生成方法獲取對(duì)應(yīng)code。

    在指定的路徑下寫(xiě)入對(duì)應(yīng)的文件。

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

    根據(jù)配置對(duì)應(yīng)復(fù)制toCopyFiles文件夾中依賴(lài)的less等文件到對(duì)應(yīng)的文件夾。

其中主要模塊為genCode文件夾中根據(jù)json配置生成代碼的過(guò)程。 以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 || "請(qǐng)求失敗") } }, ..., ${dynamicYieldFunction(dicArray)} }, reducers: { save(state, action) { return { ...state, data: action.payload, }; }, ..., ${dynamicReducerFunction(dicArray)} }, }; ` }

因?yàn)榱斜頂?shù)據(jù)可能有字典項(xiàng)從后臺(tái)獲取值來(lái)對(duì)應(yīng)顯示,所以import、effectsreducers模塊均有需根據(jù)配置動(dòng)態(tài)生成的代碼。 以dynamecImport為例:

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

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

若有通過(guò)babel轉(zhuǎn)換無(wú)法生成的代碼,可通過(guò)正則來(lái)完成。

例如以下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 || "請(qǐng)求失敗") } }

基礎(chǔ)代碼可通過(guò)yieldExpression生成,但是轉(zhuǎn)換之后無(wú)function之后的*符號(hào),反復(fù)查了文檔之后沒(méi)有解決辦法,最后只能將生成完的code利用正則替換來(lái)解決。 如果大家有遇到類(lèi)似的問(wèn)題歡迎討論~

問(wèn)題

    目前使用的編輯器組件為braft-editor,但是結(jié)合antd使用initialValue不生效,必須使用setFieldsValue。但是使用useEffects時(shí)會(huì)默認(rèn)添加props.form作為依賴(lài)并且props.form會(huì)不斷變化而觸發(fā)死循環(huán),目前無(wú)奈只有禁用eslint react-hooks/exhaustive-deps。

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

    生成的代碼怎么刪除未使用的依賴(lài)?使用eslint --fix不會(huì)刪除未使用的變量定義。

    初始化之后的代碼要修改怎么辦?因當(dāng)前方法只會(huì)完成代碼初始化過(guò)程,以后修改的過(guò)程暫無(wú)思路解決。

功能API

參數(shù)規(guī)范參考react-antd-admin 功能配置包含三個(gè)基礎(chǔ)配置文件:

config.json配置基本屬性

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

querySchema.json配置篩選區(qū)域字段

config.json

配置列表

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

upload

參數(shù) 必填 類(lèi)型 默認(rèn)值 說(shuō)明
uploadUrl false string null 默認(rèn)的上傳接口.優(yōu)先級(jí)image/fileApiUrl > uploadUrl > Global.apiPath
imageApiUrl false string null 默認(rèn)的圖片上傳接口
fileApiUrl false string null 默認(rèn)的文件上傳接口
image false string "/uploadImage" 默認(rèn)的上傳圖片接口
imageSizeLimit false number 1500 默認(rèn)的圖片大小限制, 單位KB
file false string "/uploadFile" 默認(rèn)的上傳文件接口
fileSizeLimit false number 10240 默認(rèn)的文件大小限制, 單位KB

pagination

參數(shù) 必填 類(lèi)型 默認(rèn)值 說(shuō)明
pageSize false number 10 每頁(yè)顯示數(shù)量
showSizeChanger false boolean false 是否可以改變pageSize
pageSizeOptions false array ["10", "20", "50", "100"] 指定每頁(yè)可以顯示多少條
showQuickJumper false boolean false 是否可以快速跳轉(zhuǎn)至某頁(yè)
showTotal false boolean true 是否顯示總數(shù)

dictionary

參數(shù) 必填 類(lèi)型 默認(rèn)值 說(shuō)明
key true string null 變量標(biāo)識(shí)
url true string null 請(qǐng)求數(shù)據(jù)地址

dataSchema.json

配置列表

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

actions

參數(shù) 必填 類(lèi)型 默認(rèn)值 說(shuō)明
keys false array null 允許更新哪些字段, 如果不設(shè)置keys, 就允許更所有字段
name true string null 展示標(biāo)題
type false string null update/delete/newLine/component

querySchema.json

配置列表

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

參考

react-antd-admin

AST語(yǔ)法轉(zhuǎn)換器

babel-types-api

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/6655.html

相關(guān)文章

  • babel提升前端效率實(shí)踐

    摘要:配置涵蓋了目前的業(yè)務(wù)場(chǎng)景的基本需求,但是可擴(kuò)展性很低。最終決定采用的生態(tài)鏈來(lái)解決上述遇到的問(wèn)題。在指定的路徑下寫(xiě)入對(duì)應(yīng)的文件。 大綱 遇到的問(wèn)題場(chǎng)景及解決方案對(duì)比 什么是babel? 解決過(guò)程 目前遺留的問(wèn)題 目前實(shí)現(xiàn)功能API 參考 遇到的問(wèn)題場(chǎng)景及解決方案對(duì)比 我們目前采用的是antd + react(umi)的框架做業(yè)務(wù)開(kāi)發(fā)。在業(yè)務(wù)開(kāi)發(fā)過(guò)程中會(huì)有較多頻繁出現(xiàn)并且相似度很高的場(chǎng)...

    huayeluoliuhen 評(píng)論0 收藏0
  • Taro 簡(jiǎn)介

    摘要:讓人又愛(ài)又恨的微信小程序自微信小程序以下簡(jiǎn)稱(chēng)小程序誕生以來(lái),就伴隨著贊譽(yù)與爭(zhēng)議不斷。同時(shí)于開(kāi)發(fā)者來(lái)說(shuō),小程序的生態(tài)不斷在完善,許多的坑已被踩平,雖然還是存在一些令人詬病的問(wèn)題,但已經(jīng)足見(jiàn)微信的誠(chéng)意了。 Taro 介紹 在互聯(lián)網(wǎng)不斷發(fā)展的今天,前端程序員們也不斷面臨著新的挑戰(zhàn),在這個(gè)變化多端、不斷革新自己的領(lǐng)域,每一年都有新的美好事物在發(fā)生。從去年微信小程序的誕生,到今年的逐漸火熱,以及...

    sixgo 評(píng)論0 收藏0
  • 《從零構(gòu)建前后分離web項(xiàng)目》:前端了解過(guò)關(guān)了嗎?

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

    lbool 評(píng)論0 收藏0
  • 《從零構(gòu)建前后分離web項(xiàng)目》:前端了解過(guò)關(guān)了嗎?

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

    cgspine 評(píng)論0 收藏0
  • 《從零構(gòu)建前后分離web項(xiàng)目》:前端了解過(guò)關(guān)了嗎?前端基礎(chǔ)架構(gòu)和硬核介紹

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

    SwordFly 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<