简体   繁体   中英

JS code is working in the console but not out of it

I am coding a blog with Nuxt.js, and I am connected with the API of ButterCMS.
I want to get the date (text) of the post, and slice it. My problem is that it return an error: TypeError: null is not an object (evaluating 'document.querySelector(".date").textContent') . When I execute the same code in the JS Console, it is working. I already tried to add a event listener to the load of the page, but it didn't change anything. Here is my code:

 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>

The first thing is to make sure we understand what the error is trying to tell us.

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

Generally when you see something ( like a variable or element ) being labeled as null or undefined that means it does not exist. This could be due to a timing issue ( being called before it is created/ready ) or due to a scope issue ( like a variable being called outside of its declared scope/function ).

Because you are using an API and template-based code, it is almost certainly a timing issue. You did mention you tried adding an event listener to the page load, however this only works if your element/data is set before the page load, which almost certainly does not happen.

Realistically, the page will always complete its load event first, and then data from the API will be returned. And after all of this, then your template-based code will plug in the data to your page. This can be assumed because your template-based code is using promises (indicated by the .then() method).

So how do you fix this? You have to wait for the element you need to actually exists. The best way I found to do this is with something like a MutationObserver . You can create a function that uses a Mutation Observer on the page and whenever the content of the page changes, it fires some code. Here you can check to see if your date element exists or not. When it does finally exists, this function can return a promise, which allows you to now finally execute some code (like getting the textContent of said element).

So try adding something like this:

 // 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); });

I just added a setTimeout and it work. Thank you for your help. Here is my new code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM