JavaScript addEventListener&初始化函数冲突,尝试更新全局变量

时间:2018-01-27 19:19:02

标签: javascript jquery

我正在开发游戏交互菜单,它是一个HTML菜单,根据玩家目前的工作情况显示操作。

我的问题:我通过window.addEventListener检索有关玩家工作的信息。它是从我的游戏Lua文件发送到JavaScript。我可以确认这是有效的。但是,在JavaScript部分存在问题。

在item.updateJob下的addEventListener中存储/检索/更新作业,作为名为playerJob的变量。这也将使用相同的名称更新全局变量。正如您在代码中看到的那样,init()函数正在window.addEventListener之前运行。 init()必须使用更新的全局变量playerJob来显示正确的菜单,但它不会。在控制台中调试它时,它告诉我它是“未定义的”。我试图把window.addEventListener放在init()函数的上面§(函数...代码,但是没有做任何事情。

如何确保正在运行window.addEventListener并在init()函数执行任何操作之前设置playerJob变量?我尝试在顶部放置一个全局变量并执行此操作:playerJob =“police”,然后它工作正常。谁知道我怎么能这样做?

    var playerJob;

    $( function() {
        // Adds all of the correct button actions 
            console.log("Before int: ", playerJob)
            init();

        // Gets the interactionmenu div container 
        var interactionContainer = $( "#interactionmenu" );

        // Listens for NUI messages from Lua 
        window.addEventListener( 'message', function( event ) {
            var item = event.data;


            // Show the menu 
            if ( item.showmenu ) {
                ResetMenu()
                interactionContainer.show();
            }

            if ( item.hidemenu ) {
                interactionContainer.hide(); 
            }

            // This will update the players job, and does work!
            if ( item.updateJob ) {
                playerJob = item.job; 
                setJob(playerJob);
                console.log("playerJob set to: ", playerJob)
            }                   
        } );
    } )

    // Hides all div elements that contain a data-parent, in
    // other words, hide all buttons in submenus. 
    function ResetMenu() {
        $( "div" ).each( function( i, obj ) {
            var element = $( this );

            if ( element.attr( "data-parent" ) ) {
                element.hide();
            } else {
                element.show();
            }
        } );
    }

    // Configures every button click to use its data-action, or data-sub
    // to open a submenu. 
    function init() {
        // Loops through every button that has the class of "menuoption"
        $( ".menuoption" ).each( function( i, obj ) {

            // If the button has a data-action, then we set it up so when it is 
            // pressed, we send the data to the lua side. 
            if ( $( this ).attr( "data-action" ) ) {
                $( this ).click( function() { 
                    var data = $( this ).data( "action" ); 

                    sendData( "ButtonClick", data ); 
                } )
            }

            // If the button has a data-sub, then we set it up so when it is 
            // pressed, we show the submenu buttons, and hide all of the others.
            if ( $( this ).attr( "data-sub" ) ) {
                $( this ).click( function() {
                    var menu = $( this ).data( "sub" );
                    var element = $( "#" + menu ); 
                    element.show();
                    $( this ).parent().hide();  
                } )
            }

            // Here I'd like to know the playerJob, and want via item.updateJob in the addEventListener
            // However it returns undefined, no matter if I place the init() above or below
            // My question is: how can I make sure the item.updatePlayer job in the addEventListener updates
            // the variable globally and makes sure that it does that before this function is being run? 
            console.log("right before data-require: ", playerJob)   // returns undefined X amount of times.         

            if ( ( $( this ).attr ( "data-require" ) == "police" && playerJob != "police") ) {
                $( this ).hide();
            }

            else if ( ( $( this ).attr ( "data-require" ) == "mecano" && playerJob != "mecano") ) {
                $( this ).hide();
            }

            else if ( ( $( this ).attr ( "data-require" ) == "ambulance" && playerJob != "ambulance") ) {
                $( this ).hide();
            }
        } );

    }

    // Send data to lua for processing.
    function sendData( name, data ) {
        $.post( "http://wk_interactionmenu/" + name, JSON.stringify( data ), function( datab ) {
            if ( datab != "ok" ) {
                console.log( datab );
            }            
        } );
    }

1 个答案:

答案 0 :(得分:0)

如果我理解正确的问题,您只需要在{0}收到init事件后才能运行message,因此playerJob已设置。

我认为你不理解的是addEventListener电话不是在运行听众,它只是设置它。问题是message事件直到稍后才会发生。这就是您在查看undefined时获得playerJob的原因。

但是您不希望init多次运行,因此不希望它从事件处理程序运行。

您可以在同一位置设置一个标记var didInit = false;,而不是当前对init()的调用。然后,在事件处理程序中,在设置playerJob后,检查didInit的状态。如果还不是,请将其设置为true并运行init功能。

以下是您的onLoad($(function(){...)功能的替代品,该功能可以完成这项工作:

$( function() {
    // Did we initialize yet?
    var didInit = false;

    // Gets the interactionmenu div container
    var interactionContainer = $( "#interactionmenu" );

    // Listens for NUI messages from Lua 
    window.addEventListener( 'message', function( event ) {
        var item = event.data;


        // Show the menu
        if ( item.showmenu ) {
            ResetMenu()
            interactionContainer.show();
        }

        if ( item.hidemenu ) {
            interactionContainer.hide();
        }

        // This will update the players job, and does work!
        if ( item.updateJob ) {
            playerJob = item.job;
            setJob(playerJob);
            console.log("playerJob set to: ", playerJob)

            // Initialize if we didn't yet
            if (!didInit) {
                didInit = true;
                init();
            }
        }
    } );
} )

玩家的工作是否有变化?如果是这样,你可能想要运行再次隐藏按钮的初始化代码的一部分,并且你想要改变它以显示以前隐藏的任何现在相关的按钮。

如果是这样的话,可能值得将init分成两部分 - 一部分你可以在一开始就运行(正如你的原始代码所做的那样)并不依赖在playerJob上,另一个可以在playerJob更改(包括第一次设置)时运行,并更新用户界面。然后,您可以运行此(没有任何条件或didInit标志)作为事件处理程序的一部分。