얼마전에 require.js 소스코드를 분석해봤는데 전체적인 분석이 좀 일반적이고, 내용이 좀 빈약하고, requirejs 의존성 처리의 본질을 파악하지 못했어요. require.js 소스 코드에 대한 가장 실패한 분석입니다.
구현 내용은 잘 이해하지 못하더라도 소스 코드 구성과 기본 로직 실행에 대해서는 전반적으로 이해하고 있습니다.
이 글은 인터넷에 있는 소스코드를 참고하여 그 아이디어로 구현한 간단한 모듈 로더를 분석하여 require.js에 대한 지식과 이해를 심화시키는 것을 목표로 합니다.
우선 다음 사항이 분명합니다.
require 함수가 호출될 때마다 Context 객체가 생성됩니다
Module 객체는 모듈 객체를 나타내며, 기본
위의 두 객체는 이 간단한 모듈 로더를 구현하는 핵심입니다. 로딩 프로세스 중 처리 흐름은 아래 그림과 같습니다.
의 속성은 다음과 같습니다. 모듈 개체는 다음과 같습니다.
mid: 모듈 ID를 나타냅니다.
src: 모듈 경로
이름: 모듈 이름
deps: 모듈 종속성 목록
콜백: 콜백 함수
errback: 오류 처리 기능
상태: 모듈 상태
내보내기: 콜백 함수 매개변수 시퀀스에 해당하는 모듈 출력
Module의 프로토타입 개체에는 다음과 같은 메서드가 있습니다.
init: 모듈 개체의 초기화 처리
가져오기: 스크립트 노드를 생성하고 요소 노드에 추가합니다
checkCycle: 순환 종속성을 처리하고 현재 순환 종속성 목록을 반환합니다
handlerDeps: 종속성 목록 처리
changeStatus: 모듈의 상태를 변경합니다. 주로 모듈이 성공적으로 로드되었는지 여부를 처리합니다.
실행: 모든 종속 모듈이 성공적으로 로드된 후 매개변수 목록을 얻는 방법
실제로 종속성 목록 처리는 정의 및 요구의 처리 코드에서 처리됩니다. 함수와 require 함수는 다음과 같습니다.
먼저 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!