主頁 > 企業開發 > 前端工程化實戰-開發企業級CLI

前端工程化實戰-開發企業級CLI

2023-07-04 09:54:11 企業開發

1. 前言

腳手架大家一定都不陌生,比如我們經常使用的 vue-cli、create-react-app,它可以幫助我們快速的初始化一個專案,無需從零配置,極大的方便我們的開發,到這里你可能會疑惑,既然市面上有成熟的腳手架,為什么需要寫一個屬于自己的腳手架呢,因為公共腳手架雖然強大,但并不能滿足我們的實際開發需求,

例如專案中已有的沉淀,專案架構、介面請求的統一處理、換膚、業務組件、eslint配置等,這些想要用到新專案中,只能通過復制粘貼,會存在以下弊端:

  • 重復性勞動,繁瑣且浪費時間
  • 已有專案沉淀分散在各處,很容易有所遺漏
  • 專案間的配置差異很可能會被忽略
  • 人工操作永遠都有可能犯錯,建新專案時,總要花時間去排錯

如果我們自己開發一套腳手架,定制自己的模板,復制粘貼的人工流程就會轉換為 cli 的自動化流程, 還可以通過維護不同的模板以適應不同業務需求,既然要開發一套腳手架,站在巨人肩膀上顯然省事多了,我們先來看看業界知名腳手架Vue CLI是如何實作的,

 

 2.Vue CLI 原理分析 

Vue CLI 是一個基于 Vue.js 進行快速開發的完整系統,提供:

  • 通過 @vue/cli 實作的互動式的專案腳手架,
  • 通過 @vue/cli + @vue/cli-service-global 實作的零配置原型開發,
  • 一個運行時依賴 (@vue/cli-service),該依賴:
    • 可升級;
    • 基于 webpack 構建,并帶有合理的默認配置;
    • 可以通過專案內的組態檔進行配置;
    • 可以通過插件進行擴展,
  • 一個豐富的官方插件集合,集成了前端生態中最好的工具,

  • 一套完全圖形化的創建和管理 Vue.js 專案的用戶界面,

     

2.1

全域 vue 執行命令存放在哪里

以mac為例,使用命令 where vue,就可以查到 vue 命令所在位置,找到所在位置后,查看目錄即可分析原始碼,

 

  2.2

vue命令是從哪里注冊的

找到原始碼目錄中的package.json,我們會看到如下代碼:

圖片

可以看到bin欄位指定了可執行檔案的命令名以及可執行檔案的路徑,npm安裝一個依賴時,如果該依賴的package.json中指定了bin的資訊,那么同時會創建一個全域的軟連接指向該命令所對應的可執行檔案,詳細可查看npm的官方檔案:package.json中bin的使用說明,

  2.3

依賴包分析

包名 用途
commander 完整的 node.js 命令列解決方案, Commander 負責將引數決議為選項和命令引數
shelljs 用來執行shell命令
inquirer 通用互動式命令列用戶界面的集合
semver 語意化版本控制
chalk 設定終端字串樣式

  2.4

腳手架都做了哪些事情

2.4.1 HTML 和靜態資源

