最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue?+?Node.js自動(dòng)發(fā)布服務(wù)腳本的完整流程

 更新時(shí)間:2026年03月20日 10:58:48   作者:赤兔之神  
在當(dāng)今快節(jié)奏的軟件開發(fā)環(huán)境中,前端項(xiàng)目的快速迭代與高效部署成為了提升競(jìng)爭(zhēng)力的關(guān)鍵,這篇文章主要介紹了基于Vue+Node.js自動(dòng)發(fā)布服務(wù)腳本的完整流程,需要的朋友可以參考下

前言

基于 Vue 和 Node.js 的自動(dòng)化發(fā)布服務(wù)腳本實(shí)現(xiàn)方案,該方案主要依賴 node-ssh(用于服務(wù)器 SSH 連接)和 archiver(用于文件壓縮打包)兩大核心模塊。通過與 package.json 中配置的多環(huán)境部署腳本協(xié)同工作,在 deploy 目錄下構(gòu)建完整的發(fā)布流程。以下將詳細(xì)介紹腳本開發(fā)、環(huán)境配置及使用說(shuō)明,確保完全符合您的項(xiàng)目需求。

一、環(huán)境準(zhǔn)備:依賴安裝

請(qǐng)?jiān)?Vue 項(xiàng)目根目錄執(zhí)行以下命令安裝必要依賴(包括 rimraf 清理工具,該依賴已在您的 package.json 中配置,建議一并確認(rèn)安裝狀態(tài)):

# 核心依賴:ssh連接、壓縮打包
npm i node-ssh archiver -D
# 清理依賴(若未安裝)
npm i rimraf -D
# ssh
npm i node-ssh -D 

二、項(xiàng)目目錄結(jié)構(gòu)

在 Vue 項(xiàng)目根目錄新建 deploy 文件夾,最終目錄結(jié)構(gòu)如下(新增文件已標(biāo)注):

三、編寫 deploy 文件夾下的核心文件

deploy/index.js :部署入口文件 核心邏輯:解析命令行的環(huán)境參數(shù) → 執(zhí)行 Vue 打包 → 壓縮 dist 目錄為 zip 包 → SSH 連接服務(wù)器 → 上傳壓縮包并解壓 → 清理臨時(shí)文件 → 完成部署,全程自動(dòng)化,無(wú)需手動(dòng)操作:

 * 自動(dòng)化部署腳本
 * @description 實(shí)現(xiàn)項(xiàng)目打包、壓縮、上傳、備份、解壓等自動(dòng)化部署功能
 */
const { NodeSSH } = require("node-ssh");
const archiver = require("archiver");
const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");
const util = require("util");
const execPromise = util.promisify(exec);

/**
 * 獲取環(huán)境配置
 * @returns {Object} 配置對(duì)象
 */
function getConfig() {
  // 從命令行參數(shù)獲取環(huán)境,例如: node deploy/index.js --env=test
  const args = process.argv.slice(2);
  let env = "prod"; // 默認(rèn)生產(chǎn)環(huán)境

  // 解析命令行參數(shù)
  for (const arg of args) {
    if (arg.startsWith("--env=")) {
      env = arg.split("=")[1];
    }
  }

  // 如果有環(huán)境變量 DEPLOY_ENV,優(yōu)先使用
  if (process.env.DEPLOY_ENV) {
    env = process.env.DEPLOY_ENV;
  }

  // 處理 production 別名
  if (env === "production") {
    env = "prod";
  }

  // 直接根據(jù)環(huán)境名稱構(gòu)建配置文件路徑
  const configFile = `./config.${env}.js`;
  const configPath = path.join(__dirname, configFile);

  // 檢查配置文件是否存在
  if (!fs.existsSync(configPath)) {
    throw new Error(
      `配置文件不存在: ${configFile}\n` +
        `請(qǐng)創(chuàng)建 deploy/config.${env}.js 文件,或使用已有的環(huán)境配置。\n` +
        `可用環(huán)境示例: test, prod, xj, mj`
    );
  }

  console.log(`\x1b[36m[INFO]\x1b[0m 使用配置環(huán)境: ${env}`);
  console.log(`\x1b[36m[INFO]\x1b[0m 配置文件: ${configFile}`);

  return require(configFile);
}

