简介

说实话requireJS我没应用过,起因是接触的16年时候感觉很鸡肋,随后马上就用webpack ES6模块化和node的CommonJS了,昨天看文章看到了模块化,就想着这个货色如何实现。想想的确也不是很简略。
简略实现,没看源码,也可能思路不是这样,无所谓了,就是练练手

思路

requireJS的大略写法应该就是

require(['a', 'b'], function (a, b) {                console.log(b + a)            })

define(['c'], function (c) {    return 20 + c})

最根本的定义和应用就是这样了。

那么就开始剖析一下:

第一步:依据依赖项加载js文件;

既然要有依赖,那么必定要加载js文件,那么就要动静插入标签,插入标签很简略,那运行callback对应的参数变量怎么对应呢?

第二步:解决依赖项与callback运行时参数对应关系;

应用requirejs时候是define和require调用办法,这个时候引入js外面都是应用define来定义的。js加载结束会触发onload事件,并且是与某个文件加载程序是一一对应的,那么能够在onload外面去运行callback,至于callback须要的参数咱们能够定义一个变量去存储?

第三步:解决callback运行程序;

define办法会依赖某些js文件,那么总有一个源头,会不依赖其余js文件,这个模型就像俄罗斯套娃,一个套一个,或者是洋葱,或者是大盒子套小盒子之类的;

把有依赖项的文件的callback放在一个数组外面先放着,等到他的依赖项都有了再去执行它,执行完了之后删除;

是的,就是在onload外面去执行。

这样是不是就能够了呢?当然还不行,还要解决require办法的callback,依赖项曾经存在的状况,等等问题,这些问题都会影响加载后果。

上代码

a.js

define(['d'], function (d) {    return 10 + d})

b.js

define(['c'], function (c) {    return 20 + c})

c.js

define([], function () {    return 20})

d.js

define([], function () {    return 10})

require.js

(function () {    const variables = {}    let moudle = null    const tasks = []    const createNode = function (depend) {        let script = document.createElement("script");        script.src = `./${depend}.js`;        script.setAttribute("data-moduleName", depend);        let fs = document.getElementsByTagName('script')[0];        fs.parentNode.insertBefore(script, fs);        return script;    }    const hasAlldependencies = function (dependencies) {        let hasValue = true        dependencies.forEach(depd => {            if (!variables.hasOwnProperty(depd)) {                hasValue = false            }        })        return hasValue    }    const implementCallback = function (callbacks) {        if (callbacks.length) {            callbacks.forEach((callback, index) => {                if (hasAlldependencies(callback.dependencies)) {                    const returnValue = callback.callback(...callback.dependencies.map(it => variables[it]))                    if (callback.name) {                        variables[callback.name] = returnValue                    }                    tasks.splice(index, 1)                    implementCallback(tasks)                }            })        }    }    const require = function (dependencies, callback) {        if (!dependencies.length) { //这个文件没有依赖项            moudle = {                value: callback()              }        } else { //这个文件有依赖项            moudle = {                dependencies,                callback            }            tasks.push(moudle)            dependencies.forEach(function (item) {                if (!variables[item]) {                    createNode(item).onload = function () {                        let modulename = this.dataset.modulename                        if (moudle.hasOwnProperty('value')) {                            variables[modulename] = moudle.value                        } else {                            moudle.name = modulename                            if (hasAlldependencies(moudle.dependencies)) {                                variables[modulename] = el.callback(...moudle.dependencies.map(it => variables[it]))                            }                        }                        implementCallback(tasks) // 递归执行callback                    }                }            })        }    }    window.require = require    window.define = require})(window)

调用

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8">        <meta name="viewport" content="width=device-width, initial-scale=1.0">        <title>Document</title>    </head>    <body>        <script src="./require.js"></script>        <script>            require(['a', 'b'], function (a, b) {                console.log(b + a)            })        </script>    </body></html>