1. 程式人生 > 實用技巧 >掌握JS模組化開發,編寫高可用程式碼

掌握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頁面背景已經變成了粉色~