const config = getConfig();

const ssh = new NodeSSH();

/**
 * 輸出帶顏色的日志
 */
const log = {
  info: (msg) => console.log(`\x1b[36m[INFO]\x1b[0m ${msg}`),
  success: (msg) => console.log(`\x1b[32m[SUCCESS]\x1b[0m ${msg}`),
  error: (msg) => console.log(`\x1b[31m[ERROR]\x1b[0m ${msg}`),
  warning: (msg) => console.log(`\x1b[33m[WARNING]\x1b[0m ${msg}`),
};

/**
 * 步驟1: 執(zhí)行項(xiàng)目打包
 * @returns {Promise<void>}
 */
async function buildProject() {
  log.info("開始執(zhí)行項(xiàng)目打包...");
  try {
    const { stdout, stderr } = await execPromise(config.build.command);
    if (stderr && !stderr.includes("warning")) {
      log.warning(`構(gòu)建警告: ${stderr}`);
    }
    log.success("項(xiàng)目打包完成!");
    return true;
  } catch (error) {
    log.error(`項(xiàng)目打包失敗: ${error.message}`);
    throw error;
  }
}

/**
 * 步驟2: 壓縮dist文件夾為zip
 * @returns {Promise<string>} 返回zip文件路徑
 */
async function compressDistToZip() {
  log.info("開始?jí)嚎sdist文件夾...");

  const { localDistPath, localZipName } = config.deploy;
  const zipPath = path.join(process.cwd(), localZipName);

  // 如果已存在zip文件,先刪除
  if (fs.existsSync(zipPath)) {
    fs.unlinkSync(zipPath);
  }

  // 檢查 dist 目錄是否存在
  if (!fs.existsSync(localDistPath)) {
    throw new Error(`dist目錄不存在: ${localDistPath}`);
  }

  return new Promise((resolve, reject) => {
    const output = fs.createWriteStream(zipPath);
    const archive = archiver("zip", {
      zlib: { level: 9 }, // 壓縮級(jí)別
    });

    let fileCount = 0;

    output.on("close", () => {
      const size = (archive.pointer() / 1024 / 1024).toFixed(2);
      log.success(`壓縮完成! 文件大小: ${size} MB, 文件數(shù): ${fileCount}`);
      log.info(`壓縮包路徑: ${zipPath}`);
      resolve(zipPath);
    });

    archive.on("error", (err) => {
      log.error(`壓縮失敗: ${err.message}`);
      reject(err);
    });

    archive.on("warning", (err) => {
      if (err.code === "ENOENT") {
        log.warning(`壓縮警告: ${err.message}`);
      } else {
        reject(err);
      }
    });

    // 監(jiān)聽文件添加事件
    archive.on("entry", (entry) => {
      fileCount++;
    });

    archive.pipe(output);

    // 將dist文件夾內(nèi)容添加到壓縮包根目錄
    // false 參數(shù)表示不包含 dist 文件夾本身,直接將其內(nèi)容放在 zip 根目錄
    archive.directory(localDistPath, false);

    archive.finalize();
  });
}

/**
 * 步驟3: 連接SSH服務(wù)器
 * @returns {Promise<void>}
 */
async function connectSSH() {
  log.info("正在連接SSH服務(wù)器...");
  try {
    await ssh.connect({
      host: config.server.host,
      port: config.server.port,
      username: config.server.username,
      password: config.server.password,
    });
    log.success(`成功連接到服務(wù)器: ${config.server.host}`);
  } catch (error) {
    log.error(`SSH連接失敗: ${error.message}`);
    throw error;
  }
}

/**
 * 步驟4: 備份服務(wù)器上的dist目錄
 * @returns {Promise<void>}
 */
