【问题标题】:Search a table made with JS with for() loop使用 for() 循环搜索用 JS 制作的表格
【发布时间】:2019-06-15 12:41:31
【问题描述】:

我正在尝试设置一个搜索栏,该栏搜索通过按名称或电子邮件从 API 获取的循环数据创建的表格,但我找不到我出错的地方。控制台显示未捕获的 ReferenceError: sBar is not defined at window.onload 请记住,我是 JS 的新手。真的很抱歉这很愚蠢,但我已尽力而为,我对无法看到错误感到非常沮丧

这是我的 HTML

<body>
  <div>
    <label for="finder">Find User:</label>
    <input type="search" id="searchInput" name="sInput" placeholder="Search 
    user">
    <button id="sButton">Search</button>
  </div>
  <table class="table table-responsive">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Id</th>
        <th scope="col">Name</th>
        <th scope="col">Username</th>
        <th scope="col">Email</th>
        <th scope="col">Address</th>
        <th scope="col">Phone</th>
        <th scope="col">Website</th>
        <th scope="col">Company</th>
      </tr>
    </thead>
    <tbody name="tTable">
    </tbody>
  </table>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
<script src="script.js">
</script>

小米JS

window.onload = function(){    

    let uList = document.querySelector('[name =tTable]');  

    fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
    sButton.addEventListener('click', 
    fetchCall('https://jsonplaceholder.typicode.com/users', sBar), false);


  function sBar(getObject) {
    let sUser = getObject;
    let inputBar = document.getElementById("searchInput");
    let text = inputBar.textContent;
    let textView = text.toUpperCase();
    for (let i = 0; i < getObject.length; i++) {
         let uObject = sUser[i];
      if (textView == uObject.name || textView == uObject.email) {
        let new_tTable = document.createElement('tbody');
        uList.parentNode.replaceChild(new_tTable, uList)

        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = uObject.id;
        nameInput.textContent = uObject.name;
        usernameInput.textContent = uObject.username;
        emailInput.textContent = uObject.email;
        cityInput.textContent = uObject.address.city;
        phoneInput.textContent = uObject.phone;
        websiteInput.textContent = uObject.website;
        companyInput.textContent = uObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
        row.appendChild(usernameInput);
        row.appendChild(emailInput);
        row.appendChild(cityInput);
        row.appendChild(phoneInput);
        row.appendChild(websiteInput);
        row.appendChild(companyInput);  
     } else {
       alert("User not found");         
     }
   }
} 


  function fetchCall(url, fn){
    fetch(url)
        .then(function(response){
            return response.json();
        })
        .then(function(endPoint){
            fn(endPoint);
        })
        .catch(function(error){
            console.error(error);
        })
    }

  function getUsers(getObject) {
    let user = getObject;      
      for (let i = 0; i < getObject.length; i++) {
        let userObject = user[i];
        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = userObject.id;
        nameInput.textContent = userObject.name;
        usernameInput.textContent = userObject.username;
        emailInput.textContent = userObject.email;
        cityInput.textContent = userObject.address.city;
        phoneInput.textContent = userObject.phone;
        websiteInput.textContent = userObject.website;
        companyInput.textContent = userObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
         row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);        
        }
      } 
    }

【问题讨论】:

  • name 属性在大部分元素中是没有意义的,只有表单控件元素和窗口元素被名称识别。将id 用于其他元素。实际出现什么问题,用帖子里的代码是无法复现的。
  • "sBar is not defined at window.onload" 没有正确描述问题,应该是“sBar is not defined on "Search" button click” ...不要使用内联事件,在window.onload 函数内添加按钮的事件。向sButton 添加点击监听器也会失败,fetchCall 不会返回任何用作事件处理函数的内容。

标签: javascript ajax for-loop html-table search-box


【解决方案1】:

您可能希望单独定义window.onload 和其他函数。

window.onload = function(){    

    let uList = document.querySelector('[name =tTable]');  

    fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
    sButton.addEventListener('click', 
    fetchCall('https://jsonplaceholder.typicode.com/users', sBar), false);
};

  function sBar(getObject) {
    let sUser = getObject;
    let inputBar = document.getElementById("searchInput");
    let text = inputBar.textContent;
    let textView = text.toUpperCase();
    for (let i = 0; i < getObject.length; i++) {
         let uObject = sUser[i];
        if (textView == uObject.name || textView == 
       uObject.email) {
        let new_tTable = document.createElement('tbody');
        uList.parentNode.replaceChild(new_tTable, uList)


        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = uObject.id;
        nameInput.textContent = uObject.name;
        usernameInput.textContent = uObject.username;
        emailInput.textContent = uObject.email;
        cityInput.textContent = uObject.address.city;
        phoneInput.textContent = uObject.phone;
        websiteInput.textContent = uObject.website;
        companyInput.textContent = uObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
          row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);  
          } else{
           alert("User not found");
               }
       }
   } 


  function fetchCall(url, fn){
    fetch(url)
        .then(function(response){
            return response.json();
        })
        .then(function(endPoint){
            fn(endPoint);
        })
        .catch(function(error){
            console.error(error);
        })
    }

  function getUsers(getObject) {
    let user = getObject;      
      for (let i = 0; i < getObject.length; i++) {
        let userObject = user[i];
        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = userObject.id;
        nameInput.textContent = userObject.name;
        usernameInput.textContent = userObject.username;
        emailInput.textContent = userObject.email;
        cityInput.textContent = userObject.address.city;
        phoneInput.textContent = userObject.phone;
        websiteInput.textContent = userObject.website;
        companyInput.textContent = userObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
         row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);        
        }
      } 

