>  기사  >  웹 프론트엔드  >  js를 사용하여 간단한 모듈 로더를 구현하는 방법

js를 사용하여 간단한 모듈 로더를 구현하는 방법

一个新手
一个新手원래의
2017-10-11 10:07:231576검색


머리말

얼마전에 require.js 소스코드를 분석해봤는데 전체적인 분석이 좀 일반적이고, 내용이 좀 빈약하고, requirejs 의존성 처리의 본질을 파악하지 못했어요. require.js 소스 코드에 대한 가장 실패한 분석입니다.

구현 내용은 잘 이해하지 못하더라도 소스 코드 구성과 기본 로직 실행에 대해서는 전반적으로 이해하고 있습니다.

이 글은 인터넷에 있는 소스코드를 참고하여 그 아이디어로 구현한 간단한 모듈 로더를 분석하여 require.js에 대한 지식과 이해를 심화시키는 것을 목표로 합니다.

구현 아이디어

우선 다음 사항이 분명합니다.

  • require 함수가 호출될 때마다 Context 객체가 생성됩니다

  • Module 객체는 모듈 객체를 나타내며, 기본

위의 두 객체는 ​​이 간단한 모듈 로더를 구현하는 핵심입니다. 로딩 프로세스 중 처리 흐름은 아래 그림과 같습니다.
js를 사용하여 간단한 모듈 로더를 구현하는 방법
js를 사용하여 간단한 모듈 로더를 구현하는 방법代码

의 속성은 다음과 같습니다. 모듈 개체는 다음과 같습니다.

mid: 모듈 ID를 나타냅니다.
src: 모듈 경로
이름: 모듈 이름
deps: 모듈 종속성 목록
콜백: 콜백 함수
errback: 오류 처리 기능
상태: 모듈 상태
내보내기: 콜백 함수 매개변수 시퀀스에 해당하는 모듈 출력

Module의 프로토타입 개체에는 다음과 같은 메서드가 있습니다.

init: 모듈 개체의 초기화 처리
가져오기: 스크립트 노드를 생성하고 요소 노드에 추가합니다
checkCycle: 순환 종속성을 처리하고 현재 순환 종속성 목록을 반환합니다
handlerDeps: 종속성 목록 처리
changeStatus: 모듈의 상태를 변경합니다. 주로 모듈이 성공적으로 로드되었는지 여부를 처리합니다.
실행: 모든 종속 모듈이 성공적으로 로드된 후 매개변수 목록을 얻는 방법

종속성 목록을 처리하는 방법

실제로 종속성 목록 처리는 정의 및 요구의 처리 코드에서 처리됩니다. 함수와 require 함수는 다음과 같습니다.
js를 사용하여 간단한 모듈 로더를 구현하는 방법

먼저 require 함수를 살펴보세요. 예:

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

위에서 알 수 있듯이 require 함수가 호출되면 종속성 목록은 ['a', 'b입니다. ']이고 콜백 함수는 function(a, b) {console.log( a, b);}

require 코드에서 볼 수 있듯이 Context 생성자가 호출되어 Context 객체를 생성합니다. Context 생성자의 처리 시: let Context = function(deps, callback, errback) {

    this.cid = ++contextId;
    this.init(deps, callback, errback);
}
;
    Context.prototype.init = function(deps, callback, errback) {
    this.deps = deps;
    this.callback = callback;
    this.errback = errback;
    contexts[this.cid] = this;
}
;

위에서 중요한 것은 contexts[this.cid] = this입니다. 현재 Context 개체를 전역 컨텍스트 개체에 등록합니다. 수집.

그런 다음 종속성 목록을 처리하는 handlerDeps 함수를 호출합니다. 구체적인 코드는 다음과 같습니다. handlerDeps: function() {

    let depCount = this.deps ? this.deps.length : 0;
    // require.js中处理循环依赖的处理 let requireInDep = (this.deps || []).indexOf('require');
    if (requireInDep !== -1) {
    depCount--;
    this.requireInDep = requireInDep;
    this.deps.splice(requireInDep, 1);
}
// 处理循环依赖情况 let cycleArray = this.checkCycle();
    if (cycleArray) {
    depCount = depCount - cycleArray.length;
}
// depCount表示当前模块的依赖模块数,depCount为0表示模块中某一依赖加载完成 this.depCount = depCount;
    if (depCount === 0) {
    this.execute();
    return;
}
// 遍历依赖列表,创建Module对象,并且将当前模块与其依赖的关系构建出来maps this.deps.forEach((depModuleName) => {
    if (!modules[depModuleName]) {
    let module = new Module(depModuleName);
    modules[module.name] = module;
}
if (!maps[depModuleName]) {
    maps[depModuleName] = [];
}
maps[depModuleName].push(this);
}
);

}순환 종속성 처리

이 구현 코드는 순환 종속성을 처리합니다. 콜백 함수에서 require 및 require를 다시 전달하는 require.js의 공식 메서드입니다. 이것이 순환 종속성을 해결할 수 있는 이유는 무엇입니까?

이 구현에 관한 한 require는 Context 개체를 한 번 생성하기 때문입니다. 주요 코드는 다음과 같습니다. // require.js에서 순환 종속성 처리 let requireInDep = (this.deps || []).indexOf('require');

   if (requireInDep !== -1) {
    depCount--;
    this.requireInDep = requireInDep;
    this.deps.splice(requireInDep, 1);
}
// 获取循环依赖 let cycleArray = this.checkCycle();
    if (cycleArray) {
    depCount = depCount - cycleArray.length;
}
// execute函数中代码// 插入require到回调函数的参数列表中if (this.requireInDep !== -1 && this.requireInDep !== undefined) {
    arg.splice(this.requireInDep, 0, require);
}

Conclusion

종이에 완성됨 Jue Qian은 이 문제를 구현해야 한다는 것을 알고 간단한 모듈 로더를 구현함으로써 require.js 모듈 로딩에 대한 아이디어와 논리적 처리가 더 명확해질 것입니다.

require.js는 js 파일의 비동기 로딩을 다르게 처리하지만 본질은 동일합니다. require.js는 head 태그에 스크립트 노드를 추가하고 스크립트는 비동기 로딩을 달성하기 위해 async 속성을 추가합니다.

위 내용은 js를 사용하여 간단한 모듈 로더를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.