html檔案是一個會被 html-webpack-plugin 處理的模板,在構建程序中,資源鏈接會被自動注入,另外,Vue CLI 也會自動注入 resource hint (preload/prefetch、manifest 和圖示鏈接 (當用到 PWA 插件時) 以及構建程序中處理的 JavaScript 和 CSS 檔案的資源鏈接,

2.4.2  CSS 相關

Vue CLI生成專案支持 PostCSS、CSS Modules 和包含 Sass、Less、Stylus 在內的前處理器,你可以在創建專案的時候選擇前處理器,

2.4.3  webpack 相關

Vue CLI基于 webpack 構建,并帶有合理的默認配置,可以通過專案內的組態檔進行配置,還可以通過插件進行擴展,

2.4.4  模式與環境變數

模式是 Vue CLI 專案中一個重要的概念,默認情況下,一個 Vue CLI 專案有三個模式:

development 模式用于 vue-cli-service servetest 模式用于 vue-cli-service test:unitproduction 模式用于 vue-cli-service build 和 vue-cli-service test:e2e你可以通過傳遞 --mode 選項引數為命令列覆寫默認的模式,

 2.4.5  構建目標

當你運行 vue-cli-service build 時,你可以通過 --target 選項指定不同的構建目標,它允許你將相同的源代碼根據不同的用例生成不同的構建,

通過以上對Vue CLI 的分析,我們就對腳手架工具提供的構建集成能力有了一個大概的了解,這有助于我們在使用具體工具時快速定位問題的邊界,當我們自己設計腳手架的時候,我們也可以參照和借鑒,可以適用于我們業務的有:

  • 通過命令列與用戶互動
  • 根據用戶的選擇生成對應的檔案,實作的零配置原型開發
需要做出修改的部分有:
  • 基于 vite 構建,并帶有合理的默認配置;
  • 預定義業務模板,根據用戶選擇生成
  • 業務模板基礎支持:
    • HTML 和靜態資源處理
    • 內置css前處理器
    • 內置vite配置,可以直接修改vite組態檔
    • 內置test、pre、pro三種模式,并生成對應的組態檔

按照上述總結,讓我們一步一步撰寫自己的腳手架吧,首先是通過命令列與用戶互動,那么我們需要有一個可執行命令的名字,也是腳手架的名字,這里我們就叫做dt-fe-cli

 3.腳手架實作 

  3.1

命令列工具撰寫

  3.1.1  初始化專案

我們的腳手架叫做dt-fe-cli,創建dt-fe-cli檔案夾,執行npm init -y初始化倉庫,生成package.json檔案,

在dt-fe-cli檔案夾下創建bin檔案夾,并在里面創建cli.mjs檔案,此檔案作為我們腳手架的入口,需要將其配置到package.json的bin欄位,

{
    "name": "@auto/dt-fe-cli",
    "version": "0.0.1",
    "bin": {
        "dt-fe-cli": "bin/cli.mjs"
    }
}

這樣我們腳手架的入口就有了,繼續撰寫腳手架的功能吧

  3.1.2  指令

dt-fe-cli 作為全域命令,同時提供了很多指令,

  • dt-fe-cli --version可以查看 dt-fe-cli 版本
  • dt-fe-cli --help可以查看幫助檔案
  • dt-fe-cli create xxx可以創建一個專案 ...

圖片

  3.1.3  create命令

create接受一個專案名作為引數,這里還提供了額外選項-f, --force,此選項代表如果本地已經存在同名檔案夾,是否覆寫,命令列解決方案需要依賴第三方庫commander

import create from '../lib/create.mjs'

program
  .command('create <app-name>')
  .description('create a new project powered by dt-fe-cli')
  .option("-f, --force", "overwrite target directory if it exists")
  .action((projectName, options) => {
    create(projectName, options)
  })

  3.1.4  create方法設計與實作

執行create命令后,如何創建專案呢,我們公司的專案都是托管在內部gitlab上面的,所以直接使用git clone去拉取模板專案,這里需要依賴第三方庫shelljs,那么這里就需要首先判斷git是否存在,不存在提示并退出,之前我們還寫了一個額外選項,用來表示如果本地已經存在同名檔案夾,是否覆寫,若沒有此選項,還需要互動式的詢問,這里需要依賴第三方庫inquirer,

create.mjs:

import chalk from 'chalk'
import fse from 'fs-extra'
import shelljs from 'shelljs'
import path from 'path'
import inquirer from 'inquirer'

async function create(projectName, options) {
  const targetDirectory = path.join(process.cwd(), projectName)
  try {
    // 判斷是否存在git,不存在則提示并退出
    if (!shelljs.which('git')) {
      console(chalk.red('Sorry, dt-fe-cli requires git'));
      return
    }
    const isExist = await fse.pathExists(targetDirectory)
    // 判斷目錄下是否存在同名檔案夾
    if (isExist) {
      if (options.force) {
        await fse.remove(targetDirectory);
      } else {
        const { isOverwrite } = await new inquirer.prompt([
          {
            name: "isOverwrite", // 與回傳值對應
            type: "list",
            message: "Target directory already exists. Pick an action:",
            choices: [
              { name: "Overwrite", value: true },
              { name: "Cancel", value: false },
            ],
          },
        ]);
        // 移除同名檔案夾
        if (isOverwrite) {
          console.log('remove existing directory...')
          await fse.remove(targetDirectory);
        } else {
          return;
        }
      }
    }
    // 專案型別
    const { projectType } = await new inquirer.prompt([
      {
        name: "projectType", // 與回傳值對應
        type: "list",
        message: "Please select project type:",
        choices: [
          { name: "pc", value: 'pc' },
          { name: "h5", value: 'h5' },
        ],
      },
    ]);
    const PROJECT_MAP = {
      pc: 'pc.git',
      h5: 'h5.git'
    }
    // 安裝依賴專案
    shelljs.exec(`git clone ${PROJECT_MAP[projectType]} ${projectName}`, async (code, stdout, stderr) => {
      if (code === 0) {
        progress.start()
        try {
          // 洗掉原有.git
          await fse.remove(path.join(process.cwd(), projectName, '.git'))
        } catch (error) {
          console.log(error)
        }
        progress.succeed()
        console.log(`\r\nSuccessfully created project ${chalk.cyan(projectName)}`);
        console.log(`\r\n  cd ${chalk.cyan(projectName)}`);
        console.log("  git init");
        console.log("  pnpm install");
        console.log("  pnpm dev");
      }
    })
  } catch (error) {
    console.log(error);
  }
}

  3.1.5  node版本檢查

執行 create 命令后,創建專案會去 gitlab 拉取代碼下載我們自定義的模版,目前我使用的模版均由 Vite3 創建,Vite3 需要 Node.js 版本 14.18+,16+,所以在使用腳手架時,可以先檢查一下當前 Node.js 版本是否符合,不符合則拋出例外,當前依賴的 Node.js 版本需要將其配置到package.json的engines欄位,判斷當前 Node.js 版本是否符合需要依賴第三方庫semver

package.json:

{
    "engines": {
        "node": ">= 14.18.0"
    },
}

cli.mjs:

import { readFile } from 'fs/promises'
import semverSatisfies from 'semver/functions/satisfies.js'

const { engines: { node: requiredVersion }, version } = JSON.parse(
  await readFile(
    new URL('../package.json', import.meta.url)
  )
)

function checkNodeVersion (wanted, id) {
  if (!semverSatisfies(process.version, wanted, { includePrerelease: true })) {
    console.log(chalk.red(
      'You are using Node ' + process.version + ', but this version of ' + id +
      ' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
    ))
    process.exit(1)
  }
}

checkNodeVersion(requiredVersion, 'dt-fe-cli')

到這里,腳手架的基本功能就已經開發完畢了,剩下的就是我們的專案模板了

  3.2

模版設計支持功能

圖片

3.2.1  TypeScript

使用 Vite3 構建,Vite3 天然支持引入 .ts 檔案

  3.2.2  打包自動上傳CDN

const { execSync } = require('child_process');
const { loadEnv } = require('vite')

const env = process.argv[2]
const { VITE_BASE_URL } = loadEnv(env, process.cwd(), '')
const prefix = `${env}${VITE_BASE_URL}`

execSync(`vite build --mode ${env} --base=https://cdn.com/${prefix}`);
uploadCDN({
  Dir: `dist/assets`,
  Prefix: prefix
})

  3.2.3  commit 校驗

npm install husky --save-dev
npm pkg set scripts.prepare="husky install"
npm run prepare
npx husky add .husky/pre-commit "npm run lint"
git add .husky/pre-commit

  3.2.4  eslint校驗

ESLint通用配置的部分這里就不再贅述了,這里介紹一下我們業務里面自定義的ESLint插件,eslint校驗大家都很熟悉,市面上也有很多eslint插件,但隨著專案不斷迭代發展,我們團隊的編碼規范使用現有的eslint插件已經無法滿足了,需要自己創建插件,并融入到cli的模板當中,

 ? 創建插件

開始創建插件的最簡單方法是使用 Yeoman 生成器,生成器將指導您設定插件的骨架

npm i -g yo generator-eslint
yo eslint:plugin

以上命令會生成如下目錄

.
├── README.md
├── lib
│   ├── index.js
│   └── rules
├── package.json
└── tests
    └── lib
        └── rules

插件可以在 ESLint 中使用的額外規則,為此,插件必須匯出一個包含規則 ID 到規則的鍵值映射的規則物件,舉個簡單的例子,我們想創建一條不允許使用console.log的規則

  ?  創建規則
yo eslint:rule

此命令會在lib/rules檔案夾下創建一個新的js檔案,一個規則對應一個可匯出的 node 模塊

"use strict";

//-------------------------------------------------------
// Rule Definition
//-------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
  meta: {
    type: "suggestion",
    docs: {
      description: "disallow unnecessary semicolons",
      recommended: true,
      url: "https://eslint.org/docs/rules/no-extra-semi"
    },
    fixable: "code",
    schema: [] // no options
  },
  create(context) {
    return {
      // callback functions
    };
  }
};

