Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js app no errors but white page

I'm trying to learn Vue. I read this tutorial and I'm trying to split it in single file components using the standard vue-cli webpack template. I don't have any error in console but the page is white, and I cannot understand why.

This is my main.js file

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false
window.axios = require('axios');

const NYTBaseUrl = "https://api.nytimes.com/svc/topstories/v2/";
const ApiKey = "18e1540d187c4b46bae767782750f9fd";
const SECTIONS = "home, arts, automobiles, books, business, fashion, food, health, insider, magazine, movies, national, nyregion, obituaries, opinion, politics, realestate, science, sports, sundayreview, technology, theater, tmagazine, travel, upshot, world";

function buildUrl (url) {
  return NYTBaseUrl + url + ".json?api-key=" + ApiKey
}

const vm = new Vue({
  el: '#app',
  data: {
    results: [],
    sections: SECTIONS.split(', '), // create an array of the sections
    section: 'home', // set default section to 'home'
    loading: true,
    title: ''
  },
  mounted () {
    this.getPosts('home');
  },
  methods: {
    getPosts(section) {
      let url = buildUrl(section);
      axios.get(url).then((response) => {
        this.loading = false;
        this.results = response.data.results;
        let title = this.section !== 'home' ? "Top stories in '"+ this.section + "' today" : "Top stories today";
        this.title = title + "(" + response.data.num_results+ ")";
      }).catch((error) => { console.log(error); });
    }
  }
});

And this is the App.vue file

<template>
  <div id="app">
    <h1>Test</h1>
    <product-list></product-list>
  </div>
</template>

<script>
import Products from './components/Products'

export default {
  name: 'app',
  components: {
    Products
  }
}
</script>

<style lang="sass" >
  @import '~bulma/sass/utilities/initial-variables.sass'
  @import "~bulma/sass/utilities/_all"
  @import "~bulma/sass/base/_all"
  @import "~bulma/sass/grid/columns"
  @import "~bulma/sass/components/_all"
</style>

I also create a Products.vue file in the components folder

<template id="product-list">
  <section>
    <div class="row" v-for="posts in processedPosts">
      <div class="columns large-3 medium-6" v-for="post in posts">
        <div class="card">
        <div class="card-divider">
        {{ post.title }}
        </div>
        <a :href="post.url" target="_blank"><img :src="post.image_url"></a>
        <div class="card-section">
          <p>{{ post.abstract }}</p>
        </div>
      </div>
      </div>
    </div>
  </section>

</template>

Vue.component('Products', {
  props: ['results'],
  template: "#product-list",
  computed: {
    processedPosts() {
      let posts = this.results;

      // Add image_url attribute
      posts.map(post => {
        let imgObj = post.multimedia.find(media => media.format === "superJumbo");
        post.image_url = imgObj ? imgObj.url : "http://placehold.it/300x200?text=N/A";
      });

      // Put Array into Chunks
      let i, j, chunkedArray = [],
        chunk = 4;
      for (i = 0, j = 0; i < posts.length; i += chunk, j++) {
        chunkedArray[j] = posts.slice(i, i + chunk);
      }
      return chunkedArray;
    }
  }
});

