掌握JS模块化开发,编写高可用代码

  • A+
所属分类:Web前端
摘要

开发一个模块管理引擎: 模块的基本使用:script.js 模块延迟解析与严格模式:

开发一个模块管理引擎:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>      <script>         //AMD require.js         // CMD sea.js         //COMMONJS Node.js         //UMD          let module = (function () {             const moduleList = {};              function define(name, modules, action) {                 modules.map((m, i) => {                     modules[i] = moduleList[m]; //获取到依赖的方法                 });                  moduleList[name] = action.apply(null, modules);                 // console.log(moduleList);             }              return { define };          })();          module.define('arr', [], function () {             console.log('define');             return {                 first(arr) {                     return arr[0];                 },                 max(arr, key) {                     return arr.sort((a, b) => b[key] - a[key])[0];                 }             }         });          module.define('lesson', ['arr'], function (arr) {             let data = [                 { name: 'html', price: 199 },                 { name: 'css', price: 265 },             ];             // console.log(arr);             console.log(arr.max(data, 'price'));         });          module.define('a', [], function () {             return {                 name: 'cyy',                 age: 18             }         });          module.define('b', ['a'], function (a) {             a.name = 'cyy2';         });          module.define('c', ['a'], function (a) {             console.log(a);         });        </script>  </body>  </html>

 

模块的基本使用:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>      <script type="module">         //引入时当前路径的./不可省略         import { name, age, show } from './script.js';         console.log(name, age);         show();       </script>  </body>  </html>

script.js

let name = 'cyy'; let age = 18; function show() {     console.log('show'); } export { name, age, show };

 

模块延迟解析与严格模式:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 模块会在最后执行,此时元素已经渲染完毕 -->     <!-- 使用type="module"时,默认是严格模式 -->     <script type="module">         let div0 = document.querySelector('div');         console.log(div0);     </script>       <!-- 普通js必须在元素渲染之后使用 -->     <script>         let div = document.querySelector('div');         console.log(div);     </script>      <div>cyy</div>      <script>         let div2 = document.querySelector('div');         console.log(div2);     </script>  </body>  </html>

 

作用域在模块中的体现:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 普通脚本在全局顶级作用域里 -->     <script>         let url = 'www.baicu.com';         console.log(url);     </script>      <!-- module在自己的块级作用域里 可以访问顶级作用域的内容 但是顶级作用域里的内容不能访问到module里面的 -->      <!-- 想要使用module里的内容,必须要通过导入和导出 -->     <script type="module">         // console.log(url);          let cyy = 'cyy';         export { cyy };     </script>      <script>         console.log(url);     </script>  </body>  </html>

 

预解析的必要性:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 多次重复导入时会报错 -->     <script type="module">         import { name, age } from './script.js';         import { name, age } from './script.js';         import { name, age } from './script.js';         console.log(name);     </script>  </body>  </html>

 

模块的具名导出与导入:

// export let name = 'cyy'; // export function show() { console.log('show') } // export class User { //     static func() { //         console.log('User-static-func'); //     } // } // 具名导出   // 批量导出 let name = 'cyy'; function show() { console.log('show') } class User {     static func() {         console.log('User-static-func');     } } export { name, show, User };

 

批量导入与建议:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 具名导入 -->     <script type="module">         // 批量导入并设置别名         import * as api from './script.js';          console.log(api.name);         api.show();         api.User.func();     </script>  </body>  </html>

 

别名使用:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 具名导入 -->     <script type="module">          // 给导入的模块设置别名         import { name as n, s } from './script.js';         let name = 'cyy2';         console.log(n);         console.log(name);          s();     </script>  </body>  </html>

script.js

// 批量导出 let name = 'cyy'; function show() { console.log('show') } class User {     static func() {         console.log('User-static-func');     } } // 导出也可以设置别名 export { name, show as s, User };

 

default默认导出:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 具名导入 -->     <script type="module">          // 默认导出的模块,导入时随便起什么名字都可以         // import myModule from './script.js';         // myModule.func();           import myModule from './script.js';         myModule.func();     </script>  </body>  </html>

script.js

// 当模块只有一个功能时,可以设置默认导出  // 默认导出1 // export default class User { //     static func() { //         console.log('User-static-func'); //     } // }   // 默认导出2 class User {     static func() {         console.log('User-static-func');     } } export { User as default };

 

混合导入导出的使用:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 具名导入 -->     <script type="module">          // 具名导出的需要花括号,默认导出的不需要花括号         // import myModule, { show } from './script.js';         // myModule.func();         // show();           import * as api from './script.js';         console.log(api);     </script>  </body>  </html>

script.js

// export default class User { //     static func() { //         console.log('User-static-func'); //     } // } // export function show() { //     console.log('show'); // }   class User {     static func() {         console.log('User-static-func');     } } function show() {     console.log('show'); } export { User as default, show };

 

默认导出模块的使用规范:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <!-- 具名导入 -->     <script type="module">          // 默认导出的模块建议跟文件名同名,这样比较规范         import script from './script.js';         script.func();      </script>  </body>  </html>

 

模块的合并导出:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <script type="module">         import * as api from './index.js';         console.log(api);     </script>  </body>  </html>

index.js

import * as script from './script.js'; import * as script2 from './script2.js';  export { script, script2 };

script.js

export default class User {     static func() {         console.log('User-static-func');     } }

script2.js

let name = 'cyy'; function show() {     console.log('show');  } export { name, show };

 

按需动态加载模块:

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>demo</title>     <style>     </style> </head>  <body>     <button>click me</button>      <script type="module">         // document.querySelector('button').addEventListener('click', function () {         //     //点击按钮之后按需加载模块         //     import('./script.js').then(module => {         //         console.log(module);         //     })         // });           document.querySelector('button').addEventListener('click', function () {             //点击按钮之后按需加载模块             import('./script2.js').then(({ name, show }) => {                 console.log(name);                 show();             })         });     </script>  </body>  </html>

script2.js

let name = 'cyy'; function show() {     console.log('show');  } export { name, show };

 

WEBPACK构建项目的软件安装:

webpack打包工具,安装之前先安装node.js

使用一下命令生成配置文件package.json

npm init -y

 

安装webpack工具包,如果安装慢可以使用淘宝 cnpm (opens new window)命令

cnpm i webpack webpack-cli --save-dev

 

修改package.json添加打包命令,实时查看更新后的效果

... "main": "index.js", "scripts": {     "dev": "webpack --mode development --watch" }, ...

 

目录结构

index.html --dist #压缩打包后的文件 --src ----index.js  #入口 ----style.js //模块

 

index.html内容如下

<!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>Document</title>   </head>   <body>     <script src="dist/main.js"></script>   </body> </html>

 

index.js内容如下

import style from "./style"; new style().init();

 

style.js

export default class Style {     constructor() {      }     init() {         document.body.style.backgroundColor = 'pink';     } }

 

执行打包

运行以下命令将生成打包文件到 dist目录,因为在命令中添加了 --watch参数,所以源文件编辑后自动生成打包文件。

npm run dev

 

可以看到html页面背景已经变成了粉色~