上面這段代碼是一個規則的原始碼檔案的基本格式,一個規則的源檔案輸出一個物件,它由 meta 和 create 兩部分組成,

?meta(物件)包含規則的元資料,如規則型別、檔案、可接受引數的schema等等

?create (function) 回傳一個物件,其中包含了 ESLint 在遍歷 JavaScript 代碼的抽象語法樹 AST (ESTree 定義的 AST) 時,用來訪問節點的方法,

核心其實在于create方法,我們若想知道如何撰寫create方法,首先要明白其原理,那就是 ESLint 是如何分析我們所撰寫的代碼呢?相信大家對此也都有所了解,沒錯,就是AST (Abstract Syntax Tree(抽象語法樹))

  ?  插件原理

圖片

ESLint 決議器將代碼轉換為 ESLint 可以評估的抽象語法樹,默認情況下,ESLint 使用內置的 Espree 決議器,它與標準的 JavaScript 運行時和版本兼容,然后去攔截檢測是否符合我們規定的書寫方式,最后讓其展示報錯、警告或正常通過,ESLint 的核心就是規則(rules),而定義規則的核心就是利用 AST 來做校驗,那就讓我們看一下代碼 AST 中會表現為什么樣子,

圖片

上圖可以看出,console.log對應 AST 中type為ExpressionStatement(運算式陳述句),運算式型別為CallExpression(呼叫運算式),被呼叫者型別為MemberExpression(成員運算式),被呼叫物件名為console,屬性名為log,根據上述資訊,我們就可以來完善create方法了
  ?  撰寫規則
