Notes
Node.js
案例:时钟

目标效果

1

  • 将单个 index.html 页面拆分成三个文件:分别是 html 、 js 、 css 文件。拆分后放在 clock 目录中。

原始代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>index首页</title>
    <style>
        html,
        baby {
            margin: 0;
            padding: 0;
            height: 100%;
            background-image: linear-gradient(to bottom right, red, gold);
        }
 
        .box {
            width: 400px;
            height: 250px;
            background-color: rgba(255, 255, 255, 0.6);
            border-radius: 6px;
            position: absolute;
            left: 50%;
            top: 40%;
            transform: translate(-50%, -50%);
            box-shadow: 1px 1px 10px #fff;
            text-shadow: 0px 1px 30px white;
            display: flex;
            justify-content: space-around;
            align-items: center;
            font-size: 70px;
            user-select: none;
            padding: 0 20px;
 
            /*    盒子投影*/
            -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent),
            color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
        }
    </style>
</head>
<body>
<div class="box">
    <div id="HH">00</div>
    <div>:</div>
    <div id="mm">00</div>
    <div>:</div>
    <div id="ss">00</div>
</div>
<script>
    window.onload = function () {
        //    定时器,每隔1秒执行1次
        setInterval(() => {
            var dt = new Date()
            var HH = dt.getHours()
            var mm = dt.getMinutes()
            var ss = dt.getSeconds()
 
            //    为页面上的元素赋值
            document.querySelector('#HH').innerHTML = padZero(HH)
            document.querySelector('#mm').innerHTML = padZero(mm)
            document.querySelector('#ss').innerHTML = padZero(ss)
        }, 1000)
    }
 
    //    补零函数
    function padZero(n) {
        return n > 9 ? n : '0' + n
    }
</script>
</body>
</html>

分析

  • 创建正则表达式,分别来匹配 style 标签和 script 标签。
  • 使用 fs 模块,读取需要处理的 HTML 文件。
  • 自定义 resolveCSS 方法(拆解),写入 index.css 文件。
  • 自定义 resolveJS 方法(拆解),写入 index.js 文件。
  • 自定义 resolveHTML 方法(拆解),写入 index.html 文件。

正则表达式

const fs = require("fs");
const path = require("path");
 
//正则表达式
const regStyle = /<style>[\s\S]*<\/style>/;
const regScript = /<script>[\s\S]*<\/script>/;
// \s 表示空白字符,\S标识非空白字符,*表示匹配任意次数

读取原始 HTML 文件

...
// 读取原始文件,将HTML代码以纯文本的方式读入
fs.readFile(
  path.join(__dirname, "../index.html"),
  "utf8",
  function (err, dataStr) {
    // 读取失败
    if (err) {
      return console.log("读取HTML失败!");
    }
    // 拆分
    resolveCSS(dataStr);
    resolveJS(dataStr);
    resolveHTML(dataStr);
  }
);
...

拆分CSS代码

function resolveCSS(htmlStr) {
  // 调用正则表达式匹配
  const r1 = regStyle.exec(htmlStr);
  // 处理提取后的字符串,将标签去掉
  const newCSS = r1[0].replace("<style>", "").replace("</style>", "");
  fs.writeFile(
    path.join(__dirname, "./clock/index.css"),
    newCSS,
    function (err) {
      if (err) {
        return console.log(err.message);
      }
      console.log("写入css成功");
    }
  );
}

拆分JS代码

function resolveJS(htmlStr) {
  // 调用正则表达式匹配
  const r1 = regScript.exec(htmlStr);
  // 处理提取后的字符串,将标签去掉
  const newCSS = r1[0].replace("<script>", "").replace("</script>", "");
  fs.writeFile(
    path.join(__dirname, "./clock/index.js"),
    newCSS,
    function (err) {
      if (err) {
        return console.log(err.message);
      }
      console.log("写入js成功");
    }
  );
}

拆分HTML代码

// 读取原始文件,将HTML代码以纯文本的方式读入
function resolveHTML(htmlStr) {
  // 将原来的代码替换为链接
  const newHTML = htmlStr
    .replace(regStyle, '<link rel="stylesheet" href="./index.css"/>')
    .replace(regScript, '<script src="./index.js"/>');
  fs.writeFile(
    path.join(__dirname, "./clock/index.html"),
    newHTML,
    function (err) {
      if (err) {
        return console.log(err.message);
      }
      console.log("写入html成功");
    }
  );
}

完整代码

const fs = require("fs");
const { resolve } = require("path");
const path = require("path");
 
//正则表达式
const regStyle = /<style>[\s\S]*<\/style>/;
const regScript = /<script>[\s\S]*<\/script>/;
// \s 表示空白字符,\S标识非空白字符,*表示匹配任意次数
 
// 读取原始文件,将HTML代码以纯文本的方式读入
fs.readFile(
  path.join(__dirname, "/index.html"),
  "utf8",
  function (err, dataStr) {
    // 读取失败
    if (err) {
      return console.log("读取HTML失败!");
    }
    // 拆分
    resolveCSS(dataStr);
    resolveJS(dataStr);
    resolveHTML(dataStr);
  }
);
 
// 读取原始文件,将CSS代码以纯文本的方式读入
function resolveCSS(htmlStr) {
  // 调用正则表达式匹配
  const r1 = regStyle.exec(htmlStr);
  // exec 返回值是一个数组,数组的【0】是匹配好的结果
  // 处理提取后的字符串,将标签去掉
  const newCSS = r1[0].replace("<style>", "").replace("</style>", "");
  fs.writeFile(
    path.join(__dirname, "./clock/index.css"),
    newCSS,
    function (err) {
      if (err) {
        return console.log(err.message);
      }
      console.log("写入css成功");
    }
  );
}
// 读取原始文件,将JS代码以纯文本的方式读入
function resolveJS(htmlStr) {
  // 调用正则表达式匹配
  const r1 = regScript.exec(htmlStr);
  // 处理提取后的字符串,将标签去掉
  const newJS = r1[0].replace("<script>", "").replace("</script>", "");
  fs.writeFile(path.join(__dirname, "./clock/index.js"), newJS, function (err) {
    if (err) {
      return console.log(err.message);
    }
    console.log("写入js成功");
  });
}
// 读取原始文件,将HTML代码以纯文本的方式读入
function resolveHTML(htmlStr) {
  // 将原来的代码替换为链接
  const newHTML = htmlStr
    .replace(regStyle, '<link rel="stylesheet" href="./index.css"/>')
    .replace(regScript, '<script src="./index.js"/>');
  fs.writeFile(
    path.join(__dirname, "./clock/index.html"),
    newHTML,
    function (err) {
      if (err) {
        return console.log(err.message);
      }
      console.log("写入html成功");
    }
  );
}

控制台输出

PS D:\desk\FrontEnd\test\8-11> node clock
写入js成功
写入css成功
写入html成功

结果

1

运行 index.html :

2

注意点

  • writeFile 方法只能创建文件,但是不能创建路径(文件夹)
  • 重复调用 writeFile 时新内容会覆盖旧的内容。