async function backupRemoteDist() {
  log.info("正在備份服務(wù)器上的dist目錄...");

  const { remoteDir, remoteDist, backupDir } = config.deploy;
  const remoteDistPath = `${remoteDir}/${remoteDist}`;

  // 生成時(shí)間戳:格式如 20260204_153045
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  const hours = String(now.getHours()).padStart(2, "0");
  const minutes = String(now.getMinutes()).padStart(2, "0");
  const seconds = String(now.getSeconds()).padStart(2, "0");
  const timestamp = `${year}${month}${day}_${hours}${minutes}${seconds}`;

  const backupPath = `${backupDir}/${remoteDist}_backup_${timestamp}`;
  log.info(`備份時(shí)間: ${year}-${month}-${day} ${hours}:${minutes}:${seconds}`);

  try {
    // 檢查dist目錄是否存在
    const checkCmd = `[ -d "${remoteDistPath}" ] && echo "exists" || echo "not_exists"`;
    const checkResult = await ssh.execCommand(checkCmd);

    if (checkResult.stdout.trim() === "exists") {
      // 創(chuàng)建備份目錄
      await ssh.execCommand(`mkdir -p ${backupDir}`);

      // 備份dist目錄
      const backupCmd = `cp -r ${remoteDistPath} ${backupPath}`;
      await ssh.execCommand(backupCmd);
      log.success(`備份完成: ${backupPath}`);
    } else {
      log.warning("服務(wù)器上不存在dist目錄,跳過備份");
    }
  } catch (error) {
    log.error(`備份失敗: ${error.message}`);
    throw error;
  }
}

/**
 * 步驟5: 上傳zip文件到服務(wù)器(已合并到步驟6)
 * @deprecated 此步驟已合并
 */

/**
 * 步驟6: 上傳zip文件到服務(wù)器
 * @param {string} zipPath 本地zip文件路徑
 * @returns {Promise<void>}
 */
async function uploadZipToServer(zipPath) {
  log.info("正在上傳dist.zip到服務(wù)器...");

  const { remoteDir, localZipName } = config.deploy;
  const remoteZipPath = `${remoteDir}/${localZipName}`;

  try {
    // 獲取文件大小
    const stats = fs.statSync(zipPath);
    const fileSize = stats.size;
    const fileSizeMB = (fileSize / 1024 / 1024).toFixed(2);
    log.info(`文件大小: ${fileSizeMB} MB`);

    // 上傳文件并顯示進(jìn)度(提高并發(fā)數(shù)加速上傳)
    await ssh.putFile(zipPath, remoteZipPath, null, {
      concurrency: 20, // 提高并發(fā)數(shù),加速上傳
      chunkSize: 32768, // 32KB 塊大小
      step: (transferred, chunk, total) => {
        const percent = ((transferred / total) * 100).toFixed(2);
        const transferredMB = (transferred / 1024 / 1024).toFixed(2);
        const totalMB = (total / 1024 / 1024).toFixed(2);
        const speed = (chunk / 1024 / 1024).toFixed(2);
        // 使用\r回到行首,實(shí)現(xiàn)進(jìn)度條效果
        process.stdout.write(
          `\r\x1b[36m[INFO]\x1b[0m 上傳進(jìn)度: ${percent}% (${transferredMB}MB / ${totalMB}MB) 速度: ${speed}MB/s`
        );
      },
    });

    // 上傳完成后換行
    console.log("");
    log.success(`上傳完成: ${remoteZipPath}`);
  } catch (error) {
    console.log(""); // 確保錯(cuò)誤信息另起一行
    log.error(`上傳失敗: ${error.message}`);
    throw error;
  }
}

/**
 * 步驟7: 在服務(wù)器上解壓zip文件并替換dist
 * @returns {Promise<void>}
 */
