即使将Javascript放置在Body部分的最后,也无法使用。

问题描述 投票:0回答:2

我把下面的脚本放在我的html文件的body部分的最后,其中select_1,select_2,select_3是动态(依赖)下拉列表。我们把下面的脚本称为NEW SCRIPT)。

function json(response) {
    return response.json()
}

function url_parser(XArray, some_str){
    var url_str = [];
    for (var i=0; i < XArray.length; ++i)
        url_str.push('/'+XArray[i].value);
    url_str.push(some_str);
    url_str = url_str.join('');
    return url_str
}

function selectionHTML(nextFormElement, data){
    let optionHTML = '';
        for (let tmp of data.select_array) {
            optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
        }
        nextFormElement.innerHTML = optionHTML;
}


function myChoices(XArray, some_str, nextFormElement){
    my_url = url_parser(XArray, some_str);
    fetch(my_url).then(json).then(selectionHTML.bind(null, nextFormElement));
}


let select_1 = document.getElementById('tipo_via');
let select_2 = document.getElementById('numero_via');
let select_3 = document.getElementById('apendice_via');

select_1.onchange = myChoices([tipo_via], '/numero_via', select_2);
select_2.onchange = myChoices([tipo_via, numero_via], '/apendice_v', select_3);

然而,这个脚本不能工作。唯一的办法是

  1. 把它从html文件中删除,然后
  2. 按一定顺序在控制台上执行

按执行顺序提供细节。

  1. (在控制台)执行介于 function json(response)let select_3 = document.getElementById('apendice_via');
  2. 改变select_1的值(在页面中)。
  3. 执行(在控制台) select_1.onchange = myChoices([tipo_via], '/numero_via', select_2); select_2现在正确更新了)。
  4. 改变select_2的值(在页面中)。
  5. 执行(在控制台) select_2.onchange = myChoices([tipo_via, numero_via], '/apendice_v', select_3); select_3现在正确更新了)。

在看了类似的问题后,我认为问题是(也许仍然是)与页面加载的时间有关,这就是为什么我将脚本放在了 <body>. 我也试过把它放在 <head>

新脚本的目的是取代老脚本(如下......老脚本工作得很好),因为总共会有8个下拉列表。

function json(response) {
    return response.json()
}

function url_parser(XArray, some_str,){
    var url_str = [];
    for (var i=0; i < XArray.length; ++i)
        url_str.push('/'+XArray[i].value);
    url_str.push(some_str);
    url_str = url_str.join('');
    return url_str
}


let select_1 = document.getElementById('tipo_via');
let select_2 = document.getElementById('numero_via');
let select_3 = document.getElementById('apendice_via');


select_1.onchange = function(){
    my_url = url_parser([tipo_via], '/numero_via');
    fetch(my_url).then(json).then(function(data) {
            let optionHTML = '';
            for (let tmp of data.select_array) {
                optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
            }
            select_2.innerHTML = optionHTML;
        });
}

select_2.onchange = function(){
    my_url = url_parser([tipo_via, numero_via], '/apendice_v');
    fetch(my_url).then(json).then(function(data) {
            let optionHTML = '';
            for (let tmp of data.select_array) {
                optionHTML += '<option value="' + tmp.gid + '">' + tmp.gid + '</option>';
            }
            select_3.innerHTML = optionHTML;
        });
}

我不明白的是,如果问题真的与页面加载有关,为什么会影响到新的脚本而不是老的脚本。

任何帮助都将是非常感激的。谢谢你的帮助。

javascript html dom promise onload
2个回答
2
投票

你的代码混淆了 呼叫 的函数和 参考 事件处理程序的函数。例如,在这一行

select_1.onchange = myChoices([tipo_via], '/numero_via', select_2);

...这意味着 召唤 myChoices 和一些参数,并将返回值分配给 onchange. 相反,你想要的是当 onchange 事件发生时,你要调用 myChoices 与这些论点。这是你更想要的。

select_1.addEventListener(
  'change', 
  () => myChoices([tipo_via], '/numero_via', select_2));
select_2.addEventListener(
  'change',
  () => myChoices([tipo_via, numero_via], '/apendice_v', select_3));

我把赋值改为 onchange 到喜欢的 addEventListener但这里最重要的关键是将你的函数调用包装在一个新的函数中,这样实际的调用就不会马上进行。现在,直到DOM change 事件被触发,箭头函数将被调用,并在 函数,你将有对 myChoices(...). 请注意,原来的工作代码 引用了一个监听器函数来推迟调用,直到事件发生。


0
投票

DOM可能还没有准备好(HTML完全解析,DOM树在内部构建),所以你必须以 DOMContentLoaded 事件.

如果这还不能解决问题,那就发一个详细的错误描述,比如浏览器控制台的错误。

© www.soinside.com 2019 - 2024. All rights reserved.