3

I'm creating a basic app in vue that uses axios to make a get request to grab html data from a blog site and using the cheerio node package to scrape the site for elements such as blog title and the date posted of each blog articles. However, I'm having trouble trying to render the scraped elements into the html. Here's the code:

<template>
  <div class="card">
    <div 
      v-for="result in results"
      :key="result.id" 
      class="card-body">
      <h5 class="card-title">{{ result.title }}</h5>
      <h6 class="card-subtitle mb-2 text-muted">{{ result.datePosted }}</h6>
    </div>
  </div>
</template>

<script>
const Vue = require('vue')
const axios = require('axios')
const cheerio = require('cheerio')
const URL = 'https://someblogsite.com'

export default {
  data() {
    return {
      results: []
    }
  },
  mounted: function() {
    this.loadBlogs()
  },
  methods: {
    loadBlogs: function() {
      axios
        .get(URL)
        .then(({ data }) => {
          const $ = cheerio.load(data)
          let results = this
          $('.post').each((i, element) => {
            const title = $(element)
              .children('.content-inner')
              .children('.post-header')
              .children('.post-title')
              .children('a')
              .text()
            const datePosted = $(element)
              .children('.content-inner')
              .children('.post-header')
              .children('.post-meta')
              .children('.posted-on')
              .children('a')
              .children('.published')
              .text()
            this.results[i] = {
              id: i + 1,
              title: title,
              datePosted: datePosted
            }
          })
        })
        .catch(console.error)
    }
  }
}
</script>

I tried declaring

let results = this

before the axios request to refer to the scope within export default, but still getting the indicator from VS Code that the scope is still within the loadBlogs function. Am I missing something? I greatly appreciate the help! Thanks!

1 Answer 1

1

I think your problem is that you're trying to set Property of an results array so Vue can't pick your data update. Instead you should construct new array from your parsed page and set it as this.results = newResultsArray:

loadBlogs: function() {
    axios.get(URL).then(({data}) => {
        const $ = cheerio.load(data)
        const newResults = $('.post').map((i, element) => {
            const title = $(element).children('.content-inner .post-header .post-title a').text()
            const datePosted = $(element).children('.content-inner .post-header .post-meta .posted-on a .published').text()
            return {
                id: i + 1,
                title: title,
                datePosted: datePosted
            }
        })//.toArray() // this toArray call might be needed, I haven't worked with cheerio for some time and not sure whether it returns array or its own collection type like jQuery does
        this.results = newResults;
    }).catch(console.error)
}

Also it should be even simpler if you just use this.results.push({...}) instead of property assignment this.results[i] = {...} (but it is usually easier to handle whole arrays instead of inserting and removing parts of them, both are viable solutions in their respective use cases, though).

And please check out this documentation article about how Vue handles reactive updates, it describes the problem you've encountered.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.