【问题标题】:Cannot get AJAX output with onClick function无法使用 onClick 函数获取 AJAX 输出
【发布时间】:2019-02-17 09:18:06
【问题描述】:

我对 AJAX 非常陌生,并且刚刚开始讨论这个话题。我有这个 XML 文件,我应该使用 AJAX 调用来显示所需的信息。我将所有标记元素解析为相应的 javascript 代码,但是当我按下按钮时,即使我只想显示 XML 文件的标题,我也无法显示我想要的内容。下面的屏幕截图显示了预期的输出。

function makeAjaxQueryWeather(){
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
    myFunction(this);
    }
  };
  xhttp.open("GET", "A8.xml", true);
  xhttp.send();
}

// handler for the readyState change
function readyStateChangeHandler(xhttp){

  if (xhttp.readyState == 4){
    // readyState = 4 means DONE

    if(xhttp.status == 200){
      // status = 200 means OK

      handleStatusSuccess(xhttp);

    }else{
      // status is NOT OK

      handleStatusFailure(xhttp);

    }
  }

}

// XMLHttpRequest failed
function handleStatusFailure(xhttp){

  // display error message

  var displayDiv = document.getElementById("display");

  displayDiv.innerHTML = "XMLHttpRequest failed: status " + xhttp.status;
}

// XMLHttpRequest success
function handleStatusSuccess(xhttp){

  var xml = xhttp.responseXML;

  // parse the XML into an object
  var weatherObj = parseXMLWeather(xml);

  // display the object on the page
  displayWeather(weatherObj);
}

// parse the XML into an object
function parseXMLWeather(xml){

  // print XML on the console
  // console.log(xml);

  //create an object to hold the information in the xml file
  var weatherObj = {};
  
  // get the forecast XML element
  var forecastElement = xml.getElementsByTagName("forecast")[0];
  // get the query location
  weatherObj.queryLocation = forecastElement.getAttribute("queryLocation");
  // get the query time
  weatherObj.queryTime = forecastElement.getAttribute("queryTime");
  
  //get the weather XML element
  var weatherElementList = xml.getElementsByTagName("weather")[0];
  weatherObj.YYYYMMDD = weatherElementList.getAttribute("yyyymmdd");
  
  //get the rest of the child XML element in weather
  weatherObj.list = [];
  for(var i=0; i < weatherElementList.length; i++) {
  
    var weatherElement = weatherElementList[i];
	
	var weather1Obj = parseWeatherElement(weatherElement);
	
	weatherObj.list.push(weather1Obj);
  
  }
  return weatherObj;
  
}

// parse a stock XML element into a JavaScript stock object
function parseWeatherElement(weatherElement) {
    var weather1Obj = {};
	
	//get all elements
	var yearElement = weatherElement.getElementsByTagName("year")[0];
	weather1Obj.year = yearElement.textContent;
	var monthElement = weatherElement.getElementsByTagName("month")[0];
	weather1Obj.month = monthElement.textContent;
	var dateElement = weatherElement.getElementsByTagName("date")[0];
	weather1Obj.date = dateElement.textContent;
	var dayOfWeekElement = weatherElement.getElementsByTagName("dayOfWeek")[0];
	weather1Obj.dayOfWeek = dayOfWeekElement.textContent;
	var overallElement = weatherElement.getElementsByTagName("overall")[0];
	weather1Obj.overall = overallElement.textContent;
	var highestElement = weatherElement.getElementsByTagName("highest")[0];
	weather1Obj.highest = highestElement.textContent;
	var lowestElement = weatherElement.getElementsByTagName("lowest")[0];
	weather1Obj.lowest = lowestElement.textContent;
	
	return weather1Obj;

}

// display the weather object on the page
function displayWeather(weatherObj){
  // print the weatherObj on the console
  // console.log(weatherObj);

  // construct HTML code to display weather information
  var html = "<h1>" + weatherObj.queryLocation + weatherObj.queryTime "</h1>";
  html = html + weatherObj.yyyymmdd;

  // show the constructed HTML code in the display div
  var displayDiv = document.getElementById("display");
  displayDiv.innerHTML = html;
}
<h1>Part 2</h1>
<button onClick="makeAjaxQueryWeather()">
Click here to view weather forecast 1
</button>
<br/> <br/>
<div id="display">
</div>

这是 XML 文件:

【问题讨论】:

  • var html = "&lt;h1&gt;" + weatherObj.queryLocation + weatherObj.queryTime "&lt;/h1&gt;"; 中你忘记了+。替换为:var html = "&lt;h1&gt;" + weatherObj.queryLocation + weatherObj.queryTime + "&lt;/h1&gt;";.
  • @DannyFardyJhonstonBermúdez 不,它仍然对我不起作用..
  • 好的。我已经发布了答案。