"use strict";

//-------------------------------------------------------
// Rule Definition
//-------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
  meta: {
    type: "suggestion",
    fixable: "code",
    schema: [], // no options
  },
  create(context) {
    return {
      //  key 是 selector
      'CallExpression MemberExpression': (node) => {
        const { property, object } = node;
        // 如果在 AST 中匹配到了console.log,就用 context.report() 來發布警告或錯誤
        if (object.name === 'console' && property.name === 'log') {
          context.report({
            node,
            message: 'console.log is forbidden.'
          });
        }
      }
    };
  }
};

至此,包含一條規則(禁止使用console.log)的 ESLint 插件就撰寫完成了,接下來將此專案發布到npm平臺就可以在專案模板中下載使用了

 最后 

 

本文介紹了如何從零撰寫一個我們自己的腳手架,并且可以根據不同業務場景區分模版,把業務已有的積累沉淀進去,以上便是本次分享的全部內容,希望對你有所幫助 ^_^

 

作者| 馬春鍵 

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/Frontend-Engineering-Practice---Developing-Enterprise-Level-CLI.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556587.html

標籤:JavaScript

上一篇:前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下滾動跑馬燈 上下滾動廣播

下一篇:返回列表

標籤雲
其他(162061) Python(38266) JavaScript(25521) Java(18289) C(15238) 區塊鏈(8275) C#(7972) AI(7469) 爪哇(7425) MySQL(7285) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4610) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) HtmlCss(1987) .NET技术(1985) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1882) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 前端工程化實戰-開發企業級CLI

    腳手架大家一定都不陌生,比如我們經常使用的 vue-cli、create-react-app,它可以幫助我們快速的初始化一個專案,無需從零配置,極大的方便我們的開發。到這里你可能會疑惑,既然市面上有成熟的腳手架,為什么需要寫一個屬于自己的腳手架呢。因為公共腳手架雖然強大,但并不能滿足我們的實際開發需... ......

    uj5u.com 2023-07-04 09:54:11 more
  • 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下

    #### 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下滾動跑馬燈 上下滾動廣播,下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13318 #### 效果圖如下: ![](https://p3-juejin.b ......

    uj5u.com 2023-07-04 09:53:45 more
  • 記錄--多行標簽超出展開折疊功能

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 記錄分享每一個日常開發專案中的實用小知識,不整那些虛頭巴腦的框架理論與原理,之前分享過抽獎功能、簽字功能等,有興趣的可以看看本人以前的分享。 今天要分享的實用小知識是最近專案中遇到的標簽相關的功能,我不知道叫啥,姑且稱之為【多行標簽 ......

    uj5u.com 2023-07-04 08:33:59 more
  • 聊聊Excel決議:如何處理百萬行EXCEL檔案

    如何恰當地處理資料量龐大的Excel檔案,避免記憶體溢位問題?本文將對比分析業界主流的Excel決議技術,并給出解決方案。 ......

    uj5u.com 2023-07-04 08:33:51 more
  • 前端Vue自定義可自由滾動精美tabs選項卡標簽欄標題欄 可設定背景

    #### 前端Vue自定義可自由滾動精美tabs選項卡標簽欄標題欄 可設定背景顏色, 下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13313 #### 效果圖如下: #### ![](https://p3-juejin.byt ......

    uj5u.com 2023-07-04 08:33:48 more
  • 前端Vue騰訊地圖SDK Api經緯度決議為地址資訊Geocoding 可用于定

    #### 前端Vue騰訊地圖SDK Api經緯度決議為地址資訊Geocoding 可用于定位經緯度資訊決議為地址, 下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13311 #### 效果圖如下: ![](https://p3- ......

    uj5u.com 2023-07-04 08:33:44 more
  • 記錄--多行標簽超出展開折疊功能

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 記錄分享每一個日常開發專案中的實用小知識,不整那些虛頭巴腦的框架理論與原理,之前分享過抽獎功能、簽字功能等,有興趣的可以看看本人以前的分享。 今天要分享的實用小知識是最近專案中遇到的標簽相關的功能,我不知道叫啥,姑且稱之為【多行標簽 ......

    uj5u.com 2023-07-04 08:33:09 more
  • 聊聊Excel決議:如何處理百萬行EXCEL檔案

    如何恰當地處理資料量龐大的Excel檔案,避免記憶體溢位問題?本文將對比分析業界主流的Excel決議技術,并給出解決方案。 ......

    uj5u.com 2023-07-04 08:33:01 more
  • 前端Vue自定義可自由滾動精美tabs選項卡標簽欄標題欄 可設定背景

    #### 前端Vue自定義可自由滾動精美tabs選項卡標簽欄標題欄 可設定背景顏色, 下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13313 #### 效果圖如下: #### ![](https://p3-juejin.byt ......

    uj5u.com 2023-07-04 08:32:58 more
  • 1.5 撰寫自定位ShellCode彈窗

    在筆者上一篇文章中簡單的介紹了如何運用匯編語言撰寫一段彈窗代碼,雖然簡易`ShellCode`可以被正常執行,但卻存在很多問題,由于采用了硬編址的方式來呼叫相應API函式的,那么就會存在一個很大的缺陷,如果作業系統的版本不統或系統重啟過,那么基址將會發生變化,此時如果再次呼叫基址引數則會呼叫失敗,本... ......

    uj5u.com 2023-07-04 08:32:06 more