无法使用 Webpack Encore 访问 window["var_name"]
Can't access window["var_name"] with Webpack Encore
根据下面的代码,我有一个变量 mdcDialog
,它在页面加载后用 material-components-web
(MDCDialog) 库初始化。
在表单提交时,默认事件被阻止,取而代之的是,ajaxSubmit()
处理表单。
响应是一个 json 对象,我可以从中找到变量 response.modal.modal
及其字符串值 mdcDialog
.
但出于某种原因,console.info(window[response.modal.modal]);
return 未定义而不是变量 mdcDialog
。
另一方面,执行 console.log(mdcDialog)
输出变量。
如果 window
不起作用,我如何从字符串响应访问我的变量 mdcDialog
?
app.js
/* --- VARS --- */
const page="#page";
let mdcDialog;
/* --- FUNCTIONS --- */
function ajaxSubmit(node) {
$.ajax({
type: node.attr("method"),
url: node.attr("action"),
enctype: "multipart/form-data",
data: new FormData(node[0]),
processData: false,
contentType: false,
cache: false
}).done(function(response, status, xhr) {
if(response !== false) {
/** @var response.modal */
if(typeof response.modal !== "undefined") {
/** @var response.modal.action */
/** @var response.modal.modal */
/** @var response.modal.content */
if(response.modal.action === "load") {
console.info(window[response.modal.modal]);
}
}
}
}).fail(function(request, status, error) {
console.error(request);
console.error(status);
console.error(error);
});
}
/* --- ACTIONS --- */
$(document).ready(function() {
mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
$(page).on("submit", ".ajs", function(e) {
e.preventDefault();
ajaxSubmit($(this));
})
});
你只是在这个函数的范围内定义了mdcDialog
(如果javascript在"Strict Mode"中是运行):
$(document).ready(function() {
mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
要赋予它全局范围并使其可通过 window['mdcDialog']
访问,请执行以下操作:
$(document).ready(function() {
window.mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
或者在函数前定义在全局范围内:
var mdcDialog;
$(document).ready(function() {
mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
您的 app.js 文件被视为一个 JavaScript 模块,这意味着您在其中声明的变量在默认情况下作用于该模块,而不是添加到 window
(这通常是一件坏事。
如果你想在你的模块之外提供一些东西(在另一个文件中或从你的 HTML 页面/webtools),你可以设置 global.mdcDialog
.
话虽如此,我不确定您在示例中要做什么...如果您需要访问在 $(document).ready
回调中创建的 mdc.dialog.MDCDialog
的实例,为什么会你不是直接用mdcDialog
吗?
如果您的用例是 "I will have multiple dialogs and will need to retrieve the right one" 也许将所有实例存储在一个对象中是更好的方法:
const dialogs = {};
function ajaxSubmit(node) {
$.ajax({
// ...
}).done(function(response, status, xhr) {
// ...
console.info(dialogs[response.modal.modal]);
});
}
$(document).ready(function() {
dialogs['mdcDialog'] = new mdc.dialog.MDCDialog(/* ... */);
$(page).on("submit", ".ajs", function(e) {
e.preventDefault();
ajaxSubmit($(this));
})
});
用let
或const
定义的变量具有块作用域,即使定义在最外层作用域,也不会全局定义 因此 will never be accessible through the global (window
) object.
为了让它们以这种方式访问,您必须使用var
,或者在全局对象本身上定义它们。
let foo=1
window.foo //undefined
foo //1
var bar=2
window.bar //2
bar //2
window.baz=3
window.baz //3
baz //3
有关详细信息,请参阅 this SO answer
根据下面的代码,我有一个变量 mdcDialog
,它在页面加载后用 material-components-web
(MDCDialog) 库初始化。
在表单提交时,默认事件被阻止,取而代之的是,ajaxSubmit()
处理表单。
响应是一个 json 对象,我可以从中找到变量 response.modal.modal
及其字符串值 mdcDialog
.
但出于某种原因,console.info(window[response.modal.modal]);
return 未定义而不是变量 mdcDialog
。
另一方面,执行 console.log(mdcDialog)
输出变量。
如果 window
不起作用,我如何从字符串响应访问我的变量 mdcDialog
?
app.js
/* --- VARS --- */
const page="#page";
let mdcDialog;
/* --- FUNCTIONS --- */
function ajaxSubmit(node) {
$.ajax({
type: node.attr("method"),
url: node.attr("action"),
enctype: "multipart/form-data",
data: new FormData(node[0]),
processData: false,
contentType: false,
cache: false
}).done(function(response, status, xhr) {
if(response !== false) {
/** @var response.modal */
if(typeof response.modal !== "undefined") {
/** @var response.modal.action */
/** @var response.modal.modal */
/** @var response.modal.content */
if(response.modal.action === "load") {
console.info(window[response.modal.modal]);
}
}
}
}).fail(function(request, status, error) {
console.error(request);
console.error(status);
console.error(error);
});
}
/* --- ACTIONS --- */
$(document).ready(function() {
mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
$(page).on("submit", ".ajs", function(e) {
e.preventDefault();
ajaxSubmit($(this));
})
});
你只是在这个函数的范围内定义了mdcDialog
(如果javascript在"Strict Mode"中是运行):
$(document).ready(function() {
mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
要赋予它全局范围并使其可通过 window['mdcDialog']
访问,请执行以下操作:
$(document).ready(function() {
window.mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
或者在函数前定义在全局范围内:
var mdcDialog;
$(document).ready(function() {
mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));
...
});
您的 app.js 文件被视为一个 JavaScript 模块,这意味着您在其中声明的变量在默认情况下作用于该模块,而不是添加到 window
(这通常是一件坏事。
如果你想在你的模块之外提供一些东西(在另一个文件中或从你的 HTML 页面/webtools),你可以设置 global.mdcDialog
.
话虽如此,我不确定您在示例中要做什么...如果您需要访问在 $(document).ready
回调中创建的 mdc.dialog.MDCDialog
的实例,为什么会你不是直接用mdcDialog
吗?
如果您的用例是 "I will have multiple dialogs and will need to retrieve the right one" 也许将所有实例存储在一个对象中是更好的方法:
const dialogs = {};
function ajaxSubmit(node) {
$.ajax({
// ...
}).done(function(response, status, xhr) {
// ...
console.info(dialogs[response.modal.modal]);
});
}
$(document).ready(function() {
dialogs['mdcDialog'] = new mdc.dialog.MDCDialog(/* ... */);
$(page).on("submit", ".ajs", function(e) {
e.preventDefault();
ajaxSubmit($(this));
})
});
用let
或const
定义的变量具有块作用域,即使定义在最外层作用域,也不会全局定义 因此 will never be accessible through the global (window
) object.
为了让它们以这种方式访问,您必须使用var
,或者在全局对象本身上定义它们。
let foo=1
window.foo //undefined
foo //1
var bar=2
window.bar //2
bar //2
window.baz=3
window.baz //3
baz //3
有关详细信息,请参阅 this SO answer