<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                &emsp;&emsp;我們組維護的管理后臺會接到很多開發需求,每次新開頁面,就會到處復制黏貼相關代碼。 &emsp;&emsp;并且還會經常性的翻閱文檔,先在書簽或地址欄輸入WIKI地址,然后找到那一份說明文檔,再定位到要看的組件位置。 &emsp;&emsp;雖然單人損耗的時間并不是非常多,但還是會打斷思路,影響開發的流暢性,當把所有人的時間累加起來,那損耗的時間也很可觀。 &emsp;&emsp;為了能提升團隊成員的開發效率,就開始構思一套可視化搭建系統。理想狀態下,拖動組件,配置交互和樣式,頁面生成,直接可用。 &emsp;&emsp;但是要完成這套功能,開發成本比較大,現在我想先解決當前的痛點,減少代碼復制的頻率和快速讀取組件文檔。 &emsp;&emsp;為此,在構思了好多天后,打算搞一個半吊子的可視化搭建系統。 &emsp;&emsp;所謂半吊子是指搭建完后,點擊生成,會在后臺創建視圖和數據兩個腳本文件、自動添加權限、新增菜單欄,不過后續我們還得繼續做開發,完善頁面功能。 ## 一、界面 &emsp;&emsp;界面分成左右兩部分,左邊是配置區域,右邊空白處是組件的預覽區域。 :-: ![](https://img.kancloud.cn/79/77/7977f086bf2c797d2530e8ec402c0315_2681x2089.png =800x) **1)組件區域** &emsp;&emsp;組件區域的第一個下拉框可以選擇Ant Design和部分模板組件,選中后,會替換組件地址的鏈接,點擊就能跳轉到組件的說明文檔。 &emsp;&emsp;第二個下拉框能選擇頁面中需要的組件,例如圖中的提示組件,點擊添加后會在右邊顯示,并且還會提供一個刪除圖標,目前暫不支持拖動效果。 :-: ![](https://img.kancloud.cn/c7/76/c776d69e94a58daee6c3c9e16c9db8c0_2544x808.png =800x) **2)配置區域** &emsp;&emsp;在配置區域中,可以輸入菜單名稱、路由、文件目錄和權限等信息。 &emsp;&emsp;原先的話,還得手動的在路由和權限兩個文件中新增配置項,現在都能自動化了。 &emsp;&emsp;原理就是先用Node分別讀取這兩份文件,得到一個數組,然后將配置內容塞到此數組中,再將數組序列化寫入文件內。 &emsp;&emsp;注意,需求在引入模塊(調用require()函數)前刪除模塊緩存,否則讀到的將是之前的文件內容。 ~~~ //權限文件的絕對路徑 const absAuthorityPath = pathObj.resolve(__dirname, 'src/utils/authority.ts'); delete require.cache[absAuthorityPath]; //刪除模塊緩存 const authorities = require(absAuthorityPath); const obj = { id: authority, pid: parent, name: menu, desc: '', routers: currentPath, }; authorities.push(obj); //添加權限 //寫入文件 fs.writeFileSync(absAuthorityPath, `module.exports = ${JSON.stringify(authorities, null, 2)}`); ~~~ &emsp;&emsp;fs.writeFileSync()用于同步寫入文件。module.exports是Node的模塊語法,而export default是ES6語法,Node原生并不支持,好在webpack對于這些模塊化語法都支持。 &emsp;&emsp;一旦點擊生成文件按鈕,在項目重新構建后,左邊菜單列表就能出現剛剛配置的菜單名稱(例如名稱叫菜單測試),并且能夠跳轉,權限也加好了。 :-: ![](https://img.kancloud.cn/32/13/32136be051cf2db2c869783f3b62a32c_484x476.png =300x) &emsp;&emsp;視圖和數據文件也是用Node創建的,在Node項目中寫好一份模板字符串(下面是生成視圖模板的函數),將可變部分作為參數傳入。 ~~~typescript export function setPageTemplate({name, antd, namespace, code='', props, component}) { return `import { connect, Dispatch, ${namespace}ModelState } from "umi"; import { setColumn } from '@/utils/tools'; import { TEMPLATE_MODEL } from '@/utils/constants'; ${antd} // 頁面參數類型 interface ${name}Props { dispatch: Dispatch; state: ${namespace}ModelState; } // 全局聲明 ${code} const ${name} = ({ dispatch, state }: ${name}Props) => { // dispatch({ type: "xx/xx", payload: {} }); // 狀態 // const { } = state; // 通用組件配置 ${props} return <> ${component} </>; }; export default connect((data: {${namespace}: ${namespace}ModelState}) => ({ state: data.${namespace} }))(${name});`; } ~~~ ## 二、配置 &emsp;&emsp;配置是本系統的核心,構思了很久,原先考慮了系統的靈活性,就想直接提供腳本編輯框,自定義邏輯。 &emsp;&emsp;不過出現個問題,那就是我這邊目前是用TypeScript語言開發的,那么我在自定義腳本邏輯時,也需要使用TypeScript語法。 &emsp;&emsp;瀏覽器提供的[eval()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval)函數并不支持TypeScript語法,需要先做轉譯,網上搜索后,得到了解決方案,下載了TypeScript庫后。 &emsp;&emsp;但是卻一直報錯,在網上也查到了些解決方案([方案一](https://github.com/microsoft/TypeScript/issues/39436),[方案二](https://stackoverflow.com/questions/45153848/evaluate-typescript-from-string)),不過并不適用于我目前的項目環境。 ~~~ ./node_modules/typescript/lib/typescript.js Critical dependency: the request of a dependency is an expression ./node_modules/typescript/lib/typescript.js Critical dependency: the request of a dependency is an expression ./node_modules/typescript/lib/typescript.js Module not found: Can't resolve 'perf_hooks' in 'C:\Users\User\node_modules\typescript\lib' ~~~ &emsp;&emsp;最終決定暫時放棄自定義腳本邏輯,先解決當前痛點,盡快將系統上線。 &emsp;&emsp;期間還遇到個比較隱蔽的bug,如下所示,數組會先調用 toString() 轉換成字符串,最終變為 eval("(1, 2)"),所以得到的值是 2。 ~~~ eval(`(${[1,2]})`); //2 ~~~ &emsp;&emsp;還遇到個問題,那就是在用?[JSON.stringify()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)?序列化對象時,若參數是函數,那么就會被過濾掉。 ~~~ JSON.stringify({func:() => {}}); //"{}" ~~~ **1)物料庫** &emsp;&emsp;物料庫中的組件分為兩種,一種是自定義的[后臺模板組件](https://github.com/pwstrick/shin-admin/blob/main/docs/template.md),另一種是第三方的[Ant Design 3.X](https://3x.ant.design/docs/react/introduce-cn)組件。 &emsp;&emsp;為了快速搭建頁面,選擇的組件是前者。這次順便用TypeScript,再次完善了組件代碼的類型聲明。 :-: ![](https://img.kancloud.cn/ea/9d/ea9dfe53bfdc66e558a1c2cfa0bcfc57_964x454.png =400x) &emsp;&emsp;后者只是用來文檔查詢和在模板字符串中拼接引入語句,如下所示。 ~~~typescript `import { ${antds.join(',')} } from 'antd';` ~~~ **2)自定義組件** &emsp;&emsp;自定義組件的聲明采用JSON格式,TypeScript聲明的類型如下所示。 ~~~typescript interface OptionsType { value: string; label: string; children: Array<{ value: string; label: string; link: string; //鏈接地址 readonlyProps?: ObjectType; //會影響組件的呈現,并且不能配置的屬性 readonlyStrProps?: string; //待拼接的字符串屬性 handleProps?: (values:ObjectType) => ObjectType; //在格式化表單數據后,再處理特定的組件屬性 handleStrProps?: (values:ObjectType) => string; //拼接無法轉換成字符串的屬性 props: Array<{ label: string; name: string; params?: ObjectType; control: JSX.Element | ((index: number) => JSX.Element); type?: string; initControl?: (props:any) => JSX.Element; }> }>; } ~~~ &emsp;&emsp;鏈接地址就是說明文檔的地址,在組件的屬性中,有一部分是回調函數,而目前已經舍棄了自定義的回調邏輯。 &emsp;&emsp;所以這部分屬性要特殊處理(聲明在?readonlyProps),不能在界面中輸入。 ~~~ readonlyProps: { initPanes: (record: ObjectType): TabPaneType[] => [ { name: "示例", key: "demo", controls: [ { label: '測試組件', control: <>內容</> } ] }, ], }, ~~~ &emsp;&emsp;readonlyStrProps 就是?readonlyProps 對應的字符串格式,該屬性還會增加一些其它屬性,配上注釋,也相當于是份組件文檔了。 ~~~typescript readonlyStrProps: `, // 標簽欄內容回調函數,參數為 record,當標簽欄只有一項時,將不顯示菜單 "initPanes": (record: ObjectType): TabPaneType[] => [ { name: "示例", key: "demo", controls: [ { label: '測試組件', control: <>內容</> } ] }, ], // useEffect鉤子中的回調函數,參數是 record "effectCallback": (record: ObjectType) => {}`, ~~~ &emsp;&emsp;handleProps() 是一個回調函數,在表單接收到數據后,有些組件需要再做一次特殊的處理。 &emsp;&emsp;例如加些特定屬性、數組元素合并成字符串等,從而才能順利的在預覽界面呈現。 ~~~ handleProps: (values:ObjectType) => { //對表單中的值做處理 // 對接口數組做特殊處理,從['api', 'get']轉換成api.get values.url && (values.url = values.url.join('.'));// 初始化表單需要的組件 if(values.controls.length === 0) { values.controls = [ { label: "示例", name: "demo", control: <>測試組件</> }, ]; }else { values.originControls = values.controls; //備份組件名稱數組 values.controls = values.controls.map((item:string) => getControls(item)); } delete values.controlskeys; //刪除冗余屬性 return values; }, ~~~ &emsp;&emsp;handleStrProps() 是在輸出模板時使用,將那些特殊屬性寫成字符串形式。 ~~~ handleStrProps: (values:ObjectType):string => { if(values.controls.length === 0) { delete values.originControls; //刪除備份數組 delete values.controls; //刪除原始屬性 return `,"controls": [ { label: "示例", name: "demo", control: <>測試組件</> }, ]`; } // 組件名稱數組處理 const newControls = values.originControls.map((item:string) => getStrControls(item)); delete values.originControls; delete values.controls; return `,"controls": [${newControls.join(',')}]`; }, ~~~ &emsp;&emsp;在經過一系列的處理后,將一些字符串代碼傳遞給接口,接口最后拼接成兩個文件,輸出到指定目錄中。 &emsp;&emsp;不過生成的代碼,排版有點混亂,每次都還需要手動格式化一下。 ***** > 原文出處: [博客園-Node.js躬行記](https://www.cnblogs.com/strick/category/1688575.html) [知乎專欄-Node.js躬行記](https://zhuanlan.zhihu.com/pwnode) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看