I have configured Vite with an alias "#" as "./src".
Using the alias directly as <img>.src is ok:
<!-- this is ok -->
<img src="#/assets/icon-1.svg">
but passing the src as a prop is not working:
<!-- ComponentA -->
<template>
<img :src="imgSrc">
</template>
<!-- Parent Component: alias not resolved as expected; imgSrcWithAlias is "#/assets/icon-1.svg" -->
<component-a :img-src="imgSrcWithAlias" />
Is there any solution to use file path alias when passing props?
Asset URLs must be manually resolved in script with the import keyword:
<script setup>
import imgSrcWithAlias from '#/assets/icon-1.svg'
</script>
<template>
<component-a :img-src="imgSrcWithAlias" />
</template>
demo
#tony19 Answer was what works for me. Using Vue 3 with Vite + TypeScript (Js should work too!) The only difference, is that if aren't using a script with the "setup" attribute: You need to import the image, and return it inside the export default. See:
<script lang="ts">
import { defineComponent } from 'vue'
//Import the images:
import feedImg from './assets/img/feed.png'
export default defineComponent({
setup() {
//Return the imgs:
return {
feedImg
}
}
})
</script>
After that, you just need to bind the image to the prop on the component usage:
<ImageComponent
:imgSrc="feedImg"
alt="Videos on homepage"
/>
And load it on the component itself, binding the src on the img tag:
<template>
<img :alt="alt" :src="imgSrc" />
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
props: {
imgSrc: {
type: String,
required: true
},
alt: {
type: String,
required: true
}
}
})
</script>
Related
The documentation is not enough to be able to do the emit. I have seen many tutorials and nothing works, now I am testing this
Child component
<div #click="$emit('sendjob', Job )"></div>
With the Vue DevTools plugin I can see that the data is sent in the PayLoad, but I can't find a way to receive this emit from the other component.
Many people do this
Any other component
<template>
<div #sendjob="doSomething"></div>
</template>
<script>
export default {
methods:{
doSomething(){
console.log('It works')
}
}
}
</script>
In my case it doesn't work
You should import the child component in the parent component and use it instead of the regular div tag.
I'm sharing examples for your reference to achieve emits in Vue 3 using <script setup> and Composition API. I strongly suggest going with <script setup if you are going to use Composition API in Single File Component. However, the choice is yours.
Example with <script setup>: https://v3.vuejs.org/api/sfc-script-setup.html
<!-- App.vue -->
<template>
<UserDetail #user-detail-submitted="userDetailSubmitted"/>
</template>
<script setup>
import UserDetail from './components/UserDetail';
function userDetailSubmitted(name) {
console.log({ name })
}
</script>
<!-- UserDetail.vue -->
<template>
<input type="text" v-model="name" #keyup.enter="$emit('user-detail-submitted', name)" />
</template>
<script setup>
import { ref } from 'vue';
const name = ref('');
</script>
Example using Composition API: https://v3.vuejs.org/api/composition-api.html
<!-- App.vue -->
<template>
<UserDetail #user-detail-submitted="userDetailSubmitted"/>
</template>
<script>
import UserDetail from "./components/UserDetail";
export default {
components: {
UserDetail,
},
setup() {
function userDetailSubmitted(name) {
console.log({ name });
}
return {
userDetailSubmitted
}
},
};
</script>
<!-- UserDetail.vue -->
<template>
<input type="text" v-model="name" #keyup.enter="$emit('user-detail-submitted', name)" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const name = ref('');
return {
name,
}
}
}
</script>
You should import this child-component in the parent. And don't rename it to the html's original tag.vue3. You'd better use the Composition API.
Using nuxtjs/svg package, I'm conditionally rendering inline SVGs thus:
<ArrowRight v-if="condition" />
<ExternalLink v-else />
Script:
import ArrowRight from '~/assets/img/arrow-right.svg?inline'
import ExternalLink from '~/assets/img/external-link.svg?inline'
export default {
components: {
ArrowRight,
ExternalLink
}
}
I'd like to make these imports dynamically, but I don't know how in this case partly because of the necessity of the "?inline" part when importing the SVG.
Any idea as to how I can import the SVGs dynamically?
<template>
<div v-html="require(`~/assets/img/${image}.svg?raw`)"/>
</template>
<script>
export default {
computed: {
image() {
return condition ? 'arrow-right' : 'external-link'
}
}
}
</script>
That's one way by using SVGs as raw. But the idea should be clear ;-)
(copied from nuxt svg module readme)
To dynamically import an SVG, you can use the inline require() syntax.
<template>
<div v-html="require(`../assets/${name}.svg?raw`)" />
</template>
<script>
export default {
props: {
name: { type: String, default: "image" },
},
};
</script>
To render an SVG without wrapper element and the use of v-html, a combination of dynamic components and ?inline can be used.
<template>
<component :is="require(`../assets/${name}.svg?inline`)" />
</template>
<script>
export default {
props: {
name: { type: String, default: "image" },
},
};
</script>
Please see this minimum example, I have a simple component called HelloWorld.vue
HelloWorld.vue
<template>
<div class="foo">bar</div>
</template>
When I using this component like this
App.vue
<template>
<HelloWorld />
</template>
<script>
import HelloWorld from "./HelloWorld.vue";
export default {
components: {
HelloWorld,
},
};
</script>
This rendered HTML looks like this
Rendered HTML
<div class="foo">bar</div>
However, when I add :is prop, rendered HTML changed
App.vue
<template>
<HelloWorld is="h2" />
</template>
<script>
import HelloWorld from "./HelloWorld.vue";
export default {
components: {
HelloWorld,
},
};
</script>
Rendered HTML
<h2></h2>
Why is this happening?
Is it possible to overwrite only the outer HTML tag just like the class and style prop?
is should be used together with the component element:
<component is="h2"></component>
<HelloWorld is="h2" /> efficiently renders h2 instead of HelloWorld.
In order for root element to be configurable, the component should provide this:
<template>
<component :is="tag" class="foo">bar</div>
</template>
<script>
export default {
props: {
tag: {
type: String,
default: 'div'
}
}
}
</script>
So I will have an array for X length. I have no clue how many components will be included. How do I import them, can I loop over the array and import them, or use v-bind:is?
Any help is welcome!
Thanks,
Justin.
<template>
<div id="app">
<component v-for="(componentName, index) in this.components" v-bind:is="componentName" />
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'app',
// Import just the ones I need
}
</script>
You can include an i when you have no idea how many will be included
<component v-for="i in this.components" v-bind:is="componentName" />
</div>
then for the js
export default {
name: 'app',
data: function() {
return {
this: {id: 1, name: ''}
}
}
Using Vue.js I have this in my /Component/App.vue
import Vue from 'vue';
import VueFusionCharts from 'vue-fusioncharts';
import FusionCharts from 'fusioncharts';
import Column2D from 'fusioncharts/fusioncharts.charts';
import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion';
Vue.use(VueFusionCharts, FusionCharts, Column2D, FusionTheme);
export default {
name: 'app',
data () {
return {
}
}
<template>
<div id="appp">
<div id="chart-container">
</div>
</div>
</template>
In my js/examplevue.js Script I have
Vue.component('Chart', require('./components/App.vue'));
var app = new Vue({
el: '#app',
});
Then in my balde i have :
<div class=" " id="app">
<Chart>.</Chart>
</div>
<script src="{{ asset('js/examplevue.js') }}"></script>
I catch the error : Require is not defined. in Exemple.js
Usually, my vuejs code is working until i try to integer a component.
It looks like your App.vue file is malformed and there are two other errors:
in your template, the div id is mispelled as "appp" instead of "app" as defined in your examplevue.js file
I also noticed you were missing a closing } on your export default statement
If you want to use a <template> tag section you must also enclose all of your Javascript in <script> tags (see code below). :
/Component/App.vue
<template>
<div id="app">
<div id="chart-container">
</div>
</div>
</template>
<script>
import Vue from 'vue';
import VueFusionCharts from 'vue-fusioncharts';
import FusionCharts from 'fusioncharts';
import Column2D from 'fusioncharts/fusioncharts.charts';
import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion';
Vue.use(VueFusionCharts, FusionCharts, Column2D, FusionTheme);
export default {
name: 'app',
data () {
return {}
}
}
</script>
you may also have to put the following code in your examplevue.js file
import Vue from 'vue';
in order to create a new Vue instance.
Hope that helps!