async function unzipAndReplaceDist() {
  log.info("正在解壓dist.zip并準(zhǔn)備替換...");

  const { remoteDir, localZipName, remoteDist } = config.deploy;
  const remoteZipPath = `${remoteDir}/${localZipName}`;
  const remoteDistPath = `${remoteDir}/${remoteDist}`;

  try {
    // 檢查zip文件是否存在
    const checkZipCmd = `[ -f "${remoteZipPath}" ] && echo "exists" || echo "not_exists"`;
    const checkZipResult = await ssh.execCommand(checkZipCmd);

    if (checkZipResult.stdout.trim() !== "exists") {
      throw new Error("服務(wù)器上的zip文件不存在");
    }

    log.info("正在檢查zip文件內(nèi)容...");
    const listZipCmd = `unzip -l ${remoteZipPath} | head -20`;
    const listResult = await ssh.execCommand(listZipCmd);
    log.info("zip文件內(nèi)容預(yù)覽:");
    console.log(listResult.stdout);

    // 創(chuàng)建臨時(shí)目錄并解壓
    const tempDir = `${remoteDir}/temp_dist_${Date.now()}`;
    log.info(`解壓到臨時(shí)目錄: ${tempDir}`);

    // 解壓命令:使用 -o 覆蓋已存在文件
    const unzipCmd = `mkdir -p ${tempDir} && unzip -o -q ${remoteZipPath} -d ${tempDir}`;
    const unzipResult = await ssh.execCommand(unzipCmd);

    if (unzipResult.code !== 0) {
      log.error(`解壓錯(cuò)誤: ${unzipResult.stderr}`);
      // 清理臨時(shí)目錄
      await ssh.execCommand(`rm -rf ${tempDir}`);
      throw new Error(`解壓失敗: ${unzipResult.stderr}`);
    }

    // 檢查解壓后的內(nèi)容和文件數(shù)量
    const checkContentCmd = `ls -lah ${tempDir} | head -20 && echo "--- 文件統(tǒng)計(jì) ---" && find ${tempDir} -type f | wc -l`;
    const contentResult = await ssh.execCommand(checkContentCmd);
    log.info("解壓后的內(nèi)容:");
    console.log(contentResult.stdout);

    // 刪除舊dist并用臨時(shí)目錄替換(使用原子操作)
    log.info(`正在替換目標(biāo)目錄: ${remoteDistPath}`);

    // 方案:先刪除舊的,再重命名新的(更可靠)
    const deleteOldCmd = `rm -rf ${remoteDistPath}`;
    const deleteResult = await ssh.execCommand(deleteOldCmd);

    if (deleteResult.code !== 0 && deleteResult.stderr) {
      log.warning(`刪除舊目錄警告: ${deleteResult.stderr}`);
    }

    const moveCmd = `mv ${tempDir} ${remoteDistPath}`;
    const moveResult = await ssh.execCommand(moveCmd);

    if (moveResult.code !== 0) {
      log.error(`移動(dòng)失敗: ${moveResult.stderr}`);
      throw new Error(`替換文件失敗: ${moveResult.stderr}`);
    }

    log.success("替換完成");

    // 驗(yàn)證最終結(jié)果 - 顯示詳細(xì)信息
    log.info("正在驗(yàn)證部署結(jié)果...");
    const verifyCmd = `
      echo "=== 目錄內(nèi)容 ===" && 
      ls -lah ${remoteDistPath} | head -20 && 
      echo "" && 
      echo "=== 文件統(tǒng)計(jì) ===" && 
      echo "總文件數(shù): $(find ${remoteDistPath} -type f | wc -l)" && 
      echo "總目錄數(shù): $(find ${remoteDistPath} -type d | wc -l)" && 
      echo "總大小: $(du -sh ${remoteDistPath} | cut -f1)" &&
      echo "" &&
      echo "=== index.html 信息 ===" &&
      ls -lh ${remoteDistPath}/index.html 2>/dev/null || echo "index.html 不存在"
    `;
    const verifyResult = await ssh.execCommand(verifyCmd);
    console.log(verifyResult.stdout);

    if (verifyResult.code !== 0) {
      log.warning("驗(yàn)證過程中出現(xiàn)警告,但部署已完成");
    }

    // 刪除zip文件
    await ssh.execCommand(`rm -f ${remoteZipPath}`);
    log.success("清理臨時(shí)文件完成");
  } catch (error) {
    log.error(`操作失敗: ${error.message}`);
    // 清理可能的臨時(shí)目錄
    await ssh.execCommand(`rm -rf ${remoteDir}/temp_dist_*`);
    throw error;
  }
}

