8、命名空间 - Namespace

378 阅读2分钟

1、初识命名空间

以用类的形式在index.html中实现header,contentFooter部分为案例。test1.ts如下:

class Header {
    constructor() {
      const dom = document.createElement("div");
      dom.innerText = "Header";
      document.body.appendChild(dom);
    }
  }
  
  class Content {
    constructor() {
      const dom = document.createElement("div");
      dom.innerText = "Content";
      document.body.appendChild(dom);
    }
  }
  
  class Footer {
    constructor() {
      const dom = document.createElement("div");
      dom.innerText = "Footer";
      document.body.appendChild(dom);
    }
  }
  
  class Page {
    constructor() {
      new Header();
      new Content();
      new Footer();
    }
  }

index.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./build/test1.js"></script>
    <title>TSweb</title>
</head>
    <body>
        <script>new Page();</script>
    </body>
</html>

然后用tsc进行编译,再到浏览器进行预览,就可以看到对应的页面被展现出来了。

image.png

但是这样是有问题的,这样写全部都是全局变量(通过查看./build/test1.js文件可以看出全部都是var声明的变量)。过多的全局变量会让我们代码变的不可维护。

image.png

最理想的是,只要有Page这个全局变量就足够了,剩下的可以模块化封装起来,不暴露到全局,这时候就可以是有到命名空间 - Namespace。命名空间声明的关键词是namespace 比如声明一个namespace Test,需要暴露出去的类,可以使用export关键词,这样只有暴漏出去的类是全局的,其他的不会再生成全局污染了。如下:

namespace Test{ //声明一个`namespace Test`
    class Header {
        constructor() {
        const dom = document.createElement("div");
        dom.innerText = "Header";
        document.body.appendChild(dom);
        }
    }
    
    class Content {
        constructor() {
        const dom = document.createElement("div");
        dom.innerText = "Content";
        document.body.appendChild(dom);
        }
    }
    
    class Footer {
        constructor() {
        const dom = document.createElement("div");
        dom.innerText = "Footer";
        document.body.appendChild(dom);
        }
    }
    
    export class Page { //暴露出去的类,可以使用`export`关键词
        constructor() {
        new Header();
        new Content();
        new Footer();
        }
    }
}

index.html如下:

<body>
   <script>new Test.Page();</script>
</body>

这就是 TypeScript 给我们提供的类似模块化开发的语法,它的好处就是让全局变量减少了很多,实现了基本的封装,减少了全局变量的污染。

2、用命名空间实现组件化

src目录下新建一个文件Top.ts,编写代码如下:

namespace Top {
    export class topLeft {
      constructor() {
        const elem = document.createElement("div");
        elem.innerText = "topLeft";
        document.body.appendChild(elem);
      }
    }
  
    export class topCenter {
      constructor() {
        const elem = document.createElement("div");
        elem.innerText = "topCenter";
        document.body.appendChild(elem);
      }
    }
  
    export class topRight {
      constructor() {
        const elem = document.createElement("div");
        elem.innerText = "topRight";
        document.body.appendChild(elem);
      }
    }
  }

需要注意的是,这里每个类(class)都使用了export导出,导出后就可以在test1.ts中使用这些组件了。代码如下:

    export class Page {
        constructor() {
        new Header();
        new Content();
        new Footer();
        new Top.topLeft();
        new Top.topCenter();
        new Top.topRight();
        }
    }

然后使用tsc进行重新编译,但在预览时,会发现还是会报错,找不到Top,想解决这个问题,我们必须要在index.html里进行引入Top.js文件。

    <script src="./build/test1.js"></script>
    <script src="./build/Top.js"></script>

但是这样引入的话,太麻烦了,我们同样可以像webpack一样,只生成一个文件。

3、多文件编译为一个文件

直接打开tsconfig.json文件,然后找到outFile配置项,这个就是用来生成一个文件的设置,但是如果设置了它,就不再支持"module":"commonjs"设置了,我们需要把它改成"module":"amd",然后在去掉对应的outFile注释,设置成下面的样子。

{
  "outFile": "./build/test1.js"
}

这样index.html中就只需要引入test1.js,不需要引入Top.js了。

<script src="./build/test1.js"></script>

4、子命名空间

就是在命名空间里,再写一个命名空间,简单说就是嵌套。

namespace Top {
  export namespace TopLeft {
    export class topLeft {}
  }
  //...
}

学习日期:2022/1/6

视频参考www.bilibili.com/video/BV1qV…

文档参考jspang.com/detailed?id…

仅供个人学习和记录