首页 > 解决方案 > 未捕获的类型错误:无法读取 null 的属性“样式”。在同一页面中使用两个 Javascript 函数

问题描述

我有两个试图实现的 JavaScript 函数,但它们似乎相互冲突。

一个称为“showPage”的函数在单击该页面的按钮时显示/阻止选定的页面。像这样。

 function showPage(page) {
        document.querySelectorAll('tbody').forEach(tbody => {tbody.style.display = 'none';})

        document.querySelector(`#${page}`).style.display = 'table-row-group'; ---(This line in error message)
    }

    document.addEventListener('DOMContentLoaded', function() {
        document.querySelectorAll('button').forEach(button => {
            button.onclick = function() {
                showPage(this.dataset.page); ---(This line in error message)
            }           
        });
    });

这是 showPage 所针对的按钮的一个示例,以及它将显示或阻止的页面的一个示例。

<button class="posbutton" data-page="page1">QB</button>


<tbody id="page1">
               
         {% for q in QBpage %}
              <tr>
                <th scope="row">
                      
                </th>
                    
                <td><h6>{{ q.player_name }}</h6></td>
                <td><button> class="btn btn-outline-primary btn-sm m-0 waves-effect" onclick="myFunction('{{ player_data.player_name }} {{ player_data.position }}')">Add</button></td>
                <td><h6> {{ q.team }} </h6></td>
                <td><h6> {{ q.position }}  </h6></td>
                <td><h6>{{ q.points }}</h6></td>
                </tr>
                  
         {% endfor %}
</tbody>
               <!--several more pages like the above-->

总共有5个页面可以切换。当页面切换为显示时,页面上有一个按钮,该按钮链接到另一个名为 myFunction 的 JavaScript 函数。<td>此函数将元素中的文本提交到表单字段。这是我的函数。

function myFunction(txt) {
        var myTxt = txt;
    
        
        if (txt.includes('QB')) {
            document.getElementById("QB_name").value = myTxt;
        }

        else if (txt.includes('RB')) {
            document.getElementById("RB_name").value = myTxt;
        }

        else if (txt.includes('WR')) {
            document.getElementById("WR_name").value = myTxt;
        }

        else if (txt.includes('TE')) {
            document.getElementById("TE_name").value = myTxt;
        }

        else if (txt.includes('K')) {
            document.getElementById("K_name").value = myTxt;
        }
        
    }

但是,当我加载一个页面然后单击一个按钮以提交该行中的数据时,此 onclick 会导致整个页面消失。控制台错误消息指向 showPage 中的行showPage(this.dataset.page);,我认为问题是因为 showPage 的目标是所有按钮,该行document.querySelectorAll('button')单击按钮以使用 myFunction 提交数据实际上是调用 showPage,因为 showPage 目标是页面上的所有按钮元素。那么,如何阻止这两个功能发生冲突呢?这是我的知识耗尽的地方,因为我对 JavaScript 还很陌生。我想我可以明白为什么它不起作用,但我不知道如何开发替代方案。如果您阅读此内容,请提前致谢。

标签: javascripthtmltypeerror

解决方案


With document.querySelectorAll('button')one 确实以 any 为目标<button/>,这也意味着那些不提供属性[data-page]的对象,例如<tbody/>.

如果单击这样的按钮,this.dataset.page则会将undefined值传递给showPage函数,然后该函数在.style.display访问document.querySelector(``#${page}``).

为了首先正确初始化事件处理,可以尝试[data-page]仅通过定位按钮来相应地更改代码......

function handleShowPage(evt) {
  // showPage(this.dataset.page);
  showPage(evt.currentTarget.dataset.page);
}
document.addEventListener('DOMContentLoaded', function() {
  document
    .querySelectorAll('button[data-page]')
    .forEach(button =>
      button.addEventListener('click', handleShowPage)
    );
});

编辑

但是,当我加载一个页面然后单击一个按钮以提交该行中的数据时,此 onclick 会导致整个页面消失。

任何未通过其[type]属性明确说明其类型的按钮都将触发包含它的表单的提交。

因此,为了防止这种行为,可能会编写这样的按钮代码......或者通过在此按钮的单击处理程序中<button type='button' ...调用来主动抑制触发此类按钮的单击事件的提交默认值。evt.preventDefault()

编辑/总结

说了以上所有内容后,我会将OP的代码更改为这种方法...

标记

<button type="button" data-page="page1" class="posbutton">QB</button>

<tbody id="page1">
  {% for q in QBpage %}
    <tr>
      <th scope="row"></th>
      <td><h6>{{ q.player_name }}</h6></td>
      <td>
        <button
          type="button"
          data-player-name="{{ q.player_name }}"
          data-position="{{ q.position }}"
          class="btn btn-outline-primary btn-sm m-0 waves-effect"
        >Add</button>
      </td>
      <td><h6>{{ q.team }}</h6></td>
      <td><h6>{{ q.position }}</h6></td>
      <td><h6>{{ q.points }}</h6></td>
    </tr>
  {% endfor %}
</tbody>

脚本

function showPage(pageId) {
  document
    .querySelectorAll('tbody')
    .forEach(tbody => tbody.style.display = 'none');
  document
    .querySelector(`#${ pageId }`)
    .style.display = 'table-row-group';
}
function updatePosition(name, position) {
  document
    .querySelector(`#${ position }_name`)
    .value = [name, position].join(' ');
}

function handleShowPage(evt) {
  showPage(evt.currentTarget.dataset.page);
}
function handleUpdatePosition(evt) {
  const { playerName, position } = evt.currentTarge.dataset;
  updatePosition(playerName, position);
}

document.addEventListener('DOMContentLoaded', function() {
  document
    .querySelectorAll('button[data-page]')
    .forEach(button =>
      button.addEventListener('click', handleShowPage)
    );
  document
    .querySelectorAll('button[data-position][data-player-name]')
    .forEach(button =>
      button.addEventListener('click', handleUpdatePosition)
    );
});

推荐阅读