开发者问题收集

JS 代码在控制台中可以运行,但在控制台之外则不行

2022-09-26
180

我正在使用 Nuxt.js 编写博客,并且我已连接到 ButterCMS 的 API。
我想获取帖子的日期(文本)并对其进行切片。我的问题是它返回错误: TypeError:null 不是对象(评估“document.querySelector(".date").textContent') 。当我在 JS 控制台中执行相同的代码时,它可以正常工作。我已经尝试向页面加载添加事件侦听器,但它没有改变任何东西。这是我的代码:

document.querySelector(".date").textContent.slice(0, 29);
<template>
  <div id="blog-home">
    <div class="recent-article-feed">
      <div v-for="(post, index) in posts" :key="post.slug + '_' + index">
        <router-link :to="'/blog/' + post.slug">
          <div class="article">
            <div class="dark-window">
              <div class="text-box">
                <h2 class="title">{{ post.title }}</h2>
                <div>
                  <span class="author">
                    <i class="fa-solid fa-user"></i> Par Maxime Hamou
                  </span>
                  &#8729;
                  <span class="date">
                    <i class="fa-solid fa-calendar-days"></i>
                    {{ post.published }}
                  </span>
                </div>
                <p class="description">
                  {{ post.summary }}
                </p>
                <p class="read">Lire l'article &#x2192;</p>
              </div>
            </div>
          </div>
        </router-link>
      </div>
    </div>
  </div>
</template>

<style>
@import url("../css/index.css");
@import url("../css/components/recent-article-feed.css");
</style>

<script>
import { butter } from "~/plugins/buttercms";
export default {
  data() {
    return {
      posts: [],
    };
  },
  methods: {
    getPosts() {
      butter.post
        .list({
          page: 1,
          page_size: 10,
        })
        .then((res) => {
          // console.log(res.data)
          this.posts = res.data.data;
        });
    },
  },
  created() {
    this.getPosts();
  },
};
</script>
2个回答

首先要确保我们理解错误试图告诉我们什么。

TypeError: null is not an object (evaluating 'document.querySelector(".date").textContent')

通常,当您看到某些内容( 如变量或元素 )被标记为 nullundefined 时,这意味着它不存在。这可能是由于时间问题( 在创建/准备就绪之前被调用 )或由于范围问题( 如在其声明的范围/函数之外调用变量 )。

由于您使用的是 API 和基于模板的代码,因此几乎可以肯定这是时间问题。您确实提到过您尝试在页面加载时添加事件侦听器,但这仅在您的元素/数据在页面加载之前设置时才有效,而这几乎肯定不会发生。

实际上,页面将始终先完成其 load 事件,然后返回来自 API 的数据。完成所有这些操作后,基于模板的代码会将数据插入到页面中。可以假设这是因为基于模板的代码使用的是 promises (由 .then() 方法指示)。

那么如何解决这个问题呢?您必须等待所需的元素实际存在。我发现最好的方法是使用 MutationObserver 之类的东西。您可以创建一个在页面上使用 Mutation Observer 的函数,并且每当页面内容发生变化时,它都会触发一些代码。您可以在此处检查您的 date 元素是否存在。当它最终存在时,此函数可以返回一个承诺,这允许您现在最终执行一些代码(例如获取所述元素的 textContent )。

因此,请尝试添加类似以下内容:

// This declares the function to wait for an element to exist
const _ElementAwait = el => {
  return new Promise(resolve => {
    if(document.querySelector(el)) return resolve(document.querySelector(el));

    const observer = new MutationObserver(ml => {
      if(document.querySelector(el)) {
        resolve(document.querySelector(el));
        observer.disconnect();
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });
  });
}

// Here we call the function to wait for an element with the class 'date'
_ElementAwait(".date").then(el => {
  // Once it does exist, the element is returned and we can get the textContent
  el.textContent.slice(0, 29);
});
EssXTee
2022-09-26

我刚刚添加了 setTimeout ,它就起作用了。谢谢您的帮助。这是我的新代码:

setTimeout(function(){
  const date = document.querySelector(".date").textContent.slice(0, 29);
  document.querySelector(".date").textContent = "";
  document.querySelector(".date").textContent = date;
}, 1000);

编辑:
我直接在想要执行脚本的页面中用 butter.page.retrieve 替换了 setTimeout (可在 ButterCMS 文档中找到)。检索到页面“simple-page”时,将执行添加我的脚本的代码。这是新代码:

butter.page.retrieve("*", "simple-page").then(() => {
  const createScript = document.createElement("script");
  createScript.src = "../script/post-informations.js";
  document.head.appendChild(createScript);
});
MH info
2022-09-26