/**
 * 步驟8: 清理本地zip文件
 * @param {string} zipPath 本地zip文件路徑
 * @returns {void}
 */
function cleanupLocalZip(zipPath) {
  log.info("正在清理本地臨時(shí)文件...");
  try {
    if (fs.existsSync(zipPath)) {
      fs.unlinkSync(zipPath);
      log.success("本地臨時(shí)文件清理完成");
    }
  } catch (error) {
    log.warning(`清理本地文件失敗: ${error.message}`);
  }
}

/**
 * 主部署流程
 */
async function deploy() {
  const startTime = Date.now();
  console.log("\n");
  log.info("========================================");
  log.info("          開始自動(dòng)化部署流程");
  log.info("========================================");
  log.info(`目標(biāo)服務(wù)器: ${config.server.host}`);
  log.info(`部署目錄: ${config.deploy.remoteDir}/${config.deploy.remoteDist}`);
  log.info(`構(gòu)建模式: ${config.build.mode}`);
  log.info("========================================\n");

  let zipPath = "";

  try {
    // 1. 打包項(xiàng)目
    await buildProject();
    console.log("\n");

    // 2. 壓縮dist
    zipPath = await compressDistToZip();
    console.log("\n");

    // 3. 連接SSH
    await connectSSH();
    console.log("\n");

    // 4. 備份服務(wù)器dist
    await backupRemoteDist();
    console.log("\n");

    // 5. 上傳zip
    await uploadZipToServer(zipPath);
    console.log("\n");

    // 6. 解壓zip并替換dist
    await unzipAndReplaceDist();
    console.log("\n");

    // 8. 清理本地zip
    cleanupLocalZip(zipPath);
    console.log("\n");

    const duration = ((Date.now() - startTime) / 1000).toFixed(2);
    log.info("========================================");
    log.success(`       部署成功! 耗時(shí): ${duration}秒`);
    log.info("========================================\n");
  } catch (error) {
    log.error(`\n部署失敗: ${error.message}\n`);
    // 清理本地文件
    if (zipPath) {
      cleanupLocalZip(zipPath);
    }
    process.exit(1);
  } finally {
    // 斷開SSH連接
    if (ssh.isConnected()) {
      ssh.dispose();
      log.info("SSH連接已關(guān)閉");
    }
  }
}

// 執(zhí)行部署
if (require.main === module) {
  deploy();
}

module.exports = { deploy };
  1. deploy/config.XX.js :多環(huán)境服務(wù)器配置文件
    集中管理 prod/xj/mj/test 四個(gè)環(huán)境的SSH 連接信息、服務(wù)器部署目錄,后續(xù)修改環(huán)境配置僅需改此文件,按需替換你的實(shí)際配置:
 * 測(cè)試環(huán)境部署配置
 * @description 測(cè)試服務(wù)器配置
 */
module.exports = {
  // 服務(wù)器配置
  server: {
    host: "1.1.1.1",
    port: 22,
    username: "admin",
    password: "123",
  },

  // 部署配置
  deploy: {
    localDistPath: "./dist",
    localZipName: "dist.zip",
    remoteDir: "/home/web",
    remoteDist: "dist",
    backupDir: "/home/web/backup",
  },

  // 構(gòu)建配置
  build: {
    command: "npm run build:test",
    mode: "test",
  },
};

四、package.json 腳本說(shuō)明(你的原有配置,無(wú)需修改)

