JS 代码在控制台中可以运行,但在控制台之外则不行
我正在使用 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>
∙
<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 →</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>
首先要确保我们理解错误试图告诉我们什么。
TypeError: null is not an object (evaluating 'document.querySelector(".date").textContent')
通常,当您看到某些内容(
如变量或元素
)被标记为
null
或
undefined
时,这意味着它不存在。这可能是由于时间问题(
在创建/准备就绪之前被调用
)或由于范围问题(
如在其声明的范围/函数之外调用变量
)。
由于您使用的是 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);
});
我刚刚添加了
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);
});