标签: javascript html css ajax


【解决方案1】:

将您的显示功能更改为以下代码并检查。

function displayWeather(weatherObj){
  // print the weatherObj on the console
  // console.log(weatherObj);

  // construct HTML code to display weather information
  var html = `<h1>${weatherObj.queryLocation + weatherObj.queryTime}</h1><span>${weatherObj.yyyymmdd}</span>`;
  // show the constructed HTML code in the display div
  var displayDiv = document.getElementById("display");
  displayDiv.insertAdjacentHTML('afterbegin',html);
}

【讨论】:

    【解决方案2】:

    您需要使用DOMParser() 将 XML 字符串解析为正确的 XML DOM 文档:

    类似这样的:

    // Convert XML string to proper XML DOM document.
    function parseXML(xmlString) {
      return new window.DOMParser().parseFromString(xmlString, "text/xml");
    }
    

    然后您可以从返回 XML 字符串的 XMLHttpRequest 函数中正确解析 XML 字符串内容。

    上面的函数必须在这个函数中实现:

    // XMLHttpRequest success
    function handleStatusSuccess(xhttp) {
      var xml = xhttp.response; // Change to xhttp.response.
      xml = parseXML(xml); // Call the parseXML function here, where xml parameter is a string.
    
      // parse the XML into an object
      var weatherObj = parseXMLWeather(xml);
      // display the object on the page
      displayWeather(weatherObj);
    }
    

    最后的变化是这样的:

    var html = "<h1>" + weatherObj.queryLocation + " " + weatherObj.queryTime + "</h1>";
    html += weatherObj.YYYYMMDD; // Use weatherObj.YYYYMMDD.
    

    然后,你得到了这样的东西:

    function makeAjaxQueryWeather() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          readyStateChangeHandler(this);
        }
      };
      xhttp.open("GET", "https://gist.githubusercontent.com/dannyjhonston/e56a6461d88ebd43d039bac215fa4eb4/raw/af9b5883d35097e8a8a68b619c3b0a9f7a51dc7d/A8.xml", true);
      xhttp.send();
    }
    
    // handler for the readyState change
    function readyStateChangeHandler(xhttp) {
      if (xhttp.readyState == 4) {
        // readyState = 4 means DONE
        if (xhttp.status == 200) {
          // status = 200 means OK
          handleStatusSuccess(xhttp);
        } else {
          // status is NOT OK
          handleStatusFailure(xhttp);
        }
      }
    }
    
    // XMLHttpRequest failed
    function handleStatusFailure(xhttp) {
      // display error message
      var displayDiv = document.getElementById("display");
      displayDiv.innerHTML = "XMLHttpRequest failed: status " + xhttp.status;
    }
    
    // XMLHttpRequest success
    function handleStatusSuccess(xhttp) {
      var xml = xhttp.response;
      xml = parseXML(xml);
    
      // parse the XML into an object
      var weatherObj = parseXMLWeather(xml);
      // display the object on the page
      displayWeather(weatherObj);
    }
    
    // parse the XML into an object
    function parseXMLWeather(xml) {
    
      // print XML on the console
      // console.log(xml);
    
      //create an object to hold the information in the xml file
      var weatherObj = {};
    
      // get the forecast XML element
      var forecastElement = xml.getElementsByTagName("forecast")[0];
      // get the query location
      weatherObj.queryLocation = forecastElement.getAttribute("queryLocation");
      // get the query time
      weatherObj.queryTime = forecastElement.getAttribute("queryTime");
    
      //get the weather XML element
      var weatherElementList = xml.getElementsByTagName("weather")[0];
      weatherObj.YYYYMMDD = weatherElementList.getAttribute("yyyymmdd");
    
      //get the rest of the child XML element in weather
      weatherObj.list = [];
      for (var i = 0; i < weatherElementList.length; i++) {
        var weatherElement = weatherElementList[i];
        var weather1Obj = parseWeatherElement(weatherElement);
        weatherObj.list.push(weather1Obj);
      }
      return weatherObj;
    }
    // Convert XML string to proper XML DOM document.
    function parseXML(xmlString) {
      return new window.DOMParser().parseFromString(xmlString, "text/xml");
    }
    
    // parse a stock XML element into a JavaScript stock object
    function parseWeatherElement(weatherElement) {
      var weather1Obj = {};
    
      //get all elements
      var yearElement = weatherElement.getElementsByTagName("year")[0];
      weather1Obj.year = yearElement.textContent;
      var monthElement = weatherElement.getElementsByTagName("month")[0];
      weather1Obj.month = monthElement.textContent;
      var dateElement = weatherElement.getElementsByTagName("date")[0];
      weather1Obj.date = dateElement.textContent;
      var dayOfWeekElement = weatherElement.getElementsByTagName("dayOfWeek")[0];
      weather1Obj.dayOfWeek = dayOfWeekElement.textContent;
      var overallElement = weatherElement.getElementsByTagName("overall")[0];
      weather1Obj.overall = overallElement.textContent;
      var highestElement = weatherElement.getElementsByTagName("highest")[0];
      weather1Obj.highest = highestElement.textContent;
      var lowestElement = weatherElement.getElementsByTagName("lowest")[0];
      weather1Obj.lowest = lowestElement.textContent;
    
      return weather1Obj;
    }
    
    // display the weather object on the page
    function displayWeather(weatherObj) {
      // print the weatherObj on the console
      // console.log(weatherObj);
    
      // construct HTML code to display weather information
      var html = "<h1>" + weatherObj.queryLocation + " " + weatherObj.queryTime + "</h1>";
      html += weatherObj.YYYYMMDD;
    
      // show the constructed HTML code in the display div
      var displayDiv = document.getElementById("display");
      displayDiv.innerHTML = html;
    }
    <h1>Part 2</h1>
    <button onClick="makeAjaxQueryWeather()">
    Click here to view weather forecast 1
    </button>
    <br/> <br/>
    <div id="display">
    </div>

    更新:让您的代码尽可能简单。

    分析你需要做什么,你基本上需要:

    1. 使用 XMLHttpRequest 获取 XML 内容。因此,在这个示例中,我创建了一个帮助函数,以便在您需要时轻松执行 AJAX 请求。

    var newXHR = null;
    function sendXHR(type, responseType, url, data, successCallback, failureCallback) {
        newXHR = new XMLHttpRequest() || new window.ActiveXObject("Microsoft.XMLHTTP");
        newXHR.responseType = responseType;
        newXHR.open(type, url, true);
        newXHR.send(data);
        newXHR.onreadystatechange = function () {
            if (this.readyState === 4) {
                if (this.status === 200) {
                    successCallback(this.response);
                } else {
                    failureCallback(this.response);
                }
            }
        };
    }
    

    所以,你可以这样使用:

    sendXHR("GET", "text", "https://gist.githubusercontent.com/dannyjhonston/e56a6461d88ebd43d039bac215fa4eb4/raw/af9b5883d35097e8a8a68b619c3b0a9f7a51dc7d/A8.xml", null, function (response) {
        // Success you can use the response object. In this case you get the XML string content.
    }, function (error) {
        displayDiv.innerHTML = "XMLHttpRequest failed: status " + error;
    });
    
    1. 将 XML 字符串内容解析为 XML 文档。

    function parseXML(xmlString) {
        return new window.DOMParser().parseFromString(xmlString, "text/xml");
    }
    

    因此,使用前面的代码,您可以通过这种方式使用parseXML 函数:

    sendXHR("GET", "text", "https://gist.githubusercontent.com/dannyjhonston/e56a6461d88ebd43d039bac215fa4eb4/raw/af9b5883d35097e8a8a68b619c3b0a9f7a51dc7d/A8.xml", null, function (response) {
        var xml = parseXML(response);
    }, function (error) {
        displayDiv.innerHTML = "XMLHttpRequest failed: status " + error;
    });
    
    1. 从 XML 转换为 JavaScript 对象。 使用parseXML(response) 函数的结果,您得到了一个 XML DOM,所以现在您可以浏览 XML 文档中的每个节点,根据需要创建一个 JavaScript 对象.

    function convertXMLToObject(xml) {
        var obj = {}, forecastElement = xml.children[0];
        if (forecastElement) {
            obj.queryLocation = forecastElement.getAttribute("queryLocation");
            obj.queryTime = forecastElement.getAttribute("queryTime");
            obj.list = [];
            var weatherElement, weatherElements = forecastElement.children, weatherElementsLen = weatherElements.length;
            for (var i = 0; i < weatherElementsLen; i++) {
                weatherElement = weatherElements[i];
                if (weatherElement) {
                    obj.list.push({
                        yyyymmdd: weatherElement.getAttribute("yyyymmdd"),
                        year: weatherElement.children[0].textContent,
                        month: weatherElement.children[1].textContent,
                        date: weatherElement.children[2].textContent,
                        dayOfWeek: weatherElement.children[3].textContent,
                        overall: weatherElement.children[4].textContent,
                        overallCode: weatherElement.children[5].textContent,
                        highest: weatherElement.children[6].textContent,
                        lowest: weatherElement.children[7].textContent
                    });
                }
            }
        }
        return obj;
    }
    

    使用上面的函数,您将获得以下 JavaScript 对象:

    {
      "queryLocation": "Whoville",
      "queryTime": "22/07/2017 15:30:45",
      "list": [
        {
          "yyyymmdd": "20170727",
          "year": "2017",
          "month": "7",
          "date": "27",
          "dayOfWeek": "THU",
          "overall": "Considerable clouds",
          "overallCode": "cloudy",
          "highest": "18",
          "lowest": "5"
        },
        {
          "yyyymmdd": "20170726",
          "year": "2017",
          "month": "7",
          "date": "26",
          "dayOfWeek": "WED",
          "overall": "Cloudy with thunderstorm",
          "overallCode": "thunderstorm",
          "highest": "15",
          "lowest": "4"
        },
        {
          "yyyymmdd": "20170725",
          "year": "2017",
          "month": "7",
          "date": "25",
          "dayOfWeek": "TUE",
          "overall": "Considerable",
          "overallCode": "cloudy",
          "highest": "18",
          "lowest": "5"
        },
        {
          "yyyymmdd": "20170724",
          "year": "2017",
          "month": "7",
          "date": "24",
          "dayOfWeek": "MON",
          "overall": "Partly sunny",
          "overallCode": "partlySunny",
          "highest": "21",
          "lowest": "10"
        },
        {
          "yyyymmdd": "20170723",
          "year": "2017",
          "month": "7",
          "date": "23",
          "dayOfWeek": "SUN",
          "overall": "Plenty of sunshine",
          "overallCode": "sunny",
          "highest": "25",
          "lowest": "11"
        }
      ]
    }
    
    1. div 标记中显示天气信息。 最后,使用您在上一点中获得的 JavaScript 对象,您可以使用以下函数:

    function renderObject(data) {
        var html = "";
        html += "<h1>";
        html += data.queryLocation;
        html += " @ ";
        html += data.queryTime;
        html += "</h1>";
        if (data.list && data.list.length) {
            html += "<div class=\"weather\">";
            var len = data.list.length, obj;
            for (var i = 0; i < len; i++) {
                obj = data.list[i];
                html += "<div title=\"";
                html += obj.yyyymmdd;
                html += "\"><div><p><span class=\"dayOfWeek\">";
                html += obj.dayOfWeek;
                html += "</span> ";
                html += obj.month;
                html += "/";
                html += obj.date;
                html += "</p>";
                html += "<p><span class=\"icon ";
                html += obj.overallCode;
                html += "\"></span></p></div><div><p class=\"overall\">";
                html += obj.overall;
                html += "</p><p><span class=\"highest\">";
                html += obj.highest;
                html += "°</span>/";
                html += obj.lowest;
                html += "°</p></div></div>";
            }
            html += "</div>";
        }
        return html;
    }
    

    这样,您可以在 HTML 中得到以下结果。

    另外,您应该尝试使用不显眼的 JavaScript。

    只需在您的按钮中使用 id,就像在以下标记中一样:

    <button id="btnGetData" type="button">
      Click here to view weather forecast 1
    </button>
    

    并使用 JavaScript 调用它,使用以下语法:

    var btnGetData = document.getElementById("btnGetData");
    btnGetData.onclick = function () {
        getXMLContent();
    };
    

    我在这里分享完整的示例,以便您查看。我添加了一些 CSS3 规则以获得更好的可视化效果。

    (function() {
      var newXHR = null;
    
      function sendXHR(type, responseType, url, data, successCallback, failureCallback) {
        newXHR = new XMLHttpRequest() || new window.ActiveXObject("Microsoft.XMLHTTP");
        newXHR.responseType = responseType;
        newXHR.open(type, url, true);
        newXHR.send(data);
        newXHR.onreadystatechange = function() {
          if (this.readyState === 4) {
            if (this.status === 200) {
              successCallback(this.response);
            } else {
              failureCallback(this.response);
            }
          }
        };
      }
    
      function getXMLContent() {
        var displayDiv = document.getElementById("display");
        if (displayDiv) {
          sendXHR("GET", "text", "https://gist.githubusercontent.com/dannyjhonston/e56a6461d88ebd43d039bac215fa4eb4/raw/af9b5883d35097e8a8a68b619c3b0a9f7a51dc7d/A8.xml", null, function(response) {
            var xml = parseXML(response), obj = convertXMLToObject(xml);
            displayDiv.innerHTML = renderObject(obj);
          }, function(error) {
            displayDiv.innerHTML = "XMLHttpRequest failed: status " + error;
          });
        }
      }
    
      function parseXML(xmlString) {
        return new window.DOMParser().parseFromString(xmlString, "text/xml");
      }
    
      function convertXMLToObject(xml) {
        var obj = {}, forecastElement = xml.children[0];
        if (forecastElement) {
          obj.queryLocation = forecastElement.getAttribute("queryLocation");
          obj.queryTime = forecastElement.getAttribute("queryTime");
          obj.list = [];
          var weatherElement, weatherElements = forecastElement.children,
            weatherElementsLen = weatherElements.length;
          for (var i = 0; i < weatherElementsLen; i++) {
            weatherElement = weatherElements[i];
            if (weatherElement) {
              obj.list.push({
                yyyymmdd: weatherElement.getAttribute("yyyymmdd"),
                year: weatherElement.children[0].textContent,
                month: weatherElement.children[1].textContent,
                date: weatherElement.children[2].textContent,
                dayOfWeek: weatherElement.children[3].textContent,
                overall: weatherElement.children[4].textContent,
                overallCode: weatherElement.children[5].textContent,
                highest: weatherElement.children[6].textContent,
                lowest: weatherElement.children[7].textContent
              });
            }
          }
        }
        return obj;
      }
    
      function renderObject(data) {
        var html = "";
        html += "<h1>";
        html += data.queryLocation;
        html += " @ ";
        html += data.queryTime;
        html += "</h1>";
        if (data.list && data.list.length) {
          html += "<div class=\"weather\">";
          var len = data.list.length, obj;
          for (var i = 0; i < len; i++) {
            obj = data.list[i];
            html += "<div title=\"";
            html += obj.yyyymmdd;
            html += "\"><div><p><span class=\"dayOfWeek\">";
            html += obj.dayOfWeek;
            html += "</span> ";
            html += obj.month;
            html += "/";
            html += obj.date;
            html += "</p>";
            html += "<p><span class=\"icon ";
            html += obj.overallCode;
            html += "\"></span></p></div><div><p class=\"overall\">";
            html += obj.overall;
            html += "</p><p><span class=\"highest\">";
            html += obj.highest;
            html += "°</span>/";
            html += obj.lowest;
            html += "°</p></div></div>";
          }
          html += "</div>";
        }
        return html;
      }
    
      var btnGetData = document.getElementById("btnGetData");
      btnGetData.onclick = function() {
        getXMLContent();
      };
    }());
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      font-size: 1em;
      margin: 0 10px;
      padding: 0;
    }
    
    .weather {
      margin: 10px;
      width: 70%;
    }
    
    .weather div {
      border: #95b6e0 solid 1px;
      display: flex;
      margin: 5px;
      padding: 0;
    }
    
    .weather div div {
      border-style: none;
      display: block;
      padding: 5px;
      width: 50%;
    }
    
    .weather div div p {
      display: block;
      margin: 0;
      padding: 0;
    }
    
    .weather .dayOfWeek {
      background-color: inherit;
      color: #2b6daf;
      font-weight: 500;
    }
    
    .weather .overall {
      font-style: italic;
    }
    
    .weather .highest {
      font-size: 2em;
    }
    
    .weather .icon {
      background: url(https://cdn1.vectorstock.com/i/1000x1000/13/30/weather-icons-vector-731330.jpg) no-repeat;
      display: inline-block;
      height: 48px;
      width: 48px;
    }
    
    .weather .icon.sunny {
      background-position: 4px 6px;
      background-size: 400% 400%;
    }
    
    .weather .icon.partlySunny {
      background-position: -46px 7px;
      background-size: 400% 400%;
    }
    
    .weather .icon.cloudy {
      background-position: -48px -81px;
      background-size: 400% 448%;
    }
    
    .weather .icon.thunderstorm {
      background-position: -48px -41px;
      background-size: 400% 460%;
    }
    <h1>Part 2</h1>
    <button id="btnGetData" type="button">
    		Click here to view weather forecast 1
    	</button>
    <br /> <br />
    <div id="display">
    </div>

    【讨论】:

    • 我能否知道我无法从桌面本地读取 XML 文件的原因?为什么'html += weatherObj.YYYYMMDD;'尽管我做了一个 for 循环,但只调用第一个天气元素而不是后续的天气元素?
    • 根据 MDN developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest:为了能够使用 XMLHttpRequest 发出 HTTP 请求,您的页面必须托管在服务器上。
    • @alonelycoder,我正在分析您代码中的问题。我已经发布了对我的答案的更新,其中包含可以让您正确解决问题的不同建议。我希望它有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多