使用递归函数时的错误问题在JavaScript中

huangapple go评论77阅读模式
英文:

Error question when using recursive function in JavaScript

问题

在'findChildComment'方法的最后一行,“document.querySelector(idForInnerHtml).innerHTML = commentHtml;”处发生“Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')”错误。

我通过日志检查发现“<id='cm_reply_view${row.id}'>”和“<var idForInnerHtml = '#cm_reply_view' + parentId;>”具有相同的值,但我不知道哪个部分有问题。如果有人知道,请告诉我,谢谢。

请注意,此错误表明在尝试设置HTML内容时,找不到指定的DOM元素。可能的原因是DOM元素不存在或JavaScript代码在尝试访问DOM元素之前运行。

要解决此问题,您可以采取以下步骤:

  1. 确保HTML中存在具有相应ID的DOM元素,例如“cm_reply_view${row.id}”。

  2. 确保JavaScript代码在尝试访问这些DOM元素之前,页面已经加载完毕。您可以将代码包装在“window.onload”事件处理程序中,以确保在页面完全加载后运行。

  3. 在代码中添加适当的错误处理,以处理DOM元素不存在的情况,例如使用条件语句检查元素是否存在,然后执行操作。

请根据上述建议检查您的代码,并确保DOM元素存在且JavaScript代码在需要时运行。这应该有助于解决您遇到的问题。

英文:

I'm implementing a bulletin board comment function, but I'm blocked from looking up comments.

I made a recursive function to make the big comments appear under the comments, but I keep getting errors, but I don't know where the problem is.

window.onload = () =&gt; {
      findAllComment();
    }

