Передача параметров в файлы JavaScript
Часто у меня будет файл JavaScript, который я хочу использовать, который требует, чтобы определенные переменные были определены на моей веб-странице.
Итак, код выглядит примерно так:
<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
var obj1 = "somevalue";
</script>
Но то, что я хочу сделать, это:
<script type="text/javascript"
src="file.js?obj1=somevalue&obj2=someothervalue"></script>
Я пробовал разные методы, и лучший из них - проанализировать строку запроса следующим образом:
var scriptSrc = document.getElementById("myscript").src.toLowerCase();
А потом ищи мои ценности.
Интересно, есть ли другой способ сделать это без создания функции для анализа моей строки.
Вы все знаете другие методы?
19 ответов
Я бы порекомендовал не использовать глобальные переменные, если это возможно. Используйте пространство имен и ООП для передачи ваших аргументов объекту.
Этот код принадлежит в file.js:
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function() {
alert('Hello World! -' + _args[0]);
}
};
}());
И в вашем HTML-файле:
<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["somevalue", 1, "controlId"]);
MYLIBRARY.helloWorld();
</script>
Вы можете передавать параметры с произвольными атрибутами. Это работает во всех последних браузерах.
<script type="text/javascript" data-my_var_1="some_val_1" data-my_var_2="some_val_2" src="/js/somefile.js"></script>
Внутри somefile.js вы можете получить значения переданных переменных следующим образом:
........
var this_js_script = $('script[src*=somefile]'); // or better regexp to get the file name..
var my_var_1 = this_js_script.attr('data-my_var_1');
if (typeof my_var_1 === "undefined" ) {
var my_var_1 = 'some_default_value';
}
alert(my_var_1); // to view the variable value
var my_var_2 = this_js_script.attr('data-my_var_2');
if (typeof my_var_2 === "undefined" ) {
var my_var_2 = 'some_default_value';
}
alert(my_var_2); // to view the variable value
...так далее...
Еще одна идея, с которой я столкнулся, заключалась в назначении элемента "id" и передаче аргументов в качестве атрибутов data-*. Получившийся тег будет выглядеть примерно так:
<script id="helper" data-name="helper" src="helper.js"></script>
Затем скрипт может использовать идентификатор, чтобы программно найти себя и проанализировать аргументы. Учитывая предыдущий тег, имя может быть получено так:
var name = document.getElementById("helper").getAttribute("data-name");
мы получаем имя = помощник
Проверьте этот URL. Это работает отлично для требования.
http://feather.elektrum.org/book/src.html
Большое спасибо автору. Для быстрого ознакомления я вставил основную логику ниже:
var scripts = document.getElementsByTagName('script');
var myScript = scripts[ scripts.length - 1 ];
var queryString = myScript.src.replace(/^[^\?]+\??/,'');
var params = parseQuery( queryString );
function parseQuery ( query ) {
var Params = new Object ();
if ( ! query ) return Params; // return empty object
var Pairs = query.split(/[;&]/);
for ( var i = 0; i < Pairs.length; i++ ) {
var KeyVal = Pairs[i].split('=');
if ( ! KeyVal || KeyVal.length != 2 ) continue;
var key = unescape( KeyVal[0] );
var val = unescape( KeyVal[1] );
val = val.replace(/\+/g, ' ');
Params[key] = val;
}
return Params;
}
Вы используете Глобальные переменные:-D.
Как это:
<script type="text/javascript">
var obj1 = "somevalue";
var obj2 = "someothervalue";
</script>
<script type="text/javascript" src="file.js"></script">
Код JavaScript в файле file.js может получить доступ к obj1
а также obj2
без проблем.
РЕДАКТИРОВАТЬ Просто хочу добавить, что если 'file.js' хочет проверить, если obj1
а также obj2
даже было объявлено, что вы можете использовать следующую функцию.
function IsDefined($Name) {
return (window[$Name] != undefined);
}
Надеюсь это поможет.
Вот очень поспешное доказательство концепции.
Я уверен, что есть как минимум 2 места, где могут быть улучшения, и я также уверен, что это не продержится долго в дикой природе. Любые отзывы, чтобы сделать его более презентабельным или пригодным для использования, приветствуются.
Ключ устанавливает идентификатор для вашего элемента скрипта. Единственный улов в том, что это означает, что вы можете вызвать скрипт только один раз, так как он ищет этот идентификатор для извлечения строки запроса. Это можно исправить, если вместо этого сценарий перебирает все элементы запроса, чтобы увидеть, указывает ли на них какой-либо из них, и, если это так, использует последний экземпляр такого элемента сценария. Во всяком случае, с кодом:
Сценарий называется:
window.onload = function() {
//Notice that both possible parameters are pre-defined.
//Which is probably not required if using proper object notation
//in query string, or if variable-variables are possible in js.
var header;
var text;
//script gets the src attribute based on ID of page's script element:
var requestURL = document.getElementById("myScript").getAttribute("src");
//next use substring() to get querystring part of src
var queryString = requestURL.substring(requestURL.indexOf("?") + 1, requestURL.length);
//Next split the querystring into array
var params = queryString.split("&");
//Next loop through params
for(var i = 0; i < params.length; i++){
var name = params[i].substring(0,params[i].indexOf("="));
var value = params[i].substring(params[i].indexOf("=") + 1, params[i].length);
//Test if value is a number. If not, wrap value with quotes:
if(isNaN(parseInt(value))) {
params[i] = params[i].replace(value, "'" + value + "'");
}
// Finally, use eval to set values of pre-defined variables:
eval(params[i]);
}
//Output to test that it worked:
document.getElementById("docTitle").innerHTML = header;
document.getElementById("docText").innerHTML = text;
};
Скрипт вызывается через следующую страницу:
<script id="myScript" type="text/javascript"
src="test.js?header=Test Page&text=This Works"></script>
<h1 id="docTitle"></h1>
<p id="docText"></p>
Может быть очень простым
например
<script src="js/myscript.js?id=123"></script>
<script>
var queryString = $("script[src*='js/myscript.js']").attr('src').split('?')[1];
</script>
Затем вы можете конвертировать строку запроса в JSON, как показано ниже
var json = $.parseJSON('{"'
+ queryString.replace(/&/g, '","').replace(/=/g, '":"')
+ '"}');
а затем можно использовать как
console.log(json.id);
Это легко сделать, если вы используете Javascript-фреймворк, например, jQuery. Вот так,
var x = $('script:first').attr('src'); //Fetch the source in the first script tag
var params = x.split('?')[1]; //Get the params
Теперь вы можете использовать эти параметры, разделив их в качестве параметров вашей переменной.
Тот же процесс может быть выполнен без какой-либо структуры, но займет еще несколько строк кода.
Ну, вы могли бы создать файл javascript любым из языков сценариев, вставляя ваши переменные в файл при каждом запросе. Вы должны сказать своему веб-серверу, чтобы он не выдавал js-файлы статически (достаточно использовать mod_rewrite).
Имейте в виду, что вы потеряете любое кэширование этих js-файлов, так как они постоянно изменяются.
До свидания.
Это не верный HTML (я не думаю), но, похоже, он будет работать, если вы создадите пользовательский атрибут для тега script на своей веб-странице:
<script id="myScript" myCustomAttribute="some value" ....>
Затем получите доступ к пользовательскому атрибуту в JavaScript:
var myVar = document.getElementById( "myScript" ).getAttribute( "myCustomAttribute" );
Не уверен, что это лучше или хуже, чем анализ исходной строки скрипта.
Хотя этот вопрос задавался некоторое время назад, он актуален и сегодня. Это нетривиальный подход с использованием параметров файла сценария, но у меня уже были некоторые экстремальные варианты использования, которые больше всего подходят.
Я наткнулся на этот пост, чтобы найти лучшее решение, чем писал некоторое время назад, в надежде найти, возможно, нативную функцию или что-то подобное.
Я поделюсь своим решением, пока не будет реализовано лучшее. Это работает в большинстве современных браузеров, возможно, даже в старых, не пробовал.
Все вышеперечисленные решения основаны на том факте, что он должен быть введен с заранее определенным и хорошо помеченным тегом SCRIPT и полностью полагаться на реализацию HTML. Но что, если сценарий вводится динамически, или, что еще хуже, что, если вы пишете библиотеку, которая будет использоваться на различных веб-сайтах?
В этих и некоторых других случаях все вышеперечисленные ответы недостаточны и даже становятся слишком сложными.
Для начала попробуем понять, чего нам здесь нужно добиться. Все, что нам нужно сделать, это получить URL-адрес самого скрипта, оттуда это проще простого.
На самом деле есть хороший трюк, чтобы получить URL-адрес скрипта из самого скрипта. Одна из функций родногоError
class - это возможность предоставить стековую трассировку "проблемного места", включая точную трассировку файла до последнего вызова. Чтобы добиться этого, я буду использовать свойство stack экземпляра Error, которое после создания даст полную трассировку стека.
Вот как работает магия:
// The pattern to split each row in the stack trace string
const STACK_TRACE_SPLIT_PATTERN = /(?:Error)?\n(?:\s*at\s+)?/;
// For browsers, like Chrome, IE, Edge and more.
const STACK_TRACE_ROW_PATTERN1 = /^.+?\s\((.+?):\d+:\d+\)$/;
// For browsers, like Firefox, Safari, some variants of Chrome and maybe other browsers.
const STACK_TRACE_ROW_PATTERN2 = /^(?:.*?@)?(.*?):\d+(?::\d+)?$/;
const getFileParams = () => {
const stack = new Error().stack;
const row = stack.split(STACK_TRACE_SPLIT_PATTERN, 2)[1];
const [, url] = row.match(STACK_TRACE_ROW_PATTERN1) || row.match(STACK_TRACE_ROW_PATTERN2) || [];
if (!url) {
console.warn("Something went wrong. You should debug it and find out why.");
return;
}
try {
const urlObj = new URL(url);
return urlObj.searchParams; // This feature doesn't exists in IE, in this case you should use urlObj.search and handle the query parsing by yourself.
} catch (e) {
console.warn(`The URL '${url}' is not valid.`);
}
}
Теперь в любом случае вызова скрипта, как и в случае с OP:
<script type="text/javascript" src="file.js?obj1=somevalue&obj2=someothervalue"></script>
в file.js
скрипт, теперь вы можете:
const params = getFileParams();
console.log(params.get('obj2'));
// Prints: someothervalue
Это также будет работать с RequireJS и другими динамически внедряемыми файловыми скриптами.
Хороший вопрос и креативные ответы, но я предлагаю сделать ваши методы параметризованными, и это должно решить все ваши проблемы без каких-либо уловок.
если у вас есть функция:
function A()
{
var val = external_value_from_query_string_or_global_param;
}
Вы можете изменить это на:
function B(function_param)
{
var val = function_param;
}
Я думаю, что это наиболее естественный подход, вам не нужно складывать дополнительную документацию о "параметрах файла", и вы получаете то же самое. Это особенно полезно, если вы разрешаете другим разработчикам использовать ваш файл js.
Здесь я нашел другой способ сделать то же самое. В восстановленном js-файле [ cttricks.js, поскольку я использовал его для тестирования, вы можете иметь свой любой .js-файл ], мы просто перечислим все элементы скрипта и получим требуемый, так как он всегда будет наконец показатель. А затем получите оттуда ".attributes.src.value".
Теперь в любом случае вызова скрипта это
<script src="./cttricks.js?data1=Hello&data2=World"></script>
И в файле сценария cttricks.js
var scripts = document.getElementsByTagName('script');
var jsFile = new URL("http://" + scripts[scripts.length-1].attributes.src.value);
/*get value from query parameters*/
console.log(jsFile.searchParams.get("data1"));
console.log(jsFile.searchParams.get("data2"));
Наслаждаться!!
Используйте document.currentScript.src с резервной копией window.location.
var url = new URL((document.currentScript.src)?document.currentScript.src:window.location.toLocaleString());
var obj1 = url.searchParams.get("obj1");// returns somevalue
Если вам нужен способ, который проходит проверку CSP (которая запрещает небезопасную встроенную версию), вам нужно использовать метод nonce, чтобы добавить уникальное значение как в сценарий, так и в директиву CSP или записать свои значения в html и прочитать их снова.
Метод nonce для express.js:
const uuidv4 = require('uuid/v4')
app.use(function (req, res, next) {
res.locals.nonce = uuidv4()
next()
})
app.use(csp({
directives: {
scriptSrc: [
"'self'",
(req, res) => `'nonce-${res.locals.nonce}'` // 'nonce-614d9122-d5b0-4760-aecf-3a5d17cf0ac9'
]
}
}))
app.use(function (req, res) {
res.end(`<script nonce="${res.locals.nonce}">alert(1 + 1);</script>`)
})
или напишите значения в метод html. в этом случае с использованием JQuery:
<div id="account" data-email="{{user.email}}"></div>
...
$(document).ready(() => {
globalThis.EMAIL = $('#account').data('email');
}
Я думаю, что гораздо лучше и современнее просто использовать localStorage на странице, где включен javascript, а затем просто повторно использовать его внутри самого javascript. Установите его в localStorage с помощью:
localStorage.setItem("nameOfVariable", "some text value");
и обратитесь к нему внутри файла javascript, например:
localStorage.getItem("nameOfVariable");
Можно передавать параметры в js-модули и читать их после через
import.meta.url
.
Например, со следующим HTML
<script type="module">
import './index.mjs?someURLInfo=5';
</script>
следующий файл JavaScript будет регистрировать параметр someURLInfo:
// index.mjs
new URL(import.meta.url).searchParams.get('someURLInfo'); // 5
То же самое происходит, когда файл импортирует другой:
// index.mjs
import './index2.mjs?someURLInfo=5';
// index2.mjs
new URL(import.meta.url).searchParams.get('someURLInfo'); // 5
Нет, вы не можете сделать это, добавив переменные в часть строки запроса URL-адреса файла JS. Если он пишет часть кода для анализа строки, которая вас беспокоит, возможно, другим способом было бы json кодировать ваши переменные и помещать их в нечто вроде атрибута rel тега? Я не знаю, насколько это правильно с точки зрения валидации HTML, если это то, что вас очень беспокоит. Затем вам просто нужно найти атрибут rel в скрипте и затем json_decode.
например
<script type='text/javascript' src='file.js' rel='{"myvar":"somevalue","anothervar":"anothervalue"}'></script>