使用Webpack Encore

时间:2019-06-07 18:23:51

标签: symfony webpack symfony4 webpack-encore material-components-web

基于下面的代码,我有一个变量mdcDialog,一旦页面加载,该变量就会用material-components-web(MDCDialog)库进行初始化。

在提交表单时,将阻止默认事件,而由ajaxSubmit()处理该表单。
响应是一个json对象,从中可以找到带有字符串值response.modal.modal的变量mdcDialog

但是出于某种原因,console.info(window[response.modal.modal]);返回null而不是变量mdcDialog

如果mdcDialog不起作用,如何从字符串响应中访问变量window

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));
    })
});

3 个答案:

答案 0 :(得分:2)

您仅在此函数的范围内定义mdcDialog(如果javascript以“严格模式”运行):

$(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"));

    ...
});

https://www.w3schools.com/js/js_scope.asp

答案 1 :(得分:1)

您的app.js文件被视为JavaScript模块,这意味着默认情况下,您在其中声明的变量的作用域是该模块,而不是添加到window中(这通常是一件不好的事)

如果要在模块外部(在另一个文件中或从HTML页面/ Webtools中)提供某些内容,则可以设置global.mdcDialog

话虽这么说,但我不确定您在示例中要做什么...如果您需要访问在mdc.dialog.MDCDialog回调中创建的$(document).ready的实例,为什么不您直接使用mdcDialog

如果您的用例是“我将有多个对话框,并且需要检索正确的对话框”,则将所有实例存储在一个对象中可能是一种更好的方法:

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));
    })
});

答案 2 :(得分:1)

letconst定义的变量具有块范围,即使在最外层的范围内定义,也不会在全局范围内定义它们,因此{{ 3}}

要使它们以这种方式可访问,您必须使用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

有关更多信息,请参见will never be accessible through the global (window) object.