03_path模块

path

1、path路径模块

1.1、了解path

image-20220928004206020

1.2、导入path模块

与 fs 模块相同,path模块的导入方式也是通过require函数进行引用,通过传递字符串的方式,得到一个path模块对象,并且这个模块对象我们可以使用一个常量来进行接收

image-20220928004307276

2、path的一些常用方法

2.1、path.join()

  • 使用path.join()方法,可以将 多个路径片段拼接成完整的字符串路径
  • 语法格式如下
    • image-20220928004618548
  • 举个例子
    • image-20220928005028282

1、关于 ../ 和 ./

  • 使用相对路径的时候,../和./会抵消掉左边离他最近的一个目录
  • 我们来看个例子
    • image-20220928005244082

2、与__dirname一起使用

  • 本质上 __dirname也是一个字符串对象,所以可以作为path.join()方法当中的参数

    • image-20220928010259746

    • // 3、与__dirname一起使用
      // 引入fs模块
      const fs = require("fs")
      // 读取文件信息
      fs.readFile(path.join(__dirname,"../","demo2_使用readFile语法/text/成绩.txt"),"utf-8",(err,dataStr)=>{
          if(err){
              return
          }
          console.log(dataStr);
      })
      
  • 代码解析

    • image-20220928010415835

3、注意

今后凡是涉及到路径拼接问题的,都要使用 path.join()方法进行处理,不要直接使用 + 进行字符串拼接

image-20220928010609709

仔细看一下这个代码就知道了,./返回上一级目录,但是使用 +号拼接就会出现拼接出来是个 . 的情况

image-20220928010711120

2.2、path.basename()

  • 获取路径中的文件名
  • 使用该函数,可以获取一格路径下的,最后一部分,也就是咱们的文件部分通常用这个方法来获取路径当中的文件名,使用格式如下
    • image-20220928010906284
  • 第二个参数实际上指的是,如果你传递了这个参数,那么就会将得到的文件的后缀删除掉,也就是扩展名
  • 说人话就是,只需要拿到文件名称,不需要扩展名,那么就可以传递第二个参数

测试1

image-20220928144527034

// 引入path模块
const path = require("path")

// 这里配置一个需要读取文件的路径
var needPath = "D:\\技能学习\\node\\demo2_使用readFile语法\\text\\成绩.txt";

// 使用path.basename()函数,这里不传递第二个参数
var callPath = path.basename(needPath)
console.log('basename提取到的文件名为:'+ callPath);

image-20220928144553437

测试2

第二个参数为文件的扩展名,或者说后缀

image-20220928144758607

第二个参数是字符串,也就是说,实际上第二个参数的作用就是割裂掉这个字符串

image-20220928144928170

那如果第二个参数,根本就不是这个文件名的后缀呢?

image-20220928145016449

2.3、path.extname()

使用该函数,可以获取“路径中,文件名的扩展名部分(后缀)”

image-20220928145354557

应该是以 . 作为条件进行分割的,取出.右边的路径,无论这个路径是否合理

image-20220928145454157

image-20220928145602154

3、时钟案例