Everything looks fine for me (except for the window.axios = require('axios'); that I don't understand why is not present in the original tutorial) but the page is blank and also the tag I add for debug is not present in the DOM.

Edit

Looks like the code is not compiled.

My page source code is

<body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  <script type="text/javascript" src="/app.js"></script>

</body>

** Edit 2 **

I understand the problem. This is my index.html.

like image 425
Roberto Pezzali Avatar asked Jul 06 '17 07:07

Roberto Pezzali


People also ask

How do I check my Vue app performance?

Then use the “Performance tab” to measure your Vue app's performance. Press start and stop to run a performance check, ideally during the app load. And then go to the “Component Render” tab. If your page renders 100 components, then you should see 100 created events.

Is Vue single page app?

This type of application is typically referred to as a Single-Page Application (SPA). Vue provides core libraries and comprehensive tooling support with amazing developer experience for building modern SPAs, including: Client-side router. Blazing fast build tool chain.

Does Vue need to be compiled?

Does it need to be compiled? If you want to use Vue without compiling, you can add it to an HTML document using a <script> tag. This will register Vue as a global variable. But you'll then need to compile it with your other code using a build tool like Webpack.


1 Answers

There are several issues with your codes. First you have to wrap JavaScript in a script tag on your Products.vue file. Also on your Products.vue file you could just export the component files instead of creating the way you did, also you haven't imported Vue on Products.vue file but you are using it Vue.component('Products', {}). You should create Products.vue file this way

Products.vue

<template>
  <section>
    <div class="container" v-for="posts in processedPosts">
      <div class="columns" v-for="post in posts">
        <div class="column is-6 is-offset-3">
           <div class="card">
           <header class="card-header">
             <p class="card-header-title">
            {{ post.title }}
            </p>
           </header>
           <div class="card-image">
           <a :href="post.url" target="_blank">
             <figure class="image">
               <img :src="post.image_url">
             </figure>
           </a>
           </div>

        <div class="card-content">
          <div class="content">
            <p>{{ post.abstract }}</p>
          </div>
        </div>
      </div>
        </div>
      </div>
    </div>
  </section>

</template>
<script>
export default{
  props: ['results'],
  computed: {
    processedPosts() {
      let posts = this.results;
      // Add image_url attribute
      posts.map(post => {
        let imgObj = post.multimedia.find(media => media.format === "superJumbo");
        post.image_url = imgObj ? imgObj.url : "http://placehold.it/300x200?text=N/A";
      });

      // Put Array into Chunks
      let i, j, chunkedArray = [],
        chunk = 4;
      for (i = 0, j = 0; i < posts.length; i += chunk, j++) {
        chunkedArray[j] = posts.slice(i, i + chunk);
      }
      return chunkedArray;
    }
  }  
}
</script>

On your main.js file you forgot to mount <App /> template.

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
})

You should also move code for network request, components to App.vue file.

main.js

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false
window.axios = require('axios');

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
})

Have to use the component we are importing, on your code you imported Products but using <product-list></product-list>.

App.vue

<template>
  <div id="app">
    <products :results="results"></products>
  </div>
</template>

<script>
import Products from './components/Products'

const NYTBaseUrl = "https://api.nytimes.com/svc/topstories/v2/";
const ApiKey = "18e1540d187c4b46bae767782750f9fd";
const SECTIONS = "home, arts, automobiles, books, business, fashion, food, health, insider, magazine, movies, national, nyregion, obituaries, opinion, politics, realestate, science, sports, sundayreview, technology, theater, tmagazine, travel, upshot, world";

function buildUrl (url) {
  return NYTBaseUrl + url + ".json?api-key=" + ApiKey
}

export default {
  name: 'app',
  data: function(){
    return {
    results: [],
    sections: SECTIONS.split(', '), // create an array of the sections
    section: 'home', // set default section to 'home'
    loading: true,
    title: ''
    }
  },
  components: {
    Products
  },
  mounted(){
    this.getPosts('home');
  },
  methods:{
    getPosts(section) {
      let url = buildUrl(section);
      axios.get(url).then((response) => {
        this.loading = false;
        this.results = response.data.results;
        let title = this.section !== 'home' ? "Top stories in '"+ this.section + "' today" : "Top stories today";
        this.title = title + "(" + response.data.num_results+ ")";
      }).catch((error) => { console.log(error); });
    }    
  }
}
</script>

I tested this out, and uploaded code to github https://github.com/azs06/vuejs-news, you can clone it and check it out. Here it is deployed http://noisy-coach.surge.sh/

Note: I am using the api key temporarily will remove it, as soon as you test it out.

like image 81
azs06 Avatar answered Oct 05 '22 06:10

azs06