你的 package.json 中已配置好多環(huán)境啟動(dòng)、打包、部署腳本,對(duì)應(yīng)關(guān)系如下,直接執(zhí)行即可:

  // 本地啟動(dòng)腳本(按環(huán)境區(qū)分,無(wú)需修改)
  "serve": "vue-cli-service serve",
  "dev": "vue-cli-service serve",
  "test": "vue-cli-service serve --mode test",
  "start": "npm run dev",
  // 核心部署腳本:執(zhí)行后自動(dòng)打包+發(fā)布到對(duì)應(yīng)服務(wù)器
  "deploy:prod": "node deploy/index.js --env=prod",
  "deploy:xj": "node deploy/index.js --env=xj",
  "deploy:mj": "node deploy/index.js --env=mj",
  "deploy:test": "node deploy/index.js --env=test",
}

五、使用說(shuō)明

修改配置:先修改 deploy/config.js 中四個(gè)環(huán)境的服務(wù)器 IP、賬號(hào)、密碼 、部署目錄,確保信息正確;
執(zhí)行部署:在項(xiàng)目根目錄執(zhí)行對(duì)應(yīng)環(huán)境的部署命令,全程自動(dòng)化,示例:

npm run deploy:prod
# 部署到測(cè)試環(huán)境
npm run deploy:test

部署流程:執(zhí)行命令后,腳本會(huì)自動(dòng)完成「環(huán)境打包 → 壓縮 dist → SSH 連服務(wù)器 → 上傳解壓 → 清理臨時(shí)文件」,全程控制臺(tái)輸出彩色日志,成功 / 失敗一目了然。

六、關(guān)鍵注意事項(xiàng)

服務(wù)器準(zhǔn)備:

  • 安裝unzip工具(CentOS執(zhí)行yum install unzip -y,Ubuntu執(zhí)行apt install unzip -y)
  • 確保部署目錄具有讀寫權(quán)限(推薦使用root賬戶或授權(quán)對(duì)應(yīng)賬號(hào))

打包配置:

  • 默認(rèn)test環(huán)境執(zhí)行npm run build:test
  • 其他環(huán)境執(zhí)行npm run build

日志與錯(cuò)誤處理:

  • 任一環(huán)節(jié)失敗時(shí)自動(dòng)終止流程,并輸出紅色錯(cuò)誤提示
  • 自動(dòng)清理臨時(shí)文件并斷開SSH連接,確保無(wú)資源殘留

部署說(shuō)明:

  • 安裝核心依賴:npm i node-ssh archiver rimraf -D

主要配置文件:

  1. deploy/config.xx.js(多環(huán)境服務(wù)器配置)
  2. deploy/index.js(自動(dòng)化部署邏輯)
  3. 執(zhí)行命令:npm run deploy:xxx,自動(dòng)完成「打包→壓縮→上傳→解壓」全流程服務(wù)器準(zhǔn)備:
  4. 確保服務(wù)器安裝了 unzip 命令(用于解壓,若未安裝執(zhí)行 yum install unzip -y(CentOS)或 apt install unzip -y(Ubuntu));
  5. 服務(wù)器部署目錄需有讀寫權(quán)限(建議用 root 或賦予對(duì)應(yīng)賬號(hào)權(quán)限);
  6. 打包匹配:腳本中默認(rèn) test 環(huán)境執(zhí)行 npm run build:test,其他環(huán)境執(zhí)行 npm run build,若 xj/mj 需單獨(dú)打包,可在 buildProject 函數(shù)中新增判斷;
  7. 日志輸出:腳本使用 stdio: “inherit” 讓打包、解壓的日志直接輸出到控制臺(tái),方便排查問題;
  8. 錯(cuò)誤處理:任意步驟失敗都會(huì)終止腳本,并輸出紅色錯(cuò)誤信息,同時(shí)清理臨時(shí)文件、斷開 SSH 連接,避免資源殘留。

七、總結(jié)

  • 核心依賴為 node-ssh(SSH 連接)和 archiver(壓縮),需先執(zhí)行 npm i node-ssh archiver rimraf -D 安裝;
  • 核心文件是 deploy/config.js(多環(huán)境服務(wù)器配置)和 deploy/index.js(自動(dòng)化部署邏輯),無(wú)需修改原有 package.json;
  • 部署命令直接用你原有配置的 npm run deploy:xxx,全程自動(dòng)化完成「打包→壓縮→上傳→解壓」,無(wú)需手動(dòng)操作服務(wù)器;

