How to fetch JSON data in a Vue SPA? - javascript

I created a sample Vue application via #vue/cli 3.0:
vue create testapp
cd testapp
npm run serve
As part of mounted(), I wanted to fetch some local data:
fetch("users.json")
.then(r => r.json())
.then(r => this.users = r.hits.hits.map(x => x._source))
where users is defined in data().
The response is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>example.com</title>
<link href="/about.js" rel="prefetch"><link href="/app.js" rel="preload" as="script"></head>
<body>
<noscript>
<strong>We're sorry but example.com doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="/app.js"></script></body>
</html>
I tried to move the JSON file to static in the root of the application (at the same level as src, then in assets and then everywhere I could think of - the answer is always the one from the app which assumes that this is a request for HTML/JS/CSS content, and not raw data.
Where should such a static file be placed?

You may assign the JSON into your data at the beginning, try this in your App.vue
<template>
<div>
<div v-for="user in users">{{user}}</div>
</div>
</template>
<script>
import json from './users.json'
export default{
data(){
return{
users: json
}
}
}
</script>
And also make sure your main.js has import App.vue
import Vue from 'vue'
import App from './App'
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
Locate your users.json at the same level as src(which is same with App.vue) is fine.
Hope this may help you! Cheers

Related

vuejs without build production code warning

I am using vuejs to make a simple page. Although I can make similar page without any framework, I wanted to try vuejs and now it it almost production ready.
Thing is it is simply single js and html file and it throws following warning.
You are running a development build of Vue.
Make sure to use the production build (*.prod.js) when deploying for production.
Let's say I want to keep things this way, how do I remove this warning and get single page html and js file?
// main.js
const { createApp } = Vue
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://unpkg.com/vue#3"></script>
<script src="main.js"></script>
</body>
</html>
- index.html
- assets
-- js
--- main.js
-- css
--- styles.css
As suggested by #IVO GELOV, and mentioned in guide here, it is working for me now.
Use below url for production use and to remove the warning.
https://unpkg.com/vue#3/dist/vue.global.prod.js

Error compiling template: Component template requires a root element, rather than just text in vue.js with laravel

I am Learner in Vuejs with laravel, i created a fresh project in laravel, with vue.js frontend. but after run command php artisan serve, when i run project on webbrowser. output is blank. i checked network console, there is also the output showing in example component is blank. please help me to find my mistake.
web.php
Route::get('/', function () {
return view('welcome');
});
welcome.blade.php
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel Vue</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
</head>
<body>
<div id="app">
<example-component> </example-component>
<script src="{{ asset('js/app.js') }}"></script>
</div>
</body>
</html>
ExampleComponent.vue
<script>
Vue.component('example-component', {
template: `This is the homepage`
})
new Vue({
el: '#app'
})
</script>
app.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
require('./bootstrap');
window.Vue = require('vue');
alert('Alert');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('example-component', {
template: `<div id="app">This is the homepage</div>`
})
You have to wrap the template content in a parent element, such as <div> </div>. If not Vue will show an error, explaining that every component must have a single root element.

Using vuejs via es6 modul in index.html without node

I am trying to add a vuejs frontend to my java backend (spring boot) without using node. I created a simple index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hello Test!</title>
</head>
<body>
<h1>test test</h1>
<div id="app"></div>
<script type="module" src="main.js"></script>
</body>
</html>
which is supposed to import the following main.js (located in the same folder) as module:
import Vue from './vue.js'
import {
Navbar
} from './component/navbar.js'
import {
MainTemplate
} from './templates/main-template.js'
new Vue({
el: '#app',
components: {
'navbar': Navbar
},
template: MainTemplate
})
When accessing localhost in either chrome or firefox, I get the header 'test test', but an error saying 'Failed to load resource: the server responded with a status of 404 ()' regarding the main.js.
I have found different tutorials stating that this should be working. Trying out different ways of importing the main.js didn't change the error.
As I really need to get this to work I would really appreciate any tips on that! Thanks in advance!

Import Vue breaks Vue

Can someone explain the WHY of how Import Vue from 'vue' breaks the rendering of the template? I've seen other answers on how to work around this, but none of them have gone into the details of why it breaks.
I ran npm init and npm install vue, not using the CLI.
I created an index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script type="text/javascript" src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<first-task></first-task>
{{msg}}
</div>
<script src="app.js"></script>
</body>
</html>
and an app.js looking like:
import Vue from 'vue/dist/vue.js'; //Remove to fix
Vue.component('first-task', {
template: '<p>Hello World!</p>'
});
var app = new Vue({
el: '#app',
data: {
msg: "Hello World"
}
});
Removing the import, it renders fine, but it's unclear to me why this happens. My only guesses are that the default new Vue doesn't reference the full build, or that the implicit Render() doesn't get called, but I'm unsure of how to look into this more.
import statements may only appear in a javascript module
<script type="module" src="app.js"></script>
Should fix it, though you would not need to import Vue with your current code anyway, as you have seen

Calling method from compiled js file

I seem to be unable to call a method from a JS package from one of my other files (all.js). I am using Laravel 5.4, VueJS2, and VueRouter. This is an SPA where Laravel serves as a backend.
I get the following error: TypeError: $.LoadingOverlay is not a function
I am utilizing web pack and compiling the assets like this:
mix.js([
'resources/assets/js/bootstrap.js',
'resources/assets/js/helpers.js',
'././node_modules/gasparesganga-jquery-loading-overlay/src/loadingoverlay.min.js',
'resources/assets/js/app.js',
'././node_modules/moment/min/moment.min.js',
'././node_modules/moment-duration-format/lib/moment-duration-format.js',
], 'public/js/all.js').version();
The file containing the code I am trying to pull in is the loadingoverlay.min.js file. The file that is referencing it is right underneath it (app.js).
My app.js file:
import Vue from 'vue';
import VueRouter from 'vue-router';
var $ = require('jquery');
Vue.use(VueRouter);
const routes = [
.. routes here
];
const router = new VueRouter({
routes,
mode: 'history',
});
router.beforeEach((to, from, next) => {
console.log('Entering route');
$.LoadingOverlay('show');
next();
});
router.afterEach((to, from) => {
console.log('Entered route');
$.LoadingOverlay('hide');
})
const app = new Vue({
router
}).$mount('#app');
The blade file that is responsible for pulling in the compiled assets:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="author" content="">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<link rel="stylesheet" href="{{ mix('css/all.css') }}">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
</head>
<body>
<div id="app">
<section class="container">
<div>
<router-view></router-view>
</div>
</section>
</div>
<script src="{{ mix('js/all.js') }}"></script>
</body>
</html>
Interestingly enough, I am able to call the method from that file from my blade page by adding <script></script> tags after the all.js file is pulled in, and calling it from there.
Any ideas on why this may be happening?
Exactly as it says, because $.LoadingOverlay is not a function.
The jQuery compiled into your all.js via webpack (done via nodejs) will cause the $ = require('jQuery') to be different than the one globally exposed via window.$
window.$ is referencing jQuery 1.11.0 and the one inside your app.js is referencing the jQuery built with webpack.

Categories