I've got a small problem (or maybe it's intended and I just don't know how it should work).
I've got parent component - App.vue
<script setup>
import AboutMe from "./components/AboutMe.vue";
</script>
<template>
<AboutMe username="Andrew" />
</template>
Child component AboutMe.vue
<script setup>
defineProps(["username"]);
</script>
<template>
<div class="container">
<div>Name: {{ username }}</div>
</div>
</template>
Now when I try to add some props:
App.vue:
<AboutMe username="Andrew" age="30" />
AboutMe.vue
<script setup>
defineProps(["username", "age"]);
</script>
<template>
<div class="container">
<div>Name: {{ username }}</div>
<div>Age: {{ age }}</div>
</div>
</template>
I see only 'Age: ', need to manually reload to see 'Age: 30'.
I'm using latest Vite but it's the same on the latest Vue CLI.
Not sure why but using Vitesse Framework it works great.
Vue Chrome Dev Tools shows 'age' as attr, not prop until reload.
Tried without but no luck.
Thanks in advance for any help.
It seems that the bug was reported and fixed by Evan from 3.0.0-beta.11
3.0.0-beta.11 (2020-05-11)
Bug Fixes
hmr: always force full child component props update in HMR mode (1b946c8)
Related
I am facing a problem of "defineProps is not defined". I am not sure why is this not working where the code below actually works
const props = defineProps({
time:Number
})
App.vue
<script setup>
import Bomb from './Bomb.vue'
</script>
<template>
<Bomb :time="4" />
</template>
Bomb.vue
<script setup>
const props = defineProps(['time'])
</script>
<template>
<div>
{{props.time}}
</div>
</template>
Assuming the Bomb.vue's snippet "defneProps" is a typo, it's also a known false-positive warning from eslint-plugin-vue.
https://eslint.vuejs.org/user-guide/#compiler-macros-such-as-defineprops-and-defineemits-generate-no-undef-warnings
The official solution is to install and use vue-eslint-parser
What is the difference between these two components in Nuxt3 and how do I use them correctly?
If I want to use pages/... what is the right approach here to create links and jump from page to page?
Everything is pretty much explained in the documentation: https://v3.nuxtjs.org/migration/pages-and-layouts/
You need to use this in app.vue
<template>
<nuxt-layout>
<nuxt-page /> <!-- used to display the nested pages -->
</nuxt-layout>
</template>
With a default /layouts/default.vue file
<template>
<div>
this is coming from the layout
<slot /> <!-- required here only -->
</div>
</template>
You will get this on / (with /pages/index.vue)
<template>
<div>index page</div>
</template>
And with the following structure, you will achieve dynamic pages
/pages/users/index.vue
<script setup>
definePageMeta({
layout: false
});
function goToDynamicUser() {
return navigateTo({
name: 'users-id',
params: {
id: 23
}
})
}
</script>
<template>
<div>
<p>
index page
</p>
<button #click="goToDynamicUser">navigate to user 23</button>
</div>
</template>
/pages/users/[id].vue
<script setup>
definePageMeta({
layout: false
});
const route = useRoute()
</script>
<template>
<pre>{{ route.params.id }}</pre>
</template>
I've removed the layout here to show how to disable it, but you can totally let the default here or even provide a custom one.
So, nuxt-page is to be used when you want to display the pages in your app (replacing <nuxt /> and <nuxt-child />) while <slot /> is to be used in the layout (as any other component using the slot tag).
I just got started to Vue and i'm trying to understand some basic concepts such as conditional rendering and how to pass data from where i load the app to a component. Suppose i'm rendering a Vue component like this:
<div id="app">
<myComponent></myComponent>
</div>
Suppose myComponent looks like this:
<template>
<div>
<h1>First block</h1>
</h1>Second block</h1>
</div>
</template>
I want to be able to render First block or Second block when i load the Vue app according to a parameter i pass to the component, like:
<div id="app">
<myComponent id="first"></myComponent>
</div>
In this case i should see First block, whereas if instead of id="first" there was id="second" the output was supposed to be Second block. How can i do this?
I know it's a very basic question, but most of the sources i found explained how to do the opposite. Any kind of advice is appreciated!
In vue you could pass props (parameters) to component which defines this ones in its script like :
<template>
<div>
<h1 v-if="block==='first'">First block</h1>
</h1 v-else>Second block</h1>
</div>
</template>
<script>
export default{
props:{
block:{
type:String,
default:'first'
}
}
}
</script>
in parent component pass the prop like :
<div id="app">
<myComponent block="first"></myComponent>
</div>
or
<div id="app">
<myComponent block="second"></myComponent>
</div>
Initially, I am fetching data from api in the created hook which is perfectly working.
created() {
this.fetchInformation()
}
But I was having look over best practices for lifecycle hooks and I came to this line You need to fetch some data for your component on initialization. Use created (or created + activated for keep-alive components)
I also tried to look for relevant articles or information on the internet.
Url for reference - https://alligator.io/vuejs/component-lifecycle/
My component is rendering inside keep-alive so I tried this for the test purpose.
activated() {
this.fetchInformation()
}
Instead of created, now as expected everytime the component activates it execute the api call which is really cool. But I still want to understand what this actually created + activated as I am using activated or created but if I am correct just by reading that I should do them both.
Please let me know if anything else required to understand my question.
Thanks
Use correctly keep-alive!!
Incorrect:
<template>
<div>
<div v-if="canRender">
<keep-alive>
<my-component />
</keep-alive>
</div>
</div>
<template>
Incorrect:
<template>
<div>
<keep-alive>
<div v-if="canRender">
<my-component />
</div>
</keep-alive>
</div>
<template>
Correct:
<template>
<div>
<div>
<keep-alive>
<my-component v-if="canRender" />
</keep-alive>
</div>
</div>
<template>
I'm new to Vue.js and I'm having a bit of trouble using components with sub-components. I have the following .vue files
app.vue
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
</section>
</template>
slider.vue
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<div class="slider">
<slot>
Some content
</slot>
</div>
</div>
</template>
<script>
import skin from "./skin";
export default {
components: {
skin: skin
}
};
</script>
skin.vue
<template>
<div v-for="colour in colours">
<div :style="{ backgroundColor: colour }">
<img src="../assets/images/MIA.png"/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
heading: "Choose Skin Tone"
};
}
};
</script>
I'm trying to load the skin sub component into the component. Everything works well except for the skin sub component as it doesn't get compiled. I do not get any compile or vue related errors though. I also wanted to be able to have several instances of the slider component like this
app.vue
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
<slider>
<foo></foo>
</slider>
<slider>
<bar></bar>
</slider>
</section>
</template>
I'm not sure what I am doing wrong.
I'm not 100% sure of what you want to achieve here, but to compile a component inside a component, you need to add the child component inside the parent's template, like this:
Slider.vue (I've simplified the structure):
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<skin></skin>
</div>
</template>
<script>
import skin from './skin'
export default {
components : {
'skin': skin
}
}
</script>
App.vue:
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider></slider>
</section>
</template>
Actually, if you add skin in the app's template inside of adding it in the slider component template, it gets included (and rendered) assuming that its scope is app, not slider. In order to add skin inside slider scope, it needs to be added to slider's template. Check this: https://vuejs.org/guide/components.html#Compilation-Scope
Some other things:
Use a hyphen-separated name for the components, with at least 2 words: <custom-slider> instead of <slider>, for example, following the Web Components API (otherwise it might collide with current or upcoming web components).
Slots are complicated to grasp, so read this carefully: https://vuejs.org/guide/components.html#Content-Distribution-with-Slots
Good luck!
Update:
If you want the slider component to be content agnostic and be able to insert anything you want inside it, you have two options (that I can think of):
Remove all the logic from the slider component and make skin a descendant from app. Then use slots in the slider component, as follows:
Slider.vue:
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<slot></slot>
</div>
</template>
<script>
export default {}
</script>
App.vue:
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
</section>
</template>
<script>
import skin from './skin'
export default {
skin: skin
}
</script>
If you know that the slider will always have a closed set of components inside, you can use dynamic components: https://vuejs.org/guide/components.html#Dynamic-Components
After some research I found this which refers to a is= attribute that will transclude the sub-component template
so in app.vue
<slider-component>
<div is="skin-component" v-for="colour in colours"></div>
</slider-component>
and then add child components