everyone. I've got a little node.js project with vue.js and I'd like to use a config packet (npm i config) in it. But when I add config to the vue.js component
import configData from config
and try to use one in the vue.js component
data: () => { config: configData }
I've got an exception when I make a request to the page. In the browser console appear:
Uncaught Error: Config file /config/runtime.json cannot be read. Error code is: undefined. Error message is: v.readFileSync is not a function
So I'd like to understand what's wrong with this config packet in vue.js. Is there a way to pass config data to the Vue component? Thanks a lot in advance
I created /config/default.json that contains the data I need, but when I try to pass it into my vue.js component the component page fall
data is a method that should return some variables. There is a mistake in your code. arrow functions works like this
if you want to return an empty object
data: () => ({})
If you want to call some method inside of it
func: () => {
someMethod();
anotherMethod();
}
And you can't write
data: () => { config: configData }
this is a mistake. You should put braces around your curly braces
Related
I would like to check if there's anyone that could show a implementation of a component that is included from a route page (+page.svelte) where the component itself is responsible for fetching the data and handling that trough an endpoint specific to that component.
Previously I have included the data into the component and fetched it in parent component but I guess it must be possible for the component itself to fetch the data.
The aim is for example to have implementation inside the component itself like
<Mycomponent>
instead of
<Mycomponent {myArray}>
I we take this code snippet as an example. This is similar to what I do but I need to use POST method API fetch call.
<script lang="ts">
async function getDataFromAPI() {
const body = {
action: 'search',
};
const res = await fetch('https://externalAPI.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
const values = await res.json();
return values;
}
let promise = getDataFromAPI();
</script>
{#await promise }
<p>...waiting</p>
{:then data}
<p>{data.length} my data </p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
The problem seems to be that in my case data is undefined even if when I console.log(values) in this case there's the correct data information.
So I end up in the catch error case and get error 'Failed to fetch'.
It's definitely possible. Basically, two ways to go about it. First is to do the fetch (or call a function imported from somewhere else that does the fetch) in the script tag of the +page.svelte file you want to use it in, and then refer to the variable you stored the fetched data in within the template.
The other way to do it moves the fetch into a separate file. I'm not sure of the pros and cons of this, as I'm still fairly new to svelte myself.
You want to create a +page.js/+page.ts file with an exported load function that fetches the needed data and returns the data in an object.
Then, in your +page.svelte file, you export a variable named data. The data variable will contain the object that your load function returned.
When I get the chance, I'll hack up a quick demonstration and include the code here.
This is my first attempt at building a web app with Vuejs. I've been trying to get data from an external JSON API and display it on my app. The JSON fetch etc is working fine. but I can't get the data to be displayed reactively on my component.
As you can read in Appraisal.js given an API link some data is populated in Appraisal.app_data. The data always has an array called items (that's just how the API is. I'll add validation later). As a proof of concept I'm trying to display the number of elements in the items array.
Since other components in my app will also use this data, I'm using an external store as the data source everywhere. One of the components calls Appraisal.setLink() on getting some user input. That part is working as expected. However the DOM contents don't change at all.
I referred to State Management for setting up the external store. I also referred to some other answers on StackOverflow with a similar issue and got the following suggestions:
The data should be initialized to undefined or null instead of {} for reactivity to work.
Properties of objects are not reactive. But by my understanding this was changed in Vue3 where it doesn't matter because proxies are in use. Either way I tried using the Object.assign({}, ..., ...) method but it did not help.
Arrow functions cannot be used in methods for reactive objects. If I remove the arrow function and put the body inside .then(function(data) {...}) it complains that this is not defined for the second then function on fetch
// --- src/components/AppraisalView.vue
<script setup>
import ItemView from './ItemView.vue';
</script>
<template>
<div v-if="app_data">{{app_data.items.length}} items in appraisal</div>
<div v-else>Enter link to get quote</div>
</template>
<script>
import {Appraisal} from '../stores/Appraisal.js';
export default {
data() {
return {
app_data: Appraisal.app_data,
}
},
}
</script>
// ---- src/store/Appraisal.js
import {reactive} from 'vue'
import {BuybackCalculator} from './BuybackCalculator.js';
export const Appraisal = reactive({
link: '',
app_data: undefined,
methods: {
setLink(value) {
if (this.link == value) return;
this.link = value;
console.log('Updating appraisal with: '+this.link);
fetch(this.link+".json")
.then((response) => response.json())
.then((data) => {
this.app_data = data;
console.log(this.app_data);
BuybackCalculator.methods.calculate_buyback(this.app_data);
});
}
}
});
I am using Vue.js and Laravel for my project and recently added two animations using a plugin named Lottie. Each animation is a component, and they both use an individual JSON file to animate a group of PNG images (similar to a PNG sequence). These two JSON files are stored locally in the project folder under the path /public/data/.
Firstly the JSON files are not being read unless I put in the absolute path (/users/username/documents/projectname/public/data/filename.json), is there no way I can get this to work just by using /data/filename.json?
Secondly, when I add the code below in my component, my JS files are compiled to separate chunks as expected:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
I get the following error when the animation tries to run:
Invalid prop: type check failed for prop "data". Expected Object, got Function
found in
---> <VueLottie>
However when I import my json file using a normal import in my component like below it works fine and shows the animation:
import animationData from "/users/username/documents/projectname/public/data/filename.json";
My animation components are both set up like this:
<template>
<vue-lottie ref="lottie" loop autoplay :data="animationData" :height="400" :width="400"></vue-lottie>
</template>
<script>
import vueLottie from "vue-lottie-ssr";
import animationData from '/users/username/documents/projectname/public/data/filename.json'
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData
}
},
computed: {
lottie () {
return this.$refs.lottie
}
}
}
</script>
I have also tried getting the JSON file via an axios call when the component mounts, but the same error occurs.
Update
I updated my code so that each component is lazy loaded instead of the JSON file. Like so:
components: {
WinAnimation: () => import("./WinAnimation.vue");
LoseAnimation: () => import("./LoseAnimation.vue");
}
However now I'm getting the following error:
Unknown custom element: <win-animation> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Update 2
I realised why I was getting an error message. The correct way was to add the following at the top of my script inside the parent vue file.
const winAnimation = () => import("./WinAnimation.vue");
const loseAnimation = () => import("./LoseAnimation.vue");
and then inside export default {...} I forgot to add the names, so:
components: { winAnimation, loseAnimation }
Now my code has been split and my app.js file size has reduced by almost a half! :)
1st - don't use vue-lottie library. If you take a look at the source code, the main and only thing which should be provided by this library is component src/lottie.vue (+ it's dependency lottie-web) but for some reason, NPM package also contains whole demo app including the demo JSON file (src/assets/pinjump.json)
If you take a look at lottie.vue component, its just very little and very simple wrapper for lottie-web which provides main functionality. By getting rid of vue-lottie you will get following benefits:
vue-lottie completely ignores one of the lottie-web options which is using path instead of animationData - documentation is not very clear here but I would guess that by providing path, the library will try download the animation data ad-hoc so you don't need to include it in your bundle. Worth trying imho...
Loading animation data on demand
why are you using dynamic import on JSON file instead of dynamically importing whole component ? By making separate chunk on component level, dynamic chunk will include not only your json data but also lottie-web which is also not small. And Vue will handle loading of the component without any additional code changes...
if you still want to load on demand only your JSON data, you must understand that Webpack dynamic import (import(".....")) is returning Promise and lottie-web (and in turn vue-lottie) is expecting object. So you must do something like this:
<script>
import lottie from 'lottie-web';
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
export default {
mounted () {
animationData().then(function(data) {
this.anim = lottie.loadAnimation({
// other options
animationData: data
})
});
}
}
</script>
Update
You should be always very careful when considering adding 3rd party components into your project. One more thing I'v noticed is that lottie-web has destroy() method in it's API. This indicates that it is creating some resources (DOM elements probably) which needs to be cleaned up. This is something vue-lottie component is not handling at all and can lead to nasty memory leaks in your app. You can read about the problem here
When the animationData property is set it is a function, hence the line:
Expected Object, got Function
It needs an object, not a function.
The function being:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
When defining the animationData property you need to set an object as its value. Then when mounting fetch the data (or use Axios if you prefer that) to update the animationData property on the component.
N.B. I have never used Vue, so I hope that what I am saying is correct.
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData: {}
}
},
computed: {
lottie () {
return this.$refs.lottie
}
},
mounted() {
fetch('/users/username/documents/projectname/public/data/filename.json')
.then(response => response.json())
.then(json => this.animationData = json;);
)
}
}
I am using vue for front end development, and I have the following script:
<script>
import PostService from '../PostService';
export default {
name: 'Post',
data: function() {
return {
posts: [],
text: ''
};
},
methods: {
async CreatePost() {
await PostService.CreatePost(this.text);
this.post = await PostService.GetPosts(); **//How to get error here?**
}
}
};
</script>
the problem is I keep misspelling things (like post instead of posts), but vue is not displaying any sort of error/warning, how can I get vue to detect this?
yeah, this is the tricky part and I believe there is no way to detect it.
Only solution I see is to use Vue.js with TypeScript, that will help to catch a lot of errors early and significantly improve quaity of your code in application.
This is more of an editor function I think. I use VSCode so I can only speak to that, but if you do as well I use the Vetur extension and I've been very happy with it.
so I want to make a global function that I can access in every component of mine. So I stumbled upon Vue Plugins. They worked great, till I tried out my use case. I need to use some information from the vuex store in my plugin and return a true or false value.
So this is what I have tried
plugin.js
export default {
install (Vue) {
Vue.prototype.$rbac = (method, route) => {
$store.state.generic.user.routes.some(m => m.method.includes(method) && m.route==route)
}
}
}
main.js
import plugin from './utils/common/plugin'
...
Vue.use(plugin)
...
component.vue
<template>
...
<div v-if="$plug('post', '/project')></div>
...
</template>
But I get an error saying "ReferenceError: $store is not defined".
It kind of makes sense that I cannot access the store. The store only gets the value once the user logs in.
So is there any way I can make a global function that can access the store when it gets values?
You're getting the reference error because the $store variable hasn't been defined anywhere. It's not a local variable, nor is it a function parameter or global variable.
You probably meant to do this.$store; also make sure you use function () {} syntax and not () => {} because you don't want to bind this.
export default {
install(Vue) {
Vue.prototype.$rbac = function (method, route) {
this.$store.state.generic.user.routes.some(m => m.method.includes(method) && m.route == route)
}
}
}
You could also use a global mixin to do a similar thing instead of a plugin.