JavaScript'te @import
CSS'ye benzer başka bir JavaScript dosyasının içine bir JavaScript dosyası eklemenizi sağlayan bir şey var mı ?
script
etiketleri kullanarak bildirmiyorsunuz ?
JavaScript'te @import
CSS'ye benzer başka bir JavaScript dosyasının içine bir JavaScript dosyası eklemenizi sağlayan bir şey var mı ?
script
etiketleri kullanarak bildirmiyorsunuz ?
Yanıtlar:
JavaScript'in eski sürümlerinde herhangi bir içe aktarma, içerme veya gereksinim yoktu, bu soruna birçok farklı yaklaşım geliştirildi.
Ancak 2015'ten beri (ES6), JavaScript, çoğu modern tarayıcı tarafından da desteklenen Node.js'de modülleri içe aktarmak için ES6 modülleri standardına sahiptir .
Eski tarayıcılarla uyumluluk için Webpack gibi araçlar oluşturun ve Toplama ve / veya Babel gibi çeviri araçları oluşturun kullanılabilir.
ECMAScript (ES6) modülleri, v8.5'ten beri, bayrakla birlikte ve en azından Node.js v13.8.0'da bayraksız olarak desteklenmektedir--experimental-modules
. "ESM" (node.js önceki CommonJS tarzı modülü sistemine karşı [ "CJS"]) sizi ya kullanımı etkinleştirmek için "type": "module"
depackage.json
ya dosyaları uzantısı verin .mjs
. (Benzer şekilde, Node.js'nin önceki CJS modülü ile yazılmış modüller adlandırılabilir.cjs
varsayılan değer ESM ise .)
kullanma package.json
:
{
"type": "module"
}
Sonra module.js
:
export function hello() {
return "Hello";
}
Sonra main.js
:
import { hello } from './module.js';
let val = hello(); // val is "Hello";
Kullanarak .mjs
,module.mjs
:
export function hello() {
return "Hello";
}
Sonra main.mjs
:
import { hello } from './module.mjs';
let val = hello(); // val is "Hello";
Tarayıcılar, Safari 10.1, Chrome 61, Firefox 60 ve Edge 16'dan beri ECMAScript modüllerini doğrudan yükleme (Webpack gibi bir araç gerekmez) desteğine sahipti . Caniuse'daki mevcut desteği kontrol edin . Node.js'nin .mjs
uzantısını kullanmaya gerek yoktur ; tarayıcılar modüller / komut dosyalarındaki dosya uzantılarını tamamen yok sayar.
<script type="module">
import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
Https://jakearchibald.com/2017/es-modules-in-browsers/ adresinde daha fazla bilgi bulabilirsiniz.
Dinamik içe aktarmalar komut dosyasının diğer komut dosyalarını gerektiği gibi yüklemesine izin verir:
<script type="module">
import('hello.mjs').then(module => {
module.hello('world');
});
</script>
Https://developers.google.com/web/updates/2017/11/dynamic-import adresinden daha fazla bilgi edinin.
Hala Node.js'de yaygın olarak kullanılan eski CJS modülü stili module.exports
/require
sistemidir.
// mymodule.js
module.exports = {
hello: function() {
return "Hello";
}
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
JavaScript'in harici önizleme gerektirmeyen tarayıcılara harici JavaScript içeriği eklemesinin başka yolları da vardır.
AJAX çağrısı ile ek bir komut dosyası yükleyebilir ve daha sonra eval
çalıştırmak için kullanabilirsiniz . Bu en basit yoldur, ancak JavaScript korumalı alan güvenlik modeli nedeniyle alan adınızla sınırlıdır. Kullanmak eval
da hatalara, korsanlara ve güvenlik sorunlarına kapı açar.
Dinamik İçe Aktarmalar gibi fetch
, Getirme Enjeksiyonu kitaplığını kullanarak komut dosyası bağımlılıkları için yürütme sırasını kontrol etme vaatlerini kullanarak bir veya daha fazla komut dosyası yükleyebilirsiniz :
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
JQuery kütüphanesi yükleme işlevi sağlar tek satırda :
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
HTML'ye komut dosyası URL'sini içeren bir komut dosyası etiketi ekleyebilirsiniz. JQuery yükünü önlemek için, bu ideal bir çözümdür.
Komut dosyası farklı bir sunucuda bile bulunabilir. Ayrıca, tarayıcı kodu değerlendirir. <script>
Etiketi ya web sayfası içine enjekte edilebilir <head>
, ya da sadece kapanış önüne eklenir </body>
etiketi.
Bunun nasıl çalışabileceğine ilişkin bir örnek:
function dynamicallyLoadScript(url) {
var script = document.createElement("script"); // create a script DOM node
script.src = url; // set its src to the provided URL
document.head.appendChild(script); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}
Bu işlev <script>
, sayfanın başlık bölümünün sonuna yeni bir etiket ekler ; burada src
özellik, ilk parametre olarak işleve verilen URL'ye ayarlanır.
Bu çözümlerin her ikisi de JavaScript Çılgınlığı: Dinamik Betik Yükleme bölümünde tartışılmış ve gösterilmiştir .
Şimdi bilmeniz gereken büyük bir sorun var. Bunu yapmak , kodu uzaktan yüklediğiniz anlamına gelir . Modern web tarayıcıları dosyayı yükler ve mevcut komut dosyanızı yürütmeye devam eder, çünkü performansı artırmak için her şeyi eşzamansız olarak yüklerler. (Bu hem jQuery yöntemi hem de el ile dinamik komut dosyası yükleme yöntemi için geçerlidir.)
Bu, bu hileleri doğrudan kullanırsanız, yüklenmesini istedikten sonra yeni yüklediğiniz kodu bir sonraki satırda kullanamayacağınız anlamına gelir , çünkü yine de yüklenecektir .
Örneğin: şunları my_lovely_script.js
içerir MySuperObject
:
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
var s = new MySuperObject();
Error : MySuperObject is undefined
Sonra sayfa isabet yeniden yükleyin F5. Ve çalışıyor! Kafa karıştırıcı...
Peki bu konuda ne yapmalı?
Yazarın size verdiğim linkte önerdiği hack'i kullanabilirsiniz. Özetle, acele eden insanlar için, komut dosyası yüklendiğinde bir geri arama işlevi çalıştırmak için bir olay kullanır. Böylece tüm kodu geri çağrı işlevindeki uzak kitaplığı kullanarak koyabilirsiniz. Örneğin:
function loadScript(url, callback)
{
// Adding the script tag to the head as suggested before
var head = document.head;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
Sonra komut dosyası lambda işlevinde yüklendikten SONRA kullanmak istediğiniz kodu yazarsınız :
var myPrettyCode = function() {
// Here, do whatever you want
};
Sonra tüm bunları çalıştırın:
loadScript("my_lovely_script.js", myPrettyCode);
Komut dosyasının, DOM yüklendikten sonra veya tarayıcıya ve satırı ekleyip eklemediğinize bağlı olarak daha önce çalıştırılabileceğini unutmayın script.async = false;
. Bir var genel JavaScript yükleme büyük makale bu anlatılır.
Bu cevabın en üstünde belirtildiği gibi, birçok geliştirici projelerinde Parcel, Webpack veya Babel gibi derleme / transpilasyon araçlarını kullanıyor, böylece yaklaşan JavaScript sözdizimini kullanmalarına izin veriyor, eski tarayıcılar için geriye dönük uyumluluk sağlıyor, dosyaları birleştiriyor, küçültüyor, kod bölme vb.
onreadystatechange
etkinlik ve readyState
özellik) için bazı değişiklikler gerektiriyor . Ayrıca, dinamik komut dosyası yüklemesi, broswer'in önyükleme tarayıcılarından yararlanamaz. Bu HTML5Rocks makalesini önerin: html5rocks.com/en/tutorials/speed/script-loading
Birisi daha gelişmiş bir şey arıyorsanız, RequireJS'yi deneyin . Bağımlılık yönetimi, daha iyi eşzamanlılık gibi ek avantajlar elde edersiniz ve çoğaltmayı önlersiniz (yani, bir komut dosyasını bir kereden fazla almak).
JavaScript dosyalarınızı "modüllere" yazabilir ve daha sonra diğer komut dosyalarında bağımlılık olarak başvurabilirsiniz. Veya RequireJS'yi basit bir "bu betiği al" çözümü olarak kullanabilirsiniz.
Misal:
Bağımlılıkları modül olarak tanımlayın:
Bazı-dependency.js
define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {
//Your actual script goes here.
//The dependent scripts will be fetched if necessary.
return libraryObject; //For example, jQuery object
});
implementation.js bağlıdır "ana" JavaScript dosyası olan bazı-dependency.js
require(['some-dependency'], function(dependency) {
//Your script goes here
//some-dependency.js is fetched.
//Then your script is executed
});
GitHub README'den alıntı :
RequireJS, düz JavaScript dosyalarını ve daha tanımlanmış modülleri yükler. Bir Web Çalışanı dahil olmak üzere tarayıcı içi kullanım için optimize edilmiştir, ancak Rhino ve Node gibi diğer JavaScript ortamlarında kullanılabilir. Asenkron Modül API'sini uygular.
RequireJS, modülleri / dosyaları yüklemek için düz komut dosyası etiketleri kullanır, bu nedenle kolay hata ayıklamaya izin vermelidir. Mevcut JavaScript dosyalarını yüklemek için kullanılabilir. yeniden yazmak zorunda kalmadan mevcut projenize ekleyebilirsiniz.
...
Orada aslında olan bir JavaScript dosyası yüklemek için bir yol değil bunu yüklenmesinden sonra yeni yüklenen dosya sağ dahil fonksiyonlarını kullanabilir, böylece uyumsuz ve bunu tüm tarayıcılarda çalışır düşünüyorum.
Sen kullanmak gerekir jQuery.append()
üzerinde <head>
sayfanızın elemanı, yani:
$("head").append('<script type="text/javascript" src="' + script + '"></script>');
Ancak, bu yöntemin de bir sorunu vardır: içe aktarılan JavaScript dosyasında bir hata oluşursa, Firebug (ve ayrıca Firefox Hata Konsolu ve Chrome Geliştirici Araçları da) yerini yanlış bildirir; bu, izlemek için Firebug'u kullanırsanız büyük bir sorundur. JavaScript hataları çok azaldı (yapıyorum). Firebug herhangi bir nedenle yeni yüklenen dosyayı bilmiyor, bu nedenle bu dosyada bir hata oluşursa, bunun ana HTML'nizde oluştuğunu bildiriyor dosyanızda ve hatanın gerçek nedenini bulmakta sorun yaşarsınız.
Ancak bu sizin için bir sorun değilse, bu yöntem işe yaramalıdır.
Aslında bu yöntemi kullanan $ .import_js () adlı bir jQuery eklentisi yazdım :
(function($)
{
/*
* $.import_js() helper (for JavaScript importing within JavaScript code).
*/
var import_js_imported = [];
$.extend(true,
{
import_js : function(script)
{
var found = false;
for (var i = 0; i < import_js_imported.length; i++)
if (import_js_imported[i] == script) {
found = true;
break;
}
if (found == false) {
$("head").append('<script type="text/javascript" src="' + script + '"></script>');
import_js_imported.push(script);
}
}
});
})(jQuery);
Yani JavaScript'i içe aktarmak için yapmanız gereken tek şey:
$.import_js('/path_to_project/scripts/somefunctions.js');
Ben ayrıca bunun için basit bir test yapılmış Örnek .
main.js
Ana HTML'de bir dosya ve daha sonra şu işlevi tanımlayan ek bir dosyayı içe aktarmak için main.js
kullanılan komut $.import_js()
dosyası included.js
içerir:
function hello()
{
alert("Hello world!");
}
Ve dahil ettikten hemen sonra included.js
, hello()
fonksiyon çağrılır ve uyarıyı alırsınız.
(Bu cevap e-satis'in yorumuna yanıt olarak).
jQuery.getScript
, bu şekilde eklentiyi yazma konusunda endişelenmenize gerek yok ...
script
öğenin eklenmesi head
, eşzamansız olarak çalışmasına neden olacakasync
false
.
"
, kod kırılırsa
Başka bir deyişle, bence çok daha temiz, bir <script>
etiket kullanmak yerine senkron bir Ajax isteği yapmaktır . Bu, Node.js'nin işleyişini de içerir.
İşte jQuery kullanan bir örnek:
function require(script) {
$.ajax({
url: script,
dataType: "script",
async: false, // <-- This is the key
success: function () {
// all good...
},
error: function () {
throw new Error("Could not load script " + script);
}
});
}
Daha sonra, genellikle bir içerme yöntemini kullandığınız gibi kodunuzda kullanabilirsiniz:
require("/scripts/subscript.js");
Ve sonraki satırda gerekli komut dosyasından bir işlevi çağırabilirsiniz:
subscript.doSomethingCool();
async: false
Teklifiniz, kaldırıldığı iddia edilen önceki yorumunuzu desteklemiyor gibi görünüyor . O değil! Alıntı belirttiği gibi, sadece jqXHR ilgili şeyler olduğunu.
Sizin için iyi bir haber var. Çok yakında JavaScript kodunu kolayca yükleyebileceksiniz. JavaScript kod modüllerini içe aktarmanın standart bir yolu haline gelecek ve temel JavaScript'in kendisinin bir parçası olacaktır.
Bir dosyadan import cond from 'cond.js';
adlandırılmış bir makro yüklemek için yazmanız yeterlidir .cond
cond.js
Dolayısıyla, herhangi bir JavaScript çerçevesine güvenmeniz veya Ajax çağrılarını açıkça yapmanız gerekmez .
Bakınız:
Bir JavaScript etiketini dinamik olarak oluşturmak ve diğer JavaScript kodunun içinden HTML belgesine eklemek mümkündür. Bu, hedeflenen JavaScript dosyasını yükleyecektir.
function includeJs(jsFilePath) {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
}
includeJs("/path/to/some/file.js");
js.onload = callback;
Açıklama import
ECMAScript 6'dadır.
Sözdizimi
import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;
Belki bu sayfada bulduğum bu işlevi kullanabilirsiniz. JavaScript dosyasına bir JavaScript dosyasını nasıl ekleyebilirim ? :
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
script.onload = callback;
var
değişken küresel olacak mı?
İşte jQuery olmadan senkron bir sürüm :
function myRequire( url ) {
var ajax = new XMLHttpRequest();
ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
ajax.onreadystatechange = function () {
var script = ajax.response || ajax.responseText;
if (ajax.readyState === 4) {
switch( ajax.status) {
case 200:
eval.apply( window, [script] );
console.log("script loaded: ", url);
break;
default:
console.log("ERROR: script not loaded: ", url);
}
}
};
ajax.send(null);
}
Bu çalışma arası etki alanını elde etmek için sunucunun allow-origin
yanıtında üstbilgi ayarlaması gerekeceğini unutmayın .
http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js
)
<script>
etiketle yükleyebilirsiniz , üzerinden değil XMLHttpRequest
.
const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Sadece (kullanarak bu JavaScript kodu yazdım Prototype için DOM manipülasyon):
var require = (function() {
var _required = {};
return (function(url, callback) {
if (typeof url == 'object') {
// We've (hopefully) got an array: time to chain!
if (url.length > 1) {
// Load the nth file as soon as everything up to the
// n-1th one is done.
require(url.slice(0, url.length - 1), function() {
require(url[url.length - 1], callback);
});
} else if (url.length == 1) {
require(url[0], callback);
}
return;
}
if (typeof _required[url] == 'undefined') {
// Haven't loaded this URL yet; gogogo!
_required[url] = [];
var script = new Element('script', {
src: url,
type: 'text/javascript'
});
script.observe('load', function() {
console.log("script " + url + " loaded.");
_required[url].each(function(cb) {
cb.call(); // TODO: does this execute in the right context?
});
_required[url] = true;
});
$$('head')[0].insert(script);
} else if (typeof _required[url] == 'boolean') {
// We already loaded the thing, so go ahead.
if (callback) {
callback.call();
}
return;
}
if (callback) {
_required[url].push(callback);
}
});
})();
Kullanımı:
<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
require(['foo.js','bar.js'], function () {
/* Use foo.js and bar.js here */
});
</script>
Gist: http://gist.github.com/284442 .
İşte Facebook'un her yerde Beğen düğmesi için nasıl yaptığının genelleştirilmiş bir versiyonu:
<script>
var firstScript = document.getElementsByTagName('script')[0],
js = document.createElement('script');
js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
js.onload = function () {
// do stuff with your dynamically loaded script
snowStorm.snowColor = '#99ccff';
};
firstScript.parentNode.insertBefore(js, firstScript);
</script>
Facebook için çalışıyorsa, sizin için çalışacaktır.
Bunun script
yerine head
veya yerine ilk öğeyi aramamızın nedeni body
, bazı tarayıcıların eksikse bir script
öğe oluşturmamasıdır, ancak bir öğeye sahip olacağımız garantidir - bu. Daha fazla bilgiyi http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ adresinde bulabilirsiniz .
Saf JavaScript istiyorsanız, kullanabilirsiniz document.write
.
document.write('<script src="myscript.js" type="text/javascript"></script>');
JQuery kitaplığını kullanıyorsanız, $.getScript
yöntemi kullanabilirsiniz .
$.getScript("another_script.js");
Komut dosyalarınızı PHP kullanarak da birleştirebilirsiniz :
Dosya main.js.php
:
<?php
header('Content-type:text/javascript; charset=utf-8');
include_once("foo.js.php");
include_once("bar.js.php");
?>
// Main JavaScript code goes here
Burada gösterilen çözümlerin çoğu dinamik yükleme anlamına gelir. Bunun yerine tüm bağlı dosyaları tek bir çıktı dosyasına birleştiren bir derleyici arıyordum. Less / Sass ön işlemcilerinin aynısı CSS @import
kuralında da geçerlidir. Bu türden iyi bir şey bulamadığım için, sorunu çözen basit bir araç yazdım.
İşte , istenen dosya içeriğinin güvenli bir şekilde değiştirildiği https://github.com/dsheiko/jsic derleyicisi $import("file-path")
. İlgili Grunt eklentisi: https://github.com/dsheiko/grunt-jsic .
JQuery master dalında, atomik kaynak dosyaları ile başlayan intro.js
ve biten tek bir dosyada birleştirilirler outtro.js
. Kaynak kod tasarımında esneklik sağlamadığından bu bana uymuyor. Jsic ile nasıl çalıştığını kontrol edin:
src / main.js
var foo = $import("./Form/Input/Tel");
src / Form / giriş / Tel.js
function() {
return {
prop: "",
method: function(){}
}
}
Şimdi derleyiciyi çalıştırabiliriz:
node jsic.js src/main.js build/mail.js
Ve birleştirilmiş dosyayı alın
build / main.js
var foo = function() {
return {
prop: "",
method: function(){}
}
};
JavaScript dosyasını yükleme amacınız içe aktarılan / dahil edilen dosyadaki işlevleri kullanıyorsa, genel bir nesne de tanımlayabilir ve işlevleri nesne öğeleri olarak ayarlayabilirsiniz. Örneğin:
A = {};
A.func1 = function() {
console.log("func1");
}
A.func2 = function() {
console.log("func2");
}
A.func1();
A.func2();
Bir HTML dosyasına komut dosyaları eklerken dikkatli olmanız gerekir. Sipariş aşağıdaki gibi olmalıdır:
<head>
<script type="text/javascript" src="global.js"></script>
<script type="text/javascript" src="file1.js"></script>
<script type="text/javascript" src="file2.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
Bu şunları yapmalıdır:
xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
eval
yanlış olan bu. Gönderen Crockford , " eval
kötülük. Olduğunu eval
. Bunu önlemek. Fonksiyonu JavaScript en yanlış kullanılan özelliğidir eval
adlar vardır. Kullanmayınız Function
. Yapıcısı Dizeleri geçmek etmeyin setTimeout
ya setInterval
." "JavaScript: İyi Parçalar" ı okumadıysanız hemen dışarı çıkın ve bunu yapın. Sen olacak pişman değil.
http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js
)
Veya çalışma zamanında dahil etmek yerine, yüklemeden önce birleştirme yapmak için bir komut dosyası kullanın.
Kullandığım dişlisi (başkaları da varsa bilmiyorum). JavaScript kodunuzu ayrı dosyalarda oluşturursunuz ve Sprockets altyapısı tarafından işlenen yorumları dahil edersiniz. Geliştirme için dosyaları sırayla ekleyebilir, daha sonra üretim için bunları birleştirebilirsiniz ...
Ayrıca bakınız:
Basit bir sorunum vardı, ancak bu soruya verilen yanıtlarla şaşırdım.
Başka bir JavaScript dosyasında (main.js) bir JavaScript dosyasında (myvariables.js) tanımlanan bir değişkeni (myVar1) kullanmak zorunda kaldım.
Bunun için aşağıdaki gibi yaptım:
JavaScript kodunu HTML dosyasına önce doğru sırayla, önce myvariables.js, sonra main.js olarak yükledi:
<html>
<body onload="bodyReady();" >
<script src="myvariables.js" > </script>
<script src="main.js" > </script>
<!-- Some other code -->
</body>
</html>
Dosya: myvariables.js
var myVar1 = "I am variable from myvariables.js";
Dosya: main.js
// ...
function bodyReady() {
// ...
alert (myVar1); // This shows "I am variable from myvariables.js", which I needed
// ...
}
// ...
Gördüğünüz gibi, bir JavaScript dosyasındaki başka bir JavaScript dosyasındaki bir değişkeni kullandım, ancak diğerini eklemem gerekmiyordu. İlk JavaScript dosyasının ikinci JavaScript dosyasından önce yüklendiğinden ve ilk JavaScript dosyasının değişkenlerine ikinci JavaScript dosyasında otomatik olarak erişilebilir olduğundan emin olmam gerekiyordu.
Bu benim günümü kurtardı. Umarım bu yardımcı olur.
import
. Bir js dosyasından diğerine bir şeyler almak için bir HTML dosyasına ihtiyacınız vardır.
<script>
etikete sahip olmak yararlı olacaktır . Bu organizasyonda yardımcı olabilir. Bu cevap basitçe sorunun istediği şey değildir ve bu bağlamda ideal değildir.
Web Workers kullanıyorsanız ve çalışanın kapsamına ek komut dosyaları eklemek istiyorsanız, head
etikete komut dosyası vb. Eklemekle ilgili verilen diğer yanıtlar sizin için çalışmaz.
Neyse ki, Web Çalışanlarının kendiimportScripts
, belirtimin bir parçası olduğu için tarayıcının kendisine özgü olan Web İşçisi kapsamında küresel bir işlev olan işlevlerine sahiptir .
Alternatif olarak, en yüksek ikinci soru vurgular cevabını oylarıyla , RequireJS da bir Web Worker (muhtemelen çağırarak içindeki komut dahil işleyebilir importScripts
ancak birkaç diğer yararlı özelliklere sahip, kendisini).
Komut dosyasının önceden yüklenmiş olup olmadığını kontrol eden modern dilde:
function loadJs(url){
return new Promise( (resolve, reject) => {
if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
const script = document.createElement("script")
script.src = url
script.onload = resolve
script.onerror = reject
document.head.appendChild(script)
});
}
Kullanım (zaman uyumsuz / beklemede):
try { await loadJs("https://.../script.js") }
catch(error) {console.log(error)}
veya
await loadJs("https://.../script.js").catch(err => {})
Kullanımı (Söz):
loadJs("https://.../script.js").then(res => {}).catch(err => {})
var pi = 3.14
. loadJS () fonksiyonunu loadJs("pi.js").then(function(){ console.log(pi); });
@import
JavaScript ithal böyle kendi özel aracılığıyla Karışımı gibi bir araç kullanarak mümkün gibi CSS-ulaşmak için sözdizimi .mix
dosya türü (bkz burada ). Ben bilmiyorum olsa da, uygulama sadece yukarıda belirtilen yöntemlerden birini interally kullandığını hayal ediyorum.
.mix
Dosyalar üzerindeki Mixture belgelerinden :
Mix dosyaları .mix ile .js veya .css dosyalarıdır. dosya adında. Bir mix dosyası normal bir stil veya kod dosyasının işlevselliğini genişletir ve içe aktarmanıza ve birleştirmenize izin verir.
.mix
Birden fazla .js
dosyayı tek bir dosyada birleştiren örnek bir dosya :
// scripts-global.mix.js
// Plugins - Global
@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";
Karışım bunu scripts-global.js
minimize edilmiş bir sürüm ( scripts-global.min.js
) olarak ve çıktı olarak verir .
Not: Ön uç geliştirme aracı olarak kullanmak dışında, hiçbir şekilde Mixture ile ilişkili değilim. Bir .mix
JavaScript dosyasını çalışırken (Mixture kazanlarından birinde) gördükten ve biraz karıştığımda ("bunu yapabilir misin?" Diye düşündüm) kendi kendime düşündüm. Sonra bir uygulamaya özgü dosya türü (biraz hayal kırıklığı, kabul) olduğunu fark ettim. Yine de, bilginin başkaları için yararlı olabileceğini düşündüm.
GÜNCELLEME : Mixture artık ücretsiz (çevrimdışı).
GÜNCELLEME : Karışım artık üretilmiyor. Eski karışım sürümleri hala mevcuttur
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
body
olacaktır . Ayrıca, cevapları açıklamaya yardımcı olur.
Benim her zamanki yöntemim:
var require = function (src, cb) {
cb = cb || function () {};
var newScriptTag = document.createElement('script'),
firstScriptTag = document.getElementsByTagName('script')[0];
newScriptTag.src = src;
newScriptTag.async = true;
newScriptTag.onload = newScriptTag.onreadystatechange = function () {
(!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
};
firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}
Harika çalışıyor ve benim için sayfa yeniden yükleme kullanmıyor. AJAX yöntemini denedim (diğer cevaplardan biri) ama benim için iyi çalışmıyor gibi görünüyor.
İşte merak edilenler için kodun nasıl çalıştığına dair bir açıklama: Aslında, URL'nin yeni bir komut dosyası etiketini (ilkinden sonra) oluşturur. Kodun geri kalanını engellememesi için eşzamansız moda ayarlar, ancak readyState (yüklenecek içeriğin durumu) 'yüklenmiş' olarak değiştiğinde bir geri çağırma çağrısı yapar.
Her ne kadar bu cevaplar harika olsa da, betik yüklemesi var olduğundan beri var olan basit bir "çözüm" vardır ve çoğu insanın kullanım durumlarının% 99.999'unu kapsayacaktır. İhtiyacınız olan komut dosyasını gerektiren komut dosyasının önüne eklemeniz yeterlidir. Çoğu proje için hangi komut dosyalarının ve hangi sırayla gerekli olduğunu belirlemek uzun sürmez.
<!DOCTYPE HTML>
<html>
<head>
<script src="script1.js"></script>
<script src="script2.js"></script>
</head>
<body></body>
</html>
Script2 script1 gerektiriyorsa, bu gerçekten böyle bir şey yapmanın en kolay yoludur. Kimsenin bunu getirmediğine çok şaşırdım, çünkü neredeyse her vakada uygulanacak en açık ve en basit cevap.
JavaScript'e modül komut dosyaları alma / dahil etme işini otomatikleştiren basit bir modül yazdım. Kodun ayrıntılı açıklaması için JavaScript talep / içe aktarma / dahil etme modüllerine ilişkin blog yayınına bakın .
// ----- USAGE -----
require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');
ready(function(){
//Do something when required scripts are loaded
});
//--------------------
var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
scripts: {},
length: 0
};
_rmod.findScriptPath = function(script_name) {
var script_elems = document.getElementsByTagName('script');
for (var i = 0; i < script_elems.length; i++) {
if (script_elems[i].src.endsWith(script_name)) {
var href = window.location.href;
href = href.substring(0, href.lastIndexOf('/'));
var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
return url.substring(href.length+1, url.length);
}
}
return '';
};
_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
//the root directory of your library, any library.
_rmod.injectScript = function(script_name, uri, callback, prepare) {
if(!prepare)
prepare(script_name, uri);
var script_elem = document.createElement('script');
script_elem.type = 'text/javascript';
script_elem.title = script_name;
script_elem.src = uri;
script_elem.async = true;
script_elem.defer = false;
if(!callback)
script_elem.onload = function() {
callback(script_name, uri);
};
document.getElementsByTagName('head')[0].appendChild(script_elem);
};
_rmod.requirePrepare = function(script_name, uri) {
_rmod.loading.scripts[script_name] = uri;
_rmod.loading.length++;
};
_rmod.requireCallback = function(script_name, uri) {
_rmod.loading.length--;
delete _rmod.loading.scripts[script_name];
_rmod.imported[script_name] = uri;
if(_rmod.loading.length == 0)
_rmod.onReady();
};
_rmod.onReady = function() {
if (!_rmod.LOADED) {
for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
_rmod.on_ready_fn_stack[i]();
});
_rmod.LOADED = true;
}
};
_.rmod = namespaceToUri = function(script_name, url) {
var np = script_name.split('.');
if (np.getLast() === '*') {
np.pop();
np.push('_all');
}
if(!url)
url = '';
script_name = np.join('.');
return url + np.join('/')+'.js';
};
//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
var uri = '';
if (script_name.indexOf('/') > -1) {
uri = script_name;
var lastSlash = uri.lastIndexOf('/');
script_name = uri.substring(lastSlash+1, uri.length);
}
else {
uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
}
if (!_rmod.loading.scripts.hasOwnProperty(script_name)
&& !_rmod.imported.hasOwnProperty(script_name)) {
_rmod.injectScript(script_name, uri,
_rmod.requireCallback,
_rmod.requirePrepare);
}
};
var ready = function(fn) {
_rmod.on_ready_fn_stack.push(fn);
};
Bu komut dosyası, başka herhangi bir <script>
etiketin üstüne bir JavaScript dosyası ekleyecektir :
(function () {
var li = document.createElement('script');
li.type = 'text/javascript';
li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
li.async=true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(li, s);
})();
Ayrıca Head.js de var . Başa çıkmak çok kolaydır:
head.load("js/jquery.min.js",
"js/jquery.someplugin.js",
"js/jquery.someplugin.css", function() {
alert("Everything is ok!");
});
Gördüğünüz gibi, Require.js'den daha kolay ve jQuery'nin $.getScript
yöntemi kadar kullanışlı . Ayrıca koşullu yükleme, özellik algılama ve çok daha fazlası gibi bazı gelişmiş özelliklere de sahiptir .
Bu soru için birçok potansiyel cevap var. Cevabım belli ki bunlara dayanıyor. Tüm cevapları okuduktan sonra bunu yaptım.
$.getScript
Yükleme tamamlandığında geri arama gerektiren bir sorun ve gerçekten de başka bir çözüm, onu kullanan ve birbirine bağlı birden fazla dosyanız varsa, artık tüm komut dosyalarının ne zaman yüklendiğini (iç içe yerleştirildikten sonra) bilmenin bir yolunun olmamasıdır. birden çok dosyada).
file3.js
var f3obj = "file3";
// Define other stuff
file2.js:
var f2obj = "file2";
$.getScript("file3.js", function(){
alert(f3obj);
// Use anything defined in file3.
});
file1.js:
$.getScript("file2.js", function(){
alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
alert(f2obj);
// Use anything defined in the loaded script...
});
Ajax'ı senkronize olarak çalıştırabileceğinizi veya XMLHttpRequest'i kullanabileceğinizi söylediğinizde haklısınız , ancak mevcut eğilim senkronize istekleri onaylamıyor gibi görünüyor, bu nedenle şimdi veya gelecekte tam tarayıcı desteği alamayabilirsiniz.
$.when
Bir dizi ertelenmiş nesneyi kontrol etmek için kullanmayı deneyebilirsiniz , ancak şimdi bunu her dosyada yapıyorsunuz $.when
ve geri arama yürütüldüğünde değil yürütüldüğünde dosya2 yüklenmiş olarak kabul edilecektir, bu nedenle dosya1 yüklenmeden önce dosya1 yine de yürütülmeye devam eder . Bu hala aynı problemi yaşıyor.
İleri gitmek yerine geri gitmeye karar verdim. Teşekkürler document.writeln
. Tabu olduğunu biliyorum, ama doğru kullanıldığı sürece bu iyi çalışıyor. Kolayca hata ayıklanabilen, DOM'da doğru bir şekilde gösterilen ve bağımlılıkların doğru bir şekilde yüklenmesini sağlayan kodla sonuçlanırsınız.
Elbette $ ("body"). Append () kullanabilirsiniz, ancak artık artık doğru şekilde hata ayıklayamazsınız.
NOT: Bunu yalnızca sayfa yüklenirken kullanmalısınız, aksi takdirde boş bir ekran elde edersiniz. Başka bir deyişle, bunu her zaman belgenin önüne / dışına yerleştirin . Sayfa bir tıklama olayı veya benzeri bir şey yüklendikten sonra bunu kullanarak test etmedim, ancak başarısız olacağından eminim.
JQuery'yi genişletme fikrini beğendim, ancak açıkçası ihtiyacınız yok.
Aramadan önce document.writeln
, tüm komut dosyası öğelerini değerlendirerek komut dosyasının önceden yüklenmediğinden emin olur.
Bir komut dosyası, document.ready
olayı yürütülene kadar tam olarak yürütülmediğini varsayıyorum . (Kullanmanın document.ready
gerekli olmadığını biliyorum , ancak birçok kişi bunu kullanıyor ve bunu korumak bir güvenlik önlemi.)
Ek dosyalar yüklendiğinde document.ready
geri aramalar yanlış sırada yürütülür. Bir komut dosyası gerçekten yüklendiğinde bu sorunu gidermek için, içe aktarılan komut dosyası yeniden içe aktarılır ve yürütme durdurulur. Bu, kaynak dosyanın artık document.ready
içeri aktardığı herhangi bir komut dosyasından sonra geri çağrılmasını sağlar.
Bu yaklaşım yerine jQuery'yi değiştirmeyi deneyebilirsiniz readyList
, ancak bu daha kötü bir çözüm gibi görünüyordu.
Çözüm:
$.extend(true,
{
import_js : function(scriptpath, reAddLast)
{
if (typeof reAddLast === "undefined" || reAddLast === null)
{
reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
}
var found = false;
if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
{
found = $('script').filter(function () {
return ($(this).attr('src') == scriptpath);
}).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
}
if (found == false) {
var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.
document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln
if (reAddLast)
{
$.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
}
return true;
}
return false;
}
});
Kullanımı:
dosya3:
var f3obj = "file3";
// Define other stuff
$(function(){
f3obj = "file3docready";
});
file2:
$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
f2obj = "file2docready";
});
file1:
$.import_js('js/file2.js');
// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"
$(function(){
// Use objects from file2 or file3 some more.
alert(f3obj); //"file3docready"
alert(f2obj); //"file2docready"
});
Javascript'te modülleri uygulamanın birkaç yolu vardır, İşte en popüler 2 tanesi:
Tarayıcılar bu modülasyon sistemini henüz desteklemediğinden, bu sözdizimini kullanabilmeniz için webpack gibi bir paketleyici kullanmanız gerekir. Zaten bir paketleyici kullanmak daha iyidir çünkü bu, tüm farklı dosyalarınızı tek bir (veya çift ilişkili) dosyada birleştirebilir. Bu, sunucudan istemciye dosyaları daha hızlı sunacaktır çünkü her HTTP isteğinin yanında bazı ilişkili ek yükler vardır. Böylece genel HTTP isteğini azaltarak performansı geliştiriyoruz. İşte ES6 modüllerine bir örnek:
// main.js file
export function add (a, b) {
return a + b;
}
export default function multiply (a, b) {
return a * b;
}
// test.js file
import {add}, multiply from './main'; // for named exports between curly braces {export1, export2}
// for default exports without {}
console.log(multiply(2, 2)); // logs 4
console.log(add(1, 2)); // logs 3
Bu modülasyon sistemi NodeJS'de kullanılır. Dışa aktarmalarınızı temel olarak adlandırılan bir nesneye eklersiniz module.exports
. Daha sonra bu nesneye a require('modulePath')
. Burada önemli olan, bu modüllerin önbelleğe alındığını fark etmektir, bu nedenle require()
belirli bir modülün iki katı ise, önceden oluşturulmuş modülü döndürür.
// main.js file
function add (a, b) {
return a + b;
}
module.exports = add; // here we add our add function to the exports object
// test.js file
const add = require('./main');
console.log(add(1,2)); // logs 3
Bu soruya geldim çünkü yararlı JavaScript eklentileri koleksiyonunu korumanın basit bir yolunu arıyordum. Buradaki bazı çözümleri gördükten sonra şunu buldum:
"Plugins.js" (veya extensions.js veya istediğinizi) adlı bir dosya oluşturun. Eklenti dosyalarınızı bu tek bir ana dosya ile birlikte saklayın.
plugins.js, pluginNames[]
tekrarlayacağımız ve each()
sonra <script>
her eklenti için başlığa bir etiket ekleyeceğimiz adlı bir diziye sahip olacak
//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];
//one script tag for each plugin
$.each(pluginNames, function(){
$('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
<script src="js/plugins/plugins.js"></script>
FAKAT:
Tüm eklentiler, gerektiği gibi kafa etiketine bırakılsa da, sayfayı tıkladığınızda veya yenilediğinizde tarayıcı tarafından her zaman çalıştırılmazlar.
Ben sadece bir PHP dahil komut dosyası etiketleri yazmak daha güvenilir bulduk. Sadece bir kez yazmanız gerekir ve bu eklentiyi JavaScript kullanarak çağırmak kadar işe yarar.