到此這篇關(guān)于基于Vue+Node.js自動(dòng)發(fā)布服務(wù)腳本的文章就介紹到這了,更多相關(guān)Vue Node.js自動(dòng)發(fā)布服務(wù)腳本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue 使用中的小技巧

    Vue 使用中的小技巧

    這篇文章主要介紹了Vue 使用中的小技巧,是小編日常開發(fā)的時(shí)候用到的小技巧,需要的朋友可以參考下
    2018-04-04
  • 更強(qiáng)大的vue ssr實(shí)現(xiàn)預(yù)取數(shù)據(jù)的方式

    更強(qiáng)大的vue ssr實(shí)現(xiàn)預(yù)取數(shù)據(jù)的方式

    這篇文章主要介紹了更強(qiáng)大的 vue ssr 預(yù)取數(shù)據(jù)的方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • vue組件以及父子組件通信方式

    vue組件以及父子組件通信方式

    這篇文章主要介紹了Vue組件化的基本概念,包括什么是組件化、Vue的組件化思想以及如何在Vue中注冊(cè)和使用組件,文章還詳細(xì)講解了如何進(jìn)行父子組件之間的通信,包括父組件傳遞數(shù)據(jù)給子組件和子組件通過自定義事件將數(shù)據(jù)傳遞給父組件,文章最后通過一個(gè)綜合練習(xí)來(lái)鞏固所學(xué)知識(shí)
    2025-02-02
  • el-select 數(shù)據(jù)回顯,只顯示value不顯示lable問題

    el-select 數(shù)據(jù)回顯,只顯示value不顯示lable問題

    這篇文章主要介紹了el-select 數(shù)據(jù)回顯,只顯示value不顯示lable問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 在vue中使用screenfull?依賴,實(shí)現(xiàn)全屏組件方式

    在vue中使用screenfull?依賴,實(shí)現(xiàn)全屏組件方式

    這篇文章主要介紹了在vue中使用screenfull?依賴,實(shí)現(xiàn)全屏組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 基于vue的換膚功能的示例代碼

    基于vue的換膚功能的示例代碼

    本篇文章主要介紹了基于vue的換膚功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-10-10
  • vue路由劃分模塊并自動(dòng)引入方式

    vue路由劃分模塊并自動(dòng)引入方式

    這篇文章主要介紹了vue路由劃分模塊并自動(dòng)引入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Vue實(shí)現(xiàn)Header漸隱漸現(xiàn)效果的實(shí)例代碼

    Vue實(shí)現(xiàn)Header漸隱漸現(xiàn)效果的實(shí)例代碼

    這篇文章主要介紹了Vue實(shí)現(xiàn)Header漸隱漸現(xiàn)效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • vue 組件間的通信之子組件向父組件傳值的方式

    vue 組件間的通信之子組件向父組件傳值的方式

    這篇文章主要介紹了vue 組件間的通信之子組件向父組件傳值的方式總結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • vue開發(fā)之LogicFlow自定義業(yè)務(wù)節(jié)點(diǎn)

    vue開發(fā)之LogicFlow自定義業(yè)務(wù)節(jié)點(diǎn)

    這篇文章主要為大家介紹了vue開發(fā)之LogicFlow自定義業(yè)務(wù)節(jié)點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論

平陆县| 和田市| 平顶山市| 冕宁县| 顺义区| 加查县| 定襄县| 汉阴县| 仁布县| 增城市| 玉田县| 清丰县| 丰宁| 芮城县| 化州市| 平罗县| 怀集县| 涟源市| 个旧市| 轮台县| 九江县| 乐陵市| 达州市| 若尔盖县| 车致| 土默特左旗| 庄河市| 门源| 闽清县| 永安市| 全椒县| 阿鲁科尔沁旗| 绥阳县| 镇平县| 奇台县| 益阳市| 庆安县| 宣化县| 钦州市| 西乌珠穆沁旗| 白银市|