【问题标题】:JS code is working in the console but not out of itJS 代码在控制台中运行,但不在控制台中
【发布时间】:2022-09-28 20:20:22
【问题描述】:

我正在用 Nuxt.js 编写一个博客,并且连接到 ButterCMS 的 API。
我想获取帖子的日期(文本),然后对其进行切片。我的问题是它返回一个错误:TypeError: null is not an object (evaluating \'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>
  • 日期可能是从 API 调用或您的依赖项的 js 中加载的,并且您的代码可能在实际加载日期之前执行。在 Chrome 开发工具的网络选项卡中,您可以查看日期是否从 API 调用中加载。
  • 您将document.querySelector(\".date\").textContent.slice(0, 29); 放在该代码的哪个位置?这听起来很像 Why does jQuery or a DOM method such as getElementById not find the element? 的复制品
  • 这段代码看起来像您正在使用 Vue.js。你确定吗?
  • 您根本不应该使用document.querySelector 来访问日期!只需使用this.posts[0].published

标签: javascript


【解决方案1】:

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

TypeError:null 不是对象(评估'document.querySelector(".date").textContent')

通常当你看到一些东西时(像变量或元素) 被标记为nullundefined 这意味着它不存在。这可能是由于时间问题(在创建/准备好之前被调用) 或由于范围问题 (就像一个变量在其声明的范围/函数之外被调用)。

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

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

那么你如何解决这个问题?您必须等待您需要的元素实际存在。我发现最好的方法是使用MutationObserver 之类的东西。您可以创建一个使用突变观察者在页面上,每当页面内容发生变化时,它都会触发一些代码。在这里你可以检查你的日期元素存在与否。当它最终存在时,这个函数可以返回一个承诺,它允许你现在最终执行一些代码(比如获取所述元素的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);
});

【讨论】:

  • "您必须等待您需要的元素实际存在。“ - 是的。 ”我发现做到这一点的最好方法是使用 MutationObserver 之类的东西。“ - 不。您使用突变观察者是一些您无法控制的代码确实会更改 dom。但是 OP 正在对网站本身进行编码。他们应该将他们的代码放在创建元素的位置
【解决方案2】:

我刚刚添加了一个setTimeout,它可以工作。谢谢您的帮助。这是我的新代码:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多