Salin kod Kod adalah seperti berikut:
// Kaedah _load() terutamanya menentukan fail sumber yang belum sedia lagi Jika semua fail sumber berada dalam keadaan sedia, panggil balik2
akan dilaksanakan.
// Dalam proses ini, kebergantungan bulat juga akan dinilai dan js yang dipunggah akan dimuatkan
Module.prototype._load = fungsi(uris, panggil balik2) {
//util.filter: Biarkan semua ahli data melaksanakan fungsi tertentu pada satu masa dan mengembalikan tatasusunan baharu, iaitu ahli yang mengembalikan benar selepas ahli tatasusunan asal melaksanakan panggilan balik
//unLoadedUris ialah tatasusunan uri modul yang belum disusun
var unLoadedUris = util.filter(uris, function(uri) {
//Mengembalikan ahli yang nilai Boolean bagi fungsi pelaksanaan adalah benar apabila uri wujud dan tidak wujud dalam cacheModul pembolehubah dalaman atau nilai statusnya dalam maklumat yang disimpan kurang daripada STATUS.READY
// Nilai STATUS.READY ialah 4. Jika kurang daripada empat, keadaan yang mungkin ialah ia sedang diperolehi atau dimuat turun.
Kembalikan uri && (!cachedModules[uri] ||
cachedModules[uri].status
});
//Jika semua modul dalam uris sedia, laksanakan panggilan balik dan keluar dari badan fungsi (pada masa ini, kaedah _compile modul akan dipanggil).
var length = unLoadedUris.length
if (panjang === 0) { callback2() return }
//Bilangan modul yang belum dimuatkan
var kekal = panjang
//Buat penutupan dan cuba muatkan modul yang tidak dimuatkan
untuk (var i = 0; i < panjang; i ) {
(fungsi(uri) {
//Tentukan jika maklumat storan uri tidak wujud dalam pembolehubah dalaman cachedModules, nyatakan objek Modul
var module = cachedModules[uri] ||
(CachedModules[uri] = Modul baharu(uri, STATUS.FETCHING))
//Jika nilai status modul lebih besar daripada atau sama dengan 2, ini bermakna modul telah dimuat turun dan sudah wujud secara setempat Pada masa ini, onFetched()
dilaksanakan
//Jika tidak, panggil fetch(uri, onFetched) dan cuba muat turun fail sumber Selepas fail sumber dimuat turun, onload akan dicetuskan dan kaedah panggilan balik onFetched akan dilaksanakan dalam onload.
modul.status >= STATUS.FETCHED ?
fungsi onFetched() {
modul = cachedModules[uri]
//Apabila nilai status modul lebih besar daripada atau sama dengan STATUS.SAVED, ini bermakna semua maklumat kebergantungan modul telah diperoleh
jika (modul.status >= STATUS.DISIMPAN) {
//getPureDependencies: Dapatkan tatasusunan kebergantungan tanpa kebergantungan bulat
var deps = getPureDependencies(modul)
//Jika tatasusunan kebergantungan tidak kosong
jika (deps.length) {
//Laksanakan kaedah _load() sekali lagi sehingga semua kebergantungan dimuatkan dan panggilan balik dilaksanakan
Modul.prototaip._load(deps, function() {
cb(modul)
})
}
//Jika tatasusunan kebergantungan kosong, laksanakan cb(modul)
terus
lain {
cb(modul)
}
}
// Jika pemerolehan gagal, seperti 404 atau tidak mematuhi spesifikasi modular
//Dalam kes ini, module.status akan kekal di FETCHING atau FETCHED
lain {
cb()
}
}
})(unLoadedUris[i])
}
// kaedah cb - panggil balik dilaksanakan selepas memuatkan semua modul
Fungsi cb(modul) {
// Jika maklumat storan modul wujud, kemudian ubah suai nilai status dalam maklumat storan modulnya kepada STATUS.READY
modul && (modul.status = STATUS.SEDIA)
// Laksanakan panggilan balik hanya apabila semua modul dimuatkan.
--kekal === 0 && panggil balik2()
}
}
}
Panjang tatasusunan unLoadedUris di sini ialah 2, ['http://localhost/test/SEAJS/a.js','http://localhost/test/SEAJS/lib/juqery/1.7.2/juqery- debug .js'], jadi dua penutupan yang dinamakan dengan laluan js akan dijana seterusnya.
Ambil http://localhost/test/SEAJS/a.js sebagai contoh
Seterusnya: Pertama, Modul akan dibuat:
cachedModules('http://localhost/test/SEAJS/a.js') = Modul baharu('http://localhost/test/SEAJS/a.js',1)
module.status >= STATUS.FETCHED ? onFetched() : fetch(uri, onFetched)
Oleh kerana modul a tidak dimuatkan pada masa ini, fetch(uri, onFetched) akan dilaksanakan seterusnya, iaitu fetch('http://localhost/test/SEAJS/a.js', onFetched).
function fetch(uri, onFetched) {
//Ganti uri dengan alamat permintaan baharu mengikut peraturan dalam peta
var requestUri = util.parseMap(uri)
// Mula-mula, semak sama ada terdapat rekod requestUri dalam senarai yang diperoleh
Jika (fetchedList[requestUri]) {
// Pada masa ini, muat semula maklumat storan modul uri asal kepada permintaanUri yang ditakrifkan semula melalui peta
cachedModules[uri] = cachedModules[requestUri]
// Laksanakan onFetched dan kembali, yang bermaksud modul telah berjaya diperoleh
onFetched()
kembali
}
//Soal maklumat storan requestUri dalam senarai pemerolehan
Jika (fetchingList[requestUri]) {
//Tambahkan panggilan balik yang sepadan dengan uri dalam senarai panggil balik dan kembalikan
CallbackList[requestUri].push(onFetched) //Jika ia sedang diambil, tolak kaedah panggil balik onFetched modul ini ke dalam tatasusunan dan kembalikan.
kembali
}
// Jika modul yang anda cuba ambil tidak muncul dalam fetchedList dan fetchingList, tambah maklumatnya dalam senarai permintaan dan senarai panggil balik masing-masing
fetchingList[requestUri] = benar
callbackList[requestUri] = [onFetched]
// Ambilnya
Modul._fetch(
requestUri,
fungsi() {
fetchedList[requestUri] = benar
// Mengemas kini status modul
// Jika module.status sama dengan STATUS.FECTCHING, ubah suai status modul kepada FETCHED
var modul = cachedModules[uri]
Jika (module.status === STATUS.FETCHING) {
module.status = STATUS.FETCHED
}
jika (fetchingList[requestUri]) {
padamkan fetchingList[requestUri]
}
// Memanggil panggilan balikList Pelaksanaan bersepadu panggilan balik
jika (callbackList[requestUri]) {
util.forEach(callbackList[requestUri], function(fn) {
Fn () // fn ialah kaedah onfeched sepadan dengan modul A.
})
padamkan Senarai panggilan balik[requestUri]
}
},
config.charset
)
}
Seterusnya, Module._fetch() akan dilaksanakan Fungsi panggil balik di sini dipanggil panggil balik3.
Kaedah ini adalah untuk memanggil kaedah loadJs untuk memuat turun fail a.js secara dinamik. (Oleh kerana terdapat a dan jquery, dua skrip baru akan dibuat). dimuat turun, tetapi akan menunggu untuk jquery Skrip tidak akan dimuat turun sehingga ia dibuat dan ditambahkan pada kepala (penyahpepijat Google menetapkan titik putus dan sentiasa memaparkan belum selesai). kenapa ni?
(Adalah disyorkan untuk membaca di sini: http://ux.sohu.com/topics/50972d9ae7de3e752e0081ff. Di sini saya akan bercakap tentang isu tambahan. Anda mungkin tahu mengapa kita harus menggunakan lebih sedikit jadual untuk susun atur, kerana jadual sedang memaparkan pokok Apabila meletakkan, berbilang pengiraan diperlukan, manakala div hanya memerlukan satu Pada masa yang sama, penemuduga e-dagang Midea memberitahu saya bahawa jadual perlu dihuraikan sepenuhnya sebelum ia akan dipaparkan, dan div. akan dipaparkan sebanyak yang dihuraikan teg akan dipaparkan dalam segmen mengikut tbody. Oleh itu, dalam IE6, 7 dan 8, jika anda menggunakan innerHTML untuk mencipta "
", <. ;tbody>< akan ditambahkan secara automatik padanya.
Selepas muat turun berjaya, ia akan dihuraikan dan dilaksanakan, dan kaedah define akan dilaksanakan. Kod modul a akan dilaksanakan terlebih dahulu.
analisis kaedah define(id,deps,function(){})
//define definition, id: module id, deps: modul dependency, factory
Module._define = function(id, deps, factory) {
//Selesaikan kebergantungan //Jika deps bukan jenis tatasusunan dan kilang ialah fungsi
if (!util.isArray(deps) && util.isFunction(factory)) { // Padankan rentetan keperluan dalam badan fungsi secara kerap dan bentuk tatasusunan untuk mengembalikan dan menetapkan nilai kepada deps
deps = util.parseDependencies(factory.toString())
}
//Tetapkan maklumat meta
var meta = { id: id, dependencies: deps, factory: factory }
if (document.attachEvent) {
// Dapatkan nod skrip semasa
skrip var = util.getCurrentScript()
// Jika nod skrip wujud
jika (skrip) {
// Dapatkan alamat uri asal
derivedUri = util.unParseMap(util.getScriptAbsoluteSrc(skrip)) }
jika (!derivedUri) {
util.log('Gagal mendapatkan URI daripada skrip interaktif untuk:', factory.toString(), 'warning')
}
}
.........
}
define akan terlebih dahulu melakukan penghakiman pada kilang untuk menentukan sama ada ia adalah fungsi (sebabnya kerana define juga boleh memasukkan fail dan objek)
Jika ia adalah fungsi, maka fungsi itu akan diperolehi melalui factory.toString(), dan kebergantungan a.js akan diperoleh melalui pemadanan biasa, dan kebergantungan akan disimpan dalam deps
Untuk a.js, kebergantungannya ialah b.js, jadi deps ialah ['./b']
Dan simpan maklumat a.js var meta = { id: id, dependencies: deps, factory: factory }
Untuk a.js meta = { id : undefined , dependencies : ['./b'] , factory : function(xxx){xxx}}
Dalam penyemak imbas IE 6-9, anda boleh mendapatkan laluan js semasa yang sedang berjalan Walau bagaimanapun, dalam penyemak imbas standard, ini tidak boleh dilaksanakan, jadi berikan sementara maklumat meta kepada anonymousModuleMeta = meta.
Kemudian onload dicetuskan, dan kaedah panggilan balik3 akan dipanggil Kaedah panggil balik ini akan mengubah suai nilai status modul panggil balik semasa (a.js) dan menetapkannya kepada modul.status = STATUS.FETCHED.
Seterusnya, panggilan balik yang sepadan dengan a.js dalam senarai panggil balik baris gilir akan dilaksanakan secara seragam, iaitu onFetched.
Kaedah onFetched akan menyemak sama ada modul a mempunyai modul bergantung Oleh kerana a bergantung pada b, _load() dilaksanakan pada b.js yang modul a bergantung.
akan memuat turun modul b, dan kemudian laksanakan kaedah definisi jquery terlebih dahulu. Kerana jquery tidak bergantung pada modul, selepas panggilan balik onload. onFetched memanggil kaedah cb.
Apabila b dilaksanakan mengikut proses yang sama seperti a, modul c akan dimuat turun. Akhirnya, modul c, b, dan a semuanya dimuat turun dan dilaksanakan mentakrifkan, dan selepas onload selesai, kaedah cb juga akan dipanggil, (c, kemudian b, kemudian c)
Selepas semua modul siap, kaedah panggil balik2 akan dipanggil.
Akhir sekali panggil balik ke panggil balik2, laksanakan kaedah _compile modul a dan jquery:
Kompilasi modul a.js dahulu, dan fungsi modul a dilaksanakan Oleh kerana a mengandungi require(b.js), fungsi modul b akan dilaksanakan.
Fungsi modul a mula melaksanakan
Fungsi modul b mula melaksanakan
Fungsi modul c mula melaksanakan
Fungsi modul c dilaksanakan
Fungsi modul b dilaksanakan
Fungsi modul a dilaksanakan
Akhir sekali laksanakan fungsi jquery.
Selepas penyusunan selesai, panggil balik1 dilaksanakan dan objek a dan jquery boleh digunakan.
PS: Versi seajs telah dikemas kini dan tiada kaedah _compile sekarang. (Semua pergi tengok sendiri, nak pergi tengok juga)
Kemudian mari kita bercakap tentang proses penyusunan_kompilasi modul seajs.
Yang pertama ialah kompilasi a.js
Module.prototype._compile = function() {
126 var modul = ini
127 // Jika modul telah disusun, kembalikan terus modul.exports
128 if (module.status === STATUS.COMPILED) {
129 pulangkan modul.eksport
130 }
133 // 1. fail modul ialah 404.
134 // 2. fail modul tidak ditulis dengan format modul yang sah.
135 // 3. kes ralat lain.
136 //Berikut adalah untuk mengendalikan beberapa situasi tidak normal, dan mengembalikan null terus
137 jika (modul.status < STATUS.SAVED && !mempunyaiPengubahsuai(modul)) {
138 kembalikan null
139 }
140 // Tukar status modul kepada COMPILING, menunjukkan bahawa modul sedang disusun
141 modul.status = STATUS.MENYUSUN
142
143 // Digunakan secara dalaman oleh modul, ia adalah kaedah yang digunakan untuk mendapatkan antara muka yang disediakan oleh modul lain (dipanggil submodul) dan melaksanakan operasi segerak
144 fungsi memerlukan(id) {
145 // Menghuraikan laluan modul mengikut id
146 var uri = menyelesaikan(id, module.uri)
147//Dapatkan modul daripada cache modul (perhatikan bahawa submodul di sini sebenarnya telah dimuat turun sebagai pergantungan modul utama)
148 var child = cachedModules[uri]
149
150//Hanya kembalikan null apabila uri tidak sah.
151//Jika kanak-kanak itu kosong, ia hanya boleh bermakna bahawa pengisian parameter salah dan uri tidak betul, maka null dikembalikan terus
152 jika (!anak) {
153 kembalikan null
154 }
155
156 // Mengelakkan panggilan pekeliling.
157//Jika status submodul ialah STATUS.COMPILING, kembalikan child.exports terus untuk mengelakkan penyusunan modul berulang kali disebabkan kebergantungan bulat
158 if (child.status === STATUS.COMPILING) {
159 kembalikan anak. eksport
160 }
161//Menunjuk ke modul yang memanggil modul semasa semasa pemulaan. Mengikut atribut ini, Tindanan Panggilan semasa pemulaan modul boleh diperolehi.
162 anak.ibu bapa = modul
163 //Kembalikan modul kanak-kanak yang disusun.eksport
164 return child._compile()
165 }
166 // Digunakan secara dalaman oleh modul untuk memuatkan modul secara tak segerak dan melaksanakan panggilan balik yang ditentukan selepas pemuatan selesai.
167 require.async = fungsi(id, panggil balik) {
168 modul._use(id, panggil balik)
169 }
170 // Gunakan mekanisme penghuraian laluan di dalam sistem modul untuk menghuraikan dan mengembalikan laluan modul. Fungsi ini tidak memuatkan modul dan hanya mengembalikan laluan mutlak yang diselesaikan.
171 require.resolve = function(id) {
172 kembalikan azam(id, module.uri)
173 }
174 // Melalui atribut ini, anda boleh melihat semua modul yang dimuatkan oleh sistem modul.
175 // Dalam sesetengah kes, jika anda perlu memuatkan semula modul, anda boleh mendapatkan uri modul, dan kemudian memadam maklumatnya dengan memadam require.cache[uri]. Dengan cara ini, anda akan mendapatnya semula pada kali berikutnya anda menggunakannya.
176 require.cache = cachedModules
177
178 // require ialah kaedah yang digunakan untuk mendapatkan antara muka yang disediakan oleh modul lain.
179 module.require = memerlukan
180 // Eksport ialah objek yang digunakan untuk menyediakan antara muka modul kepada dunia luar.
181 module.exports = {}
182 var kilang = modul.kilang
183
184 // Apabila kilang ialah fungsi, ia mewakili kaedah pembinaan modul. Dengan melaksanakan kaedah ini, anda boleh mendapatkan antara muka yang disediakan oleh modul.
185 if (util.isFunction(factory)) {
186 compileStack.push(modul)
187 runInModuleContext(kilang, modul)
188 compileStack.pop()
189 }
190 // Apabila kilang ialah jenis bukan fungsi seperti objek atau rentetan, ini bermakna antara muka modul ialah objek, rentetan atau nilai lain.
191 // Seperti: define({ "foo": "bar" });
192 // Contohnya: define('Saya adalah templat. Nama saya ialah {{nama}}.');
193 else if (kilang !== undefined) {
194 modul.eksport = kilang
195 }
196
197 // Tukar status modul kepada COMPILED, menunjukkan bahawa modul telah disusun
198 module.status = STATUS.DIKOMPILE
199 // Laksanakan pengubahsuaian antara muka modul melalui seajs.modify()
200 execModifiers(modul)
201 pulangan modul.eksport
202 }
jika (util.isFunction(kilang)) {
186 compileStack.push(modul)
187 runInModuleContext(kilang, modul)
188 compileStack.pop()
189 }
Berikut ialah untuk memulakan module.export. kaedah runInModuleContext:
// Laksanakan kod modul mengikut konteks modul
489 fungsi runInModuleContext(fn, modul) {
490 // Lulus dua parameter yang berkaitan dengan modul dan modul itu sendiri
491 // eksport digunakan untuk mendedahkan antara muka
492 // require digunakan untuk mendapatkan modul bergantung (penyegerakan) (kompilasi)
493 var ret = fn(module.require, module.exports, modul)
494 // Menyokong borang antara muka pendedahan nilai pulangan, seperti:
495 // kembalikan {
496 // fn1 : xx
497 // ,fn2: xx
498 // ...
499 // }
500 jika (ret !== undefined) {
501 module.exports = ret
502 }
503 }
Laksanakan kaedah fungsi dalam a.js, kemudian var b = require("b.js"),
akan dipanggil
Kaedah memerlukan akan mengembalikan nilai pulangan kaedah kompilasi b, dan terdapat var c = require('c.js') dalam modul b.
Pada masa ini, kaedah penyusunan c akan dipanggil, dan kemudian fungsi c akan dipanggil Dalam c, jika objek akan didedahkan, atau objek c dikembalikan, maka eksport modul c = c. Atau secara langsung module.export = c; ringkasnya, modul c.export = c akan dikembalikan pada akhirnya; jadi var c = modul c.export = c, dalam modul b, anda boleh menggunakan pembolehubah c untuk memanggil kaedah dan kaedah daripada objek c dalam sifat modul c.
Dengan analogi, akhirnya modul a juga boleh memanggil sifat dan kaedah objek b dalam modul b.
Tidak kira apa modul, selagi modul.export = xx modul digunakan, modul lain boleh menggunakan require("xx module") untuk memanggil pelbagai kaedah dalam modul xx.
Status modul akhir akan menjadi modul.status = STATUS.COMPILED.
Module.prototype._use = function(id, panggil balik) {
var uris = resolve(ids, this.uri); //Resolve['./a','jquery']
This._load(uris, function() { //Kira a yang dihuraikan, alamat modul jquery [url1, url2] dan panggil kaedah _load.
//util.map: Biarkan semua ahli data melaksanakan fungsi tertentu pada satu masa dan mengembalikan tatasusunan baharu, yang merupakan hasil daripada panggilan balik yang dilaksanakan oleh ahli tatasusunan asal
var args = util.map(uris, function(uri) {
pulangkan uri ? cachedModules[uri]._compile(): null;//Jika url wujud, panggil kaedah._com.
})
if (panggilan balik) { callback.apply(null, args) }
})
}
Pada masa ini args = [modul a.eksport, modul jquery.eksport];
seajs.use(['./a','jquery'],function(a,$){
var num = a.a;
$('#J_A').teks(bilangan);
})
Pada masa ini, fungsi a dan $ in ialah modul a.export dan modul jquery.export.
Oleh kerana saya sedang mengkaji kod sumber jquery dan reka bentuk rangka kerja jquery, saya ingin berkongsi beberapa pengalaman:
Saya membaca banyak analisis kod sumber jquery di Internet, tetapi saya tidak tahan lagi. Ia tidak masuk akal. Saya mengesyorkan analisis kod sumber jquery Bilik Darjah Miaowei.
Reka bentuk rangka kerja JavaScript Situ Zhengmei secara peribadi sukar, tetapi selepas membacanya dengan teliti, anda akan menjadi jurutera kanan hadapan.
Saya mengesyorkan anda mempelajari sea.js Yu Bo dan menggunakannya Lagipun, ia dibuat oleh orang Cina sendiri. Projek baharu atau pemfaktoran semula syarikat kami akan dilakukan menggunakan seajs.
Langkah seterusnya ialah membaca kod sumber bar tangan modular dan tulang belakang mvc atau sudut mvvm. Di sini saya harap seseorang boleh memberi saya nasihat tentang buku yang hendak dibaca, tapak web yang hendak dibaca dan video yang hendak ditonton untuk dipelajari dengan cepat.