掌握JS模塊化開發,編寫高可用代碼

開發一個模塊管理引擎:css

<!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>

 

模塊的基本使用: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.jsnode

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

 

模塊延遲解析與嚴格模式:webpack

<!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>

 

做用域在模塊中的體現:web

<!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>

 

預解析的必要性:npm

<!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>

 

模塊的具名導出與導入:json

// 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 };

 

批量導入與建議:api

<!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>

 

別名使用:app

<!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.jsless

// 批量導出
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頁面背景已經變成了粉色~

相關文章
相關標籤/搜索