【讨论】:

    【解决方案2】:

    您已将回调sBar() 附加到搜索输入的onchange 事件。但是没有sBar() 函数的定义(请注意,它不接受参数/参数)。您只定义了一个具有相同名称“sBar”的函数,它接受(需要)您命名为getObject 的参数。

    去掉参数“getObject”,修改前几行,用于在搜索输入中获取当前输入的文本。获取搜索输入值的示例代码是:

    var value = document.getElementById("searchInput").value;
    

    旁注:

    您可能需要使用另一个事件发射器而不是onchange。仅当您将焦点放在输入元素上而不是实际输入上时才会触发。

    如果您想在输入时跟踪更改,请使用"onkeydown"。如果您需要用鼠标捕获粘贴操作,请使用"onpaste"(IE、FF3)和"oninput"(FF、Opera、Chrome、Safari1)。

    请从this链接查看

    【讨论】:

      【解决方案3】:

      设置事件时调用函数,但需要绑定。

      sButton.addEventListener('click', fetchCall.bind(this, 'https://jsonplaceholder.typicode.com/users', sBar), false);
      

      我还建议在全局范围内创建一个函数。

      uList = document.querySelector('[name =tTable]');
      
      window.onload = function () {
          fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
          sButton.addEventListener('click', fetchCall.bind(this, 'https://jsonplaceholder.typicode.com/users', sBar), false);
      }
      
      function sBar(getObject) {
          let sUser = getObject;
          let inputBar = document.getElementById("searchInput");
          let text = inputBar.textContent;
          let textView = text.toUpperCase();
          for (let i = 0; i < getObject.length; i++) {
              let uObject = sUser[i];
              if (textView == uObject.name || textView ==
                  uObject.email) {
                  let new_tTable = document.createElement('tbody');
                  uList.parentNode.replaceChild(new_tTable, uList)
      
      
                  let row = uList.insertRow();
                  let idInput = document.createElement('td');
                  let nameInput = document.createElement('td');
                  let usernameInput = document.createElement('td');
                  let emailInput = document.createElement('td');
                  let cityInput = document.createElement('td');
                  let phoneInput = document.createElement('td');
                  let websiteInput = document.createElement('td');
                  let companyInput = document.createElement('td');
      
                  idInput.textContent = uObject.id;
                  nameInput.textContent = uObject.name;
                  usernameInput.textContent = uObject.username;
                  emailInput.textContent = uObject.email;
                  cityInput.textContent = uObject.address.city;
                  phoneInput.textContent = uObject.phone;
                  websiteInput.textContent = uObject.website;
                  companyInput.textContent = uObject.company.name;
                  row.appendChild(idInput);
                  row.appendChild(nameInput);
                  row.appendChild(usernameInput);
                  row.appendChild(emailInput);
                  row.appendChild(cityInput);
                  row.appendChild(phoneInput);
                  row.appendChild(websiteInput);
                  row.appendChild(companyInput);
              } else {
                  alert("User not found");
              }
          }
      }
      
      
      function fetchCall(url, fn) {
          fetch(url)
              .then(function (response) {
                  return response.json();
              })
              .then(function (endPoint) {
                  fn(endPoint);
              })
              .catch(function (error) {
                  console.error(error);
              })
      }
      
      function getUsers(getObject) {
          let user = getObject;
          for (let i = 0; i < getObject.length; i++) {
              let userObject = user[i];
              let row = uList.insertRow();
              let idInput = document.createElement('td');
              let nameInput = document.createElement('td');
              let usernameInput = document.createElement('td');
              let emailInput = document.createElement('td');
              let cityInput = document.createElement('td');
              let phoneInput = document.createElement('td');
              let websiteInput = document.createElement('td');
              let companyInput = document.createElement('td');
      
              idInput.textContent = userObject.id;
              nameInput.textContent = userObject.name;
              usernameInput.textContent = userObject.username;
              emailInput.textContent = userObject.email;
              cityInput.textContent = userObject.address.city;
              phoneInput.textContent = userObject.phone;
              websiteInput.textContent = userObject.website;
              companyInput.textContent = userObject.company.name;
              row.appendChild(idInput);
              row.appendChild(nameInput);
              row.appendChild(usernameInput);
              row.appendChild(emailInput);
              row.appendChild(cityInput);
              row.appendChild(phoneInput);
              row.appendChild(websiteInput);
              row.appendChild(companyInput);
          }
      }
      

      【讨论】:

      • 刚刚进行了更改,但我仍然有相同的 sBar 未定义错误。试过 IE、FF 和 Chrome
      【解决方案4】:

      async/await & fetch()

      核心函数是基于async/awaitfetch(),特殊语法请到上面的链接。

      老实说,我不知道如何处理 OP(O原始 Post)代码的所有问题。一般来说,您应该分步考虑该过程:

      1. 从 URL 获取 JSON。你确定fetchAll() 有效吗?

      2. 一旦您可以使用 fetchCall() 获取 JSON,请将 JSON 传递给 getUser()

      3. 如果fetchCall() 返回一个值(看起来确实如此...),则使用整个函数作为一个值。

      4. 事件侦听器和处理程序具有您必须遵守的特定签名,并且使用命名回调或匿名回调很重要:

      命名回调(无参数*)

      DOMObj.addEventListener('event', namedFunction);
      function namedFunction(e) {...
      

      命名回调(带参数)

      DOMObj.addEventListener('event', function(e) {
        namedFunction(num, str);
      });
      function namedFunction(num, str) {...
      

      匿名回调

      DOMObj.addEventListener('event', function(e) {...
      

      以下演示使用async function getUser(url, id) 来简化Promises,使用fetch(),并一次提取一个用户ID 的JSON。 function getData(json) 与 JSON 一起由 getUser() 返回。

      搜索输入已更改为type='number',因为用户的user.id 属性引用了用户。它还包含在&lt;form&gt; 标记中,因此回调function findUser(url, id) 将由提交事件触发。它基本上是getUser() 的函数包装器。


      演示

      <!DOCTYPE html>
      <html>
      <head>
      <meta charset='utf-8'>
      <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
      <style>
      fieldset.fieldset {width:max-content;padding: 10px 0 0}
      input.input, label.label {display:inline-block;font:inherit;width:9ch;height:30px;line-height:30px;vertical-align:middle;text-align:center;}
      input.input {width:6ch;padding-right:0;margin-right:8px}
      input.button {font:inherit;height: 30px;line-height:20px;}
      </style>
      </head>
      <body>
        <main class='container'>
          <section class='row'>
            <form id='main' class='form inline-form'>
              <fieldset class='fieldset form-group'>
                <label class='label control-label float-left' for="find">User ID:</label>
                <input id="find" class='input form-control float-left' type="number" min='1' max='10'>
                <input class="button btn btn-dark btn-sm float-left" type='submit' value='Find'>
             </fieldset>
          </form>
        </section>
        <section class='row'>
        <table class="table table-responsive">
          <thead class="thead-dark">
            <tr>
              <th scope="col">ID</th>
              <th scope="col">Name</th>
              <th scope="col">Username</th>
              <th scope="col">Email</th>
              <th scope="col">Phone</th>
              <th scope="col">Company</th>
              <th scope="col">City</th>
              <th scope="col">Website</th>
            </tr>
          </thead>
        </table>
       </section>
      </main>
      <script>
      
      const main = document.forms[0];
      
      const getData = (user) => {
        const uList = document.querySelector('.table');
        let row = uList.insertRow();  
        let cell = idx => row.insertCell(idx);
        
        for (let i = 0; i < 8; i++) {
          let C = cell(i);
          switch(i) {
            case 0:
            user.id = user.id > 9 ? "" + user.id: "0" + user.id;
            C.textContent = user.id;
            break;
            case 1:
            C.textContent = user.name;
            break;
            case 2:
            C.textContent = user.username;
            break;
            case 3:
            C.textContent = user.email;
            break;
            case 4:
            C.textContent = user.phone;
            break;
            case 5:
            C.textContent = user.company.name;
            break;
            case 6:
            C.textContent = user.address.city;
            break;
            case 7:
            C.textContent = user.website;
            break;
            default:
            break;
          }
        } 
      };
      
      const getUser = async (url, id) => { 
        const response = await fetch(`${url}${id}`);
        const json = await response.json();
        return getData(json);
      };
      
      /*/ For debugging -- an IIFE variables are private. Parameters are required.
      (async (u, i) => {
        const json = await getUser(u, i);
        console.log(json);
      })(url, id);
      /*/
      
      const findUser = (e) => {
        e.preventDefault();
        const url = 'https://jsonplaceholder.typicode.com/users/';
        let id = Number(e.currentTarget.find.value);
        getUser(url, id);
      };
      
      main.addEventListener('submit', findUser);
      
      </script>
      </body>
      </html>

      【讨论】:

        猜你喜欢
        • 2014-04-22
        • 2021-04-13
        • 2018-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-13
        相关资源
        最近更新 更多