// 전체 댓글 조회
    function findAllComment() {

      const postId = [[ ${post.id} ]];
      const accountId = [[ ${account.id} ]]

      $.ajax({
        url: `/api/posts/${postId}/comments`,
        beforeSend: function (xhr) {
          xhr.setRequestHeader(header, token);
        },
        type: &#39;get&#39;,
        dataType: &#39;json&#39;,
        async: false,
        success: function (response) {

          console.log(response);

          // 1. 조회된 데이터가 없는 경우
          if (!response.result.data.length) {
            return false;
          }

          // 2. 렌더링 할 HTML을 저장할 변수
          let commentHtml = &#39;&#39;;

          // 3. 댓글 HTML 추가
          response.result.data.forEach(row =&gt; {
            commentHtml += `
                              &lt;div class=&quot;card py-0 mt-3&quot;&gt;
                                  &lt;div class=&quot;card-header bg-light&quot;&gt;
                                      &lt;span class=&quot;comment-writer&quot;&gt;&lt;span class=&quot;card-text&quot;&gt;${row.account.nickname}&lt;/span&gt;&lt;/span&gt;
                                      &lt;a sec:authorize=&quot;isAuthenticated()&quot; th:if=&quot;${row.account.id == accountId}&quot;&gt;
                                          &lt;a class=&quot;comment-delete&quot; onclick=&quot;deleteComment(${row.id});&quot;&gt;&lt;i class=&quot;bi bi-trash3&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;삭제&lt;/span&gt;&lt;/a&gt;
                                          &lt;a class=&quot;comment-edit&quot; onclick=&quot;findEditComment(${row.id});&quot;&gt;&lt;i class=&quot;fa fa-pencil&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;수정&lt;/span&gt;&lt;/a&gt;
                                      &lt;/a&gt;
                                      &lt;a class=&quot;comment-reply&quot; onclick=&quot;findReplyComment(${row.id})&quot;&gt;&lt;i class=&quot;fa fa-comment fa&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;답글&lt;/span&gt;&lt;/a&gt;
                                      &lt;span class=&quot;date&quot; id=&quot;commentDate&quot;&gt;${dayjs(row.createdDateTime).format(&#39;YYYY-MM-DD HH:mm&#39;)}&lt;/span&gt;
                                  &lt;/div&gt;
                                  &lt;div class=&quot;card-body&quot;&gt;
                                      &lt;span class=&quot;comment-content&quot;&gt;&lt;span class=&quot;card-text&quot;&gt;${row.content}&lt;/span&gt;&lt;/span&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;

                              &lt;!--/* 답글 뷰 */--&gt;
                              &lt;div id=&quot;cm_reply_view${row.id}&quot;&gt;&lt;/div&gt;

                              &lt;!--/* 댓글 수정 뷰 */--&gt;
                              &lt;div id=&quot;cm_edit_view${row.id}&quot;&gt;&lt;/div&gt;

                              &lt;!--/* 댓글 답글 작성 뷰 */--&gt;
                              &lt;div id=&quot;cm_createReply_view${row.id}&quot;&gt;&lt;/div&gt;
                            `;

            if (row.children.length) {
              row.children.forEach(childRow =&gt; {
                findChildComment(row.id, childRow);
              })
            }
          })

          // 4. class가 &quot;cm_list&quot;인 요소를 찾아 HTML을 렌더링
          document.querySelector(&#39;.cm_list&#39;).innerHTML = commentHtml;
        },
        error: function (request, status, error) {
          console.log(error)
        }
      })
    }

    // 답글 조회
    function findChildComment(parentId, child) {

      var idForInnerHtml = &#39;#cm_reply_view&#39; + parentId;
      const accountId = [[ ${account.id} ]];

      let commentHtml = `
                              &lt;div class=&quot;card py-0 mt-3&quot;&gt;
                                  &lt;div class=&quot;card-header bg-light&quot;&gt;
                                      &lt;span class=&quot;comment-writer&quot;&gt;&lt;span class=&quot;card-text&quot;&gt;${child.account.nickname}&lt;/span&gt;&lt;/span&gt;
                                      &lt;a sec:authorize=&quot;isAuthenticated()&quot; th:if=&quot;${child.account.id == accountId}&quot;&gt;
                                          &lt;a class=&quot;comment-delete&quot; onclick=&quot;deleteComment(${child.id});&quot;&gt;&lt;i class=&quot;bi bi-trash3&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;삭제&lt;/span&gt;&lt;/a&gt;
                                          &lt;a class=&quot;comment-edit&quot; onclick=&quot;findEditComment(${child.id});&quot;&gt;&lt;i class=&quot;fa fa-pencil&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;수정&lt;/span&gt;&lt;/a&gt;
                                      &lt;/a&gt;
                                      &lt;a class=&quot;comment-reply&quot; onclick=&quot;findReplyComment(${child.id})&quot;&gt;&lt;i class=&quot;fa fa-comment fa&quot;&gt;&lt;/i&gt;&lt;span class=&quot;card-text ml-1&quot;&gt;답글&lt;/span&gt;&lt;/a&gt;
                                      &lt;span class=&quot;date&quot; id=&quot;commentDate&quot;&gt;${dayjs(child.createdDateTime).format(&#39;YYYY-MM-DD HH:mm&#39;)}&lt;/span&gt;
                                  &lt;/div&gt;
                                  &lt;div class=&quot;card-body&quot;&gt;
                                      &lt;span class=&quot;comment-content&quot;&gt;&lt;span class=&quot;card-text&quot;&gt;${child.content}&lt;/span&gt;&lt;/span&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;

                              &lt;!--/* 답글 뷰 */--&gt;
                              &lt;div id=&quot;cm_reply_view${child.id}&quot;&gt;&lt;/div&gt;

                              &lt;!--/* 댓글 수정 뷰 */--&gt;
                              &lt;div id=&quot;cm_edit_view${child.id}&quot;&gt;&lt;/div&gt;

                              &lt;!--/* 댓글 답글 작성 뷰 */--&gt;
                              &lt;div id=&quot;cm_createReply_view${child.id}&quot;&gt;&lt;/div&gt;
                            `;

      if (child.children.length) {
        child.children.forEach(childRow =&gt; {
          findChildComment(child.id, childRow);
        })
      }

      document.querySelector(idForInnerHtml).innerHTML = commentHtml;
    }

"Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')" error occurs at "document.querySelector(idForInnerHtml).innerHTML = commentHtml;" last line of 'findChildComment ' method.

I checked through logs that <id="cm_reply_view${row.id}"> and <var idForInnerHtml = '#cm_reply_view' + parentId;> has same value, but I don't know which part is the problem. If anyone knows, please let me know, thank you.

答案1

得分: 2

问题在于您在执行递归之后才分配HTML。然而,递归调用需要父div的HTML已经存在于文档中。因此,您需要稍微调整逻辑。

以下是一些对代码的更改,应该可以使其正常工作:

  • success回调中,第3步,在进行递归调用之前,首先完成forEach循环:

    response.result.data.forEach(row => {
        commentHtml += /* 这里放入您的HTML */;
    }); // 首先完成顶部的HTML,然后将收集到的HTML加载到文档中
    document.querySelector('.cm_list').innerHTML = commentHtml;
    // 现在才执行递归,这需要HTML已经存在于文档中。
    response.result.data.forEach(row => {
      if (row.children.length) {
        row.children.forEach(childRow => {
          findChildComment(row.id, childRow);
        })
      }
    })
    
  • findChildComment中也需要进行类似的更改:

    let commentHtml = /* 这里放入您的HTML */;
    // 再次强调:首先分配递归调用所需的HTML
    document.querySelector(idForInnerHtml).innerHTML = commentHtml;
    // ...然后进行递归调用:
    if (child.children.length) {
      child.children.forEach(childRow => {
        findChildComment(child.id, childRow);
      })
    }
    
英文:

The problem is that you are assigning the HTML after having performed the recursion. Yet the recursive calls need the HTML with the parent div to already be present in the document. So you need to reverse the logic a bit.

Here are some changes to the code that should make it work:

  • In the success callback, in step 3, first finish the forEach loop before making recursive calls:

    response.result.data.forEach(row =&gt; {
        commentHtml += /* Your HTML Comes here */ ;
    }); // Finish the top HTML first, then load the collected HTML into the document
    document.querySelector(&#39;.cm_list&#39;).innerHTML = commentHtml;
    // And only now perform the recursion, which needs that HTML 
    // to already be present in the document.
    response.result.data.forEach(row =&gt; {
      if (row.children.length) {
        row.children.forEach(childRow =&gt; {
          findChildComment(row.id, childRow);
        })
      }
    })
    
  • A similar change is needed in findChildComment:

    let commentHtml = /* Your HTML comes here */;
    // Again: first assign the HTML that you need for the recursive calls
    document.querySelector(idForInnerHtml).innerHTML = commentHtml;
    // ... and then make the recursive calls:
    if (child.children.length) {
      child.children.forEach(childRow =&gt; {
        findChildComment(child.id, childRow);
      })
    }
    

huangapple
  • 本文由 发表于 2023年7月27日 23:22:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781261.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定