4

我有三个 HTML DropDownList( <select><option></option></select>)。第一个DropDownList包含类别,第二个包含不同产品的子类别,第三个包含品牌(或制造商)。

选择一个类别后,应根据传递给 Ajax 函数的类别 ID 一次从数据库中填充两个下拉子类别和品牌。我正在使用以下 Ajax 代码。

function ajax()
{
    if(window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
        xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
    }
}

function getBrandList(selected)  //selected is the category id.
{               
    ajax();
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("brandList").innerHTML=xmlhttp.responseText;            
        }
    }

    xmlhttp.open("GET","ajax/BrandAjax.php?selected="+selected, true);
    xmlhttp.send();     
    alert(selected);            
}

function getSubcategoryList(selected) //selected is the category id.
{                       
    getBrandList(selected); //First above function is invoked to populate brands.
    ajax();
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("subCategoryList").innerHTML=xmlhttp.responseText;                              
        }
    }

    xmlhttp.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
    xmlhttp.send();             
}   

选择类别时,getSubcategoryList(selected)调用了执行AJAX请求的JavaScript函数。问题是我需要同时填充子类别和品牌下拉列表(选择类别时)。

它正在工作,并且根据传递的类别 ID 一次填充两个下拉列表(它是上述函数的参数selected)。

我不必要地使用了函数底部的警告框getBrandList()。注释此警告框时,仅填充一个子类别下拉菜单。品牌仍然是空的。我不再需要这个警报框了。

为什么会这样?解决办法是什么?

4

5 回答 5

2

我认为第二个 ajax() 调用正在清除 xmlhttp 变量。当您发出警报时,我敢打赌它会给第一个呼叫时间在开始第二个呼叫之前完成。您可能应该更早地调用 ajax() 并从您的处理程序中删除该调用。

于 2012-05-27T07:01:00.740 回答
2

首先,建议您为此尝试一些现代 JavaScript 框架,例如 JQuery。

@tzerb 怎么说:在第一个 AJAX 请求完成之前覆盖全局变量 xmlhttp 。为此,您必须使用局部变量。

function ajax()
{
    var xmlhttp; //!!
    if(window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
        xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
    }
    return xmlhttp; //!!
}

function getBrandList(selected)  //selected is the category id.
{               
    xmlhttp = ajax(); //!!
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("brandList").innerHTML=xmlhttp.responseText;            
        }
    }

    xmlhttp.open("GET","ajax/BrandAjax.php?selected="+selected, true);
    xmlhttp.send();     
    //alert(selected);            
}

function getSubcategoryList(selected) //selected is the category id.
{                       
    getBrandList(selected); //First above function is invoked to populate brands.
    xmlhttp = ajax(); //!!
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("subCategoryList").innerHTML=xmlhttp.responseText;                              
        }
    }

    xmlhttp.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
    xmlhttp.send();             
}

使用 JQuery,您的代码可能如下所示:

function getBrandsList(selected){
    $("#brandList").load("ajax/BrandAjax.php?selected="+selected);
}
function getSubcategoryList(selected){
    $("#brandList").load("ajax/SubCatAjax.php?selected="+selected);
}
于 2012-05-29T17:05:54.833 回答
1

我想你可以使用回调函数。但我确实建议使用 jquery。它简单了很多。您不需要手动完成所有操作。(创建 xhttprequest 对象并维护响应状态以及所有那些笨拙的 activex 对象相关的事情)

于 2012-05-29T17:34:46.783 回答
1

我建议您为此使用jQuery

 1. Load the first dropdown with categories on page load
 2. Call the following ajax call on change event of the first dropdown, categoryList
    $('#categoryList').change(function () {
      $('#subCategoryList').load("ajax/SubCatAjax.php?selected="+this.value);
      $('#brandList').load("ajax/BrandAjax.php?selected="+$('#subCategoryList').val());
    });
 3. Call the following ajax call on change event of the second dropdown, subcategoryList.
    $('#subCategoryList').change(function () {
      $('#brandList').load("ajax/BrandAjax.php?selected="+this.value);
    });

PS我假设您的ajax请求返回包含选项的字符串,例如。<option value='1'>subcategory1</option><option value='2'>subcategory2</option>..ETC。并且您想根据所选子类别而不是所选类别加载品牌。

于 2012-05-29T17:21:40.783 回答
1

seriyPS 基本上在这方面达到了目标。问题实际上是 xmlhttp 变量。您需要在每个正在使用的函数中将其声明为本地。基本上,为函数调用创建一个闭包。然而,问题不一定是它需要是“本地的”,而是由于它是一个全局变量,它在第二个请求中被重新定义。这实质上会终止初始请求,因为变量现在指向第二个请求。

警报框使其工作的原因是因为第一个请求在您可以“单击”确定之前完成了 ajax 请求。(警告框将暂停 javascript 执行,因此会延迟第二个请求,直到您单击确定之后。)

要解决此问题,您可以修改代码以对每个请求使用不同的变量。尝试将您的功能更改为以下内容:

// Global Variables
var brandListRequest;
var subcategoryRequest;

function ajax()
{
    var xmlhttp; //!!
    if(window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
        xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
    }
    return xmlhttp; //!!
}

function getBrandList(selected)  //selected is the category id.
{               
    brandListRequest = ajax(); //!!
    brandListRequest.onreadystatechange=function()
    {
        if(brandListRequest.readyState==4 && brandListRequest.status==200)
        {
            document.getElementById("brandList").innerHTML=brandListRequest.responseText;            
        }
    }

    brandListRequest.open("GET","ajax/BrandAjax.php?selected="+selected, true);
    brandListRequest.send();     
    //alert(selected);            
}

function getSubcategoryList(selected) //selected is the category id.
{                       
    getBrandList(selected); //First above function is invoked to populate brands.
    subcategoryRequest = ajax(); //!!
    subcategoryRequest.onreadystatechange=function()
    {
        if(subcategoryRequest.readyState==4 && subcategoryRequest.status==200)
        {
            document.getElementById("subCategoryList").innerHTML=subcategoryRequest.responseText;                              
        }
    }

    subcategoryRequest.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
    subcategoryRequest.send();             
}
于 2012-06-03T02:17:55.367 回答