3.1、需求分析

  1. 这里有一个html文件

    • image-20220928151938290
  2. 在这个HTML文件当中,html代码,css代码,和js代码是一体的

    • <!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>
      </head>
      <style>
      	html,
          body {
            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>
      <body>
        <div class="box">
          <div id="HH">00</div>
          <div>:</div>
          <div id="mm">00</div>
          <div>:</div>
          <div id="ss">00</div>
        </div>
      </body>
      <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>
      </html>
      
  3. 我们现在需要通过path模块,fs模块,对这个html文件进行拆分,将其拆分成css,html,和js文件,同时,需要在html文件当中通过外链的形式来导入我们的css和js文件

3.2、步骤解读

  1. 首先,引入我们的path模块和fs模块
  2. 其次,我们需要创建正则表达式来匹配我们的css内容和js内容
    • image-20220928152727752
    • 解读部分
    • image-20220928152738564
  3. 使用fs模块读取html文件,使用path模块的join函数对路径进行拼接,增强代码维护性和移植性
    • image-20220928153458697
  4. 自定义函数,在这个函数当中完成对css文件的写入操作
    • 这个时候需要使用正则表达式了,但是我应该怎么读取?
    • fs可以读取到这个index.html文件,但是我应该如何将css的部分拆分出来?
  5. .exec()函数
    • 格式: 正则表达式.exec(需要匹配的字符串)
    • image-20220928163121950
    • 返回值
    • image-20220928164207254
  6. 之前的想法是没错的,String对象当中的match也可以做到,但是我没考虑返回值的问题

3.3、思想误区

image-20220928160442125

  • 先看下这个代码吧,我犯了个什么错误?
  • 我想的是,给css和js的函数,外增加一个额外的函数供他们调用
  • 因为需要正则表达式来对匹配内容进行读取,所以readFile()是必须要用的
  • 那我就专门为readFile这个函数单独封装一个方法,供二者调用(误区
  • 那么,readFile被调用了,没问题,那么剩下的css函数和js函数谁来调用?
  • 在前端里面,我们调用函数大可以使用window这个全局对象来对js代码进行解读和函数调用
  • 而在node当中,谁来调用?node对象吗?node对象如何调用一个我自定义的方法?应该是有的,但是现在我没法接触
  • 这就是一个思想误区
  • 所以解决问题的方法,就是用 可以被node直接调用的API对象来对我自定义的方法进行调用和解析

3.4、改进

  1. 引入fs模块和path模块
  2. 编写css和js内容的正则表达式
  3. 为写入css文件和js文件还有html文件做准备 == fs.wirteFile()
    1. .exec():String对象的一个正则表达式匹配函数
      • 语法:String(这里代表的是正则表达式).exec(需要进行匹配的字符串)
    2. .match():与exec函数同理,二者用法相似
      • 语法:String(需要进行匹配的字符串).match(这里放正则表达式)
    3. 二者的返回值都是数组对象,索引为0的内容就是我们匹配出来的内容
  4. 对写入css文件的函数和js文件的函数进行标签的去除 == replace()
    • image-20220928174602117
    • 当然,参数1也可以是正则表达式,这样可以表示一片区域的内容替换
    • image-20220928174629078
  5. 我们肯定是需要通过fs模块的writeFile进行文件写入,那就单独为其封装一个方法
  6. 最后,通过fs.readFile(),函数进行index.html文件的读取,然后在这个函数当中对三个函数进行调用,避免异步的问题发生

3.5、代码

/*
 * @Author: WavesBright 1336959829@qq.com
 * @Date: 2022-09-28 14:56:43
 * @LastEditors: WavesBright 1336959829@qq.com
 * @LastEditTime: 2022-09-28 17:06:14
 * @FilePath: \node\demo3_path模块\04_时钟(综合案例).js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// 1、引入path模块和fs模块
const path = require('path')
const fs = require('fs')

// 2、创建正则表达式,对css内容和js内容进行匹配
/* 
    //:代表这是一个正则表达式

    <style><\/style>:以<style>开头,以</style>结尾
        \的目的是因为在代码当中的转译问题,所以需要正斜杠
    

    []:匹配区间,
    \s:任意空字符,\S:任意非空字符
    *:代表匹配任意多个
*/
const meatInCss = /<style>[\s\S]*<\/style>/
const meatInJs = /<script>[\s\S]*<\/script>/

// 3、使用fs模块读取我们的html文件
var readPath = "clock/index.html"
fs.readFile(path.join(__dirname,readPath),"utf-8",(err,dataStr)=>{
    if(err){
        return
    }
    // 写入css文件
    writeInCss(dataStr)

    // 写入js文件
    writeInJs(dataStr)

    // 更新html文件,引入外链
    writeInHtml(dataStr)
    
})

// 定义一个函数,来写入css样式(fs.writeFile)
/**
 * css写入内容
 * @param {匹配到的css模块内容} writeContent 
 */
function writeInCss(writeContent){
    // 对readFile读取的内容进行拆分
    var str = meatInCss.exec(writeContent)

    // 去除头部和尾部的<style>标签
    var newCss = str[0].replace("<style>","").replace("</style>","")

    // 调用自定义封装的写入方法
    writeToFile("clock/index.css",newCss)
}

// 定义一个函数,来写入js样式(fs.writeFile)
/**
 * js写入内容
 * @param {匹配到的css模块内容} writeContent 
 */
 function writeInJs(writeContent){
    // 对readFile读取的内容进行拆分
    var str = meatInJs.exec(writeContent)
    
    // 去除头部和尾部的<script>标签
    var newJs = str[0].replace("<script>","").replace("</script>","")

    // 调用自定义封装的写入方法
    writeToFile("clock/index.js",newJs)
}

/**
 * 重新写入HTML文件
 * @param {读取到的HTML文件内容} writeContent 
 */
function writeInHtml(writeContent){
    // replace的第二个用法,参数1可以是一个正则表达式对象
    // 1、将<style>标签的内容替换为外链,2、将<script>标签的内容替换为外链
    var str = writeContent.replace(meatInCss,"<link rel='stylesheet' href='./index.css' />")
    .replace(meatInJs,"<script src='./index.js' />")

    // 调用封装方法写入内容
    writeToFile("clock/index.html",str)

}

/**
 * 为写入css和js单独封装的fs模块写入方法
 * @param {*} path 写入的文件路径是?
 * @param {*} writeContent 写入的文件内容是?
 */
function writeToFile(writePath,writeContent){
    // 使用fs模块对其进行写入(不存在改文件,则新建)
    fs.writeFile(path.join(__dirname,writePath),writeContent,(err)=>{
        if(!err){
            console.log("写入成功");
        }else{
            console.log(err + "写入失败");
        }
    })
}


3.6、总结

整体来说这个案例还是蛮有意思的,虽然泛用性比较小,但是其中的一些函数,String对象当中的函数,在以后可能会经常用到,还是有收获的

  • .exec()
  • .mathc()
  • .replace()
posted @ 2022-10-02 22:59  澜璨  阅读(82)  评论(0)    收藏  举报