为什么document.querySelectorAll()返回除第一个元素之外的null元素?

时间:2018-04-03 00:00:39

标签: javascript phantomjs casperjs

我需要选择两个元素(两个标签中的五个标签)来点击它们并废弃返回的表格。 每个标签都是一个' li'而它的孩子是一个跨越式的孩子。包含onclick事件。我总是得到正确数量的选项卡列表,但只有第一个元素不为空,即使在第一个元素中,我也无法调用onclick事件来向我显示其表格。还有' id'包含onclick事件的是随机的。

我使用phantomjs 2.1.1casperjs 1.1.4

JS代码:

//Wait to be redirected to the Home page, and then make a screenshot
casper.then(function(){
    casper.wait(5000, function(){
        this.capture('home.png');
        var tabs = casper.evaluate(function() {
            //return document.querySelectorAll('[id^="dbTabLabel_"]'); //Another selector option
            return document.querySelectorAll('span.dashTitle');
        }
        console.log('Num Tabs: ' + tabs.length););

        for(i = 0; i < tabs.length; i++) {
            if(tabs[i]) {
                console.log('Form exists');
                console.log('form id: ' + tabs[i].id);
                // create a mouse click event
                var event = document.createEvent( 'MouseEvents' );
                event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );        
                // send click to element
                tabs[i].dispatchEvent( event );
                var name = tabs[i].innerText + '.png'
                casper.wait(2000, function(){ // Wait to load completely
                    this.capture(name); //Make a screenshot for each tab
                });
            } else {
                console.log("Null Tab");
            }
        }
    })    
});

输出:

Num Tabs: 5
Form exists
form id: dbTabLabel_820718256523832
Null Tab
Null Tab
Null Tab
Null Tab

我想要废弃this web(当我登录并使用getHTML casper功能保存网页时的html代码)。网络截图here。这是与标签对应的片段:

<!--TEMPLATES-->
    <ul id="tabul">
        <li id="litab" class="ntabs add"><a href="" id="addtab" class="osx">+</a></li>
        <li id="litab" class="add rightAlign setting-item">
            <img src="/Content/images/icons/expand-24x24.png" class="out-triggerer gray" onclick="fullScreen()">            
        </li>        
        <li id="default-report-export" class="rightAlign">
            <a href="/report/defaultExport" download="">
                <input type="image" src="/Content/images/icons/excel.gif" value="Excel" title="Export default report">
            </a>
        </li>
        <li id="default-report-export" class="rightAlign">
            <a href="/report/defaultExport?isPdf=true" download="">
                <input type="image" src="/Content/images/export-pdf-24x24.png" value="Excel" title="Export default report">
            </a>
        </li>
        <li id="dbTab_889113733777776" class="ntabs addedTab activeTab">
            <span id="dbTabLabel_889113733777776" class="dashTitle" onclick="clickDashboard('889113733777776')">Dashboard EUR</span>
            <span id="dbTabSettings_889113733777776" class="settingsContainer dashSettings" style="">
                <div id="topnav" class="topnav">
                    <a href="javascript:void(0)" class="signin" onclick="toggleTabSettingsMenu('889113733777776',true);">
                        <span><img src="/Content/Images/icon_gear.png" alt="Edit"></span>
                    </a>
                </div>
                <fieldset id="dbTabSettingsMenu_889113733777776" class="dashSettings-menu">
                    <ul class="dashboardEditMenu">
                        <img src="/Content/images/close.png" onclick="toggleTabSettingsMenu('889113733777776',false);" alt="tooltip" style="position:absolute;right:2px;top:2px;border:0;">
                        <li class="dashboardEditMenuList">
                            <a href="javascript:void(0)" class="addWidget" onclick="toggleLeftUpdatePanelMenu(true);"> Añadir widgets</a>
                        </li>
                        <li class="dashboardEditMenuList">
                             <a href="javascript:void(0)" class="closeDash" onclick="deleteDashboard('889113733777776')"> Borrar este dashboard</a>
                        </li>
                    </ul>
                </fieldset>
            </span>
        </li>
        <li id="dbTab_894967889413237" class="ntabs addedTab">
            <span id="dbTabLabel_894967889413237" class="dashTitle" onclick="clickDashboard('894967889413237')">Dashboard USD</span>
            <span id="dbTabSettings_894967889413237" class="settingsContainer dashSettings" style="display:none;">
                <div id="topnav" class="topnav">
                    <a href="javascript:void(0)" class="signin" onclick="toggleTabSettingsMenu('894967889413237',true);">
                        <span><img src="/Content/Images/icon_gear.png" alt="Edit"></span>
                    </a>
                </div>
                <fieldset id="dbTabSettingsMenu_894967889413237" class="dashSettings-menu"> 
                    <ul class="dashboardEditMenu">
                        <img src="/Content/images/close.png" onclick="toggleTabSettingsMenu('894967889413237',false);" alt="tooltip" style="position:absolute;right:2px;top:2px;border:0;">
                        ...
                   </ul>
            </fieldset>
        </span>
    </li>
</ul>

我不知道我的问题是否是我的问题与我已阅读的post有关。但我提出的解决方案无法做到,因为我的&#39; ids&#39;是随机的,我无法做出静态&#34;选择器来获取它们。

1 个答案:

答案 0 :(得分:1)

这不是document.querySelectorAll()的问题,因为console.log('Num Tabs: ' + tabs.length);

中的标签数量正确

这是因为异步casper.wait()这里是关于asynchronous process in a loop

的答案
  

for循环立即运行完成所有你的   异步操作已启动。当他们完成一段时间   未来并调用他们的回调,循环索引的值   变量i将是所有回调的最后一个值。

解决此问题的一种方法是使用es6代替let代替var

for(let i = 0; i < tabs.length; i++) { ... ES6 var vs let

或使用.forEach因为它创建了自己的函数闭包

for vs .forEach()

将您的for(i = 0; i < tabs.length; i++) {替换为tabs.forEach(function(tab)) { ..  并使用tab代替tab

访问tabs[i]

这是一个演示它的片段:

var tabs = ['tab1', 'tab2', 'tab3', 'tab4']

for(var i = 0; i < tabs.length; i++){
    if(tabs[i]){
    	setTimeout(function(){ // simulating casper.wait
            console.log('in the for loop with var : ' , tabs[i]);
        }, 1000);
    }
    else{
    	console.log('none');
    }
}

for(let i = 0; i < tabs.length; i++){
    if(tabs[i]){
    	setTimeout(function(){ // simulating casper.wait
            console.log('in the for loop with let : ' , tabs[i]);
        }, 1000);
    }
    else{
    	console.log('none');
    }
}

tabs.forEach(function(e){
     if(e){
        setTimeout(function(){  // simulating casper.wait
            console.log('in the forEach loop : ' , e);
        }, 1000);
     }
     else{
     	console.log('none');
     }
})