首页 > 解决方案 > 即使放在正文部分的末尾,Javascript 也不起作用

问题描述

我已将以下脚本放置在我的 html 文件正文部分的最后,其中 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>

NEW SCRIPT 旨在取代 OLD SCRIPT(如下......完美运行),因为总共将有 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;
        });
}

我无法理解的是,如果问题真的与页面加载有关,为什么它会影响 NEW 脚本而不是 OLD 脚本。

任何帮助将不胜感激。提前致谢。

标签: javascripthtmldompromiseonload

解决方案


您的代码混淆了函数的调用引用事件处理程序的函数。例如,在这一行:

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,但这里最重要的关键是将函数的调用包装在一个新函数中,因此不会立即进行实际调用。现在,直到change触发 DOM 事件,才会调用箭头函数,并且在函数中,您将调用myChoices(...). 请注意,原始工作代码引用了一个侦听器函数以将调用推迟到事件发生。


推荐阅读