6
votes

I am currently trying to learn vue and struggling with the whole component concept.

Let's say I have some components that define tabs(like browser tabs).

This component has a prop called name.

So you'd maybe use the component like so:

<tab :name="tab.display_name"></tab>

However lets say things need to be a bit more complex. Like for example, you don't just want the name to be a string, but regular HTML. Okay, so, you can use the prop in a v-html directive and use the tab component like this:

<tab :name="'<span class=\'fancy-styling\'>' + tab.display_name + '</span>'"></tab>

This one took me a while to figure out because of all the quotes. Is there a way to escape this escape hell(pun totally intended)?

How could I take it this out into its own snippet/template?

And what if we make it even more complex - say we require the prop be a vue component?

<tab :name="'<my-custom-component @click="onClick()">' + tab.display_name + '</my-custom-component>'"></tab>

The last one is invalid on a number of levels, not the least of which being the mess of quotes.

How would I accomplish this? What is the best approach?

2
<tab :name=`<span class="fancy-styling">${tab.display_name}</span>`></tab> Use ES6 template literals which have been created to solve the escaping and concatenation hell.connexo
I am using webpack and es6 in general(not sure which preset), and this fails to compile. The following however works: <tab :name="`<span class='fancy-styling'>${tab.display_name}</span>`"></tab> So I would not say this is escaping any hell, merely delaying the problem.martixy
Yeah, accidentally removed the outer quotes.connexo

2 Answers

7
votes

If you are trying to inject html in props, you should really be looking at using slots.

https://vuejs.org/v2/guide/components-slots.html

1
votes

The whole point of using components is that you create a separation of concerns. Defining all the layered components in a single line completely defeats that purpose. Create three separate components. One container component like this.

index.vue

<template>
    <tab :name="mycoolname"></tab>
</template>
<script>
    import tab from tab.vue
    export default {
        components: {
            tab
        }
</script>

The name prop you can than use in that template using {{name}}. Than within the tab component, like this:

tab.vue

<template>
    <h1>{{name}}</h1>
    <my-custom-component @click="doStuff()"></my-custom-component>
</template>
<script>
    import my-custom-component from my-custom-component.vue
    export default {
        props: [
            'name'
        ],
        components: {
            my-custom-component
        },
        methods: {
            doStuff () {
                console.log('hooray this totally works')
            }
</script>

I am using separate build files here, but the concept remains the same when you just import vue into your project. Components can contain everything, from a simple div with a <p> inside to a full page. This component system is insanely powerful to keep things organised.

Without webpack it would look something like this:

var myCustomComponent = { 
    template: `fancyHTML`
}

var Tab= {
    components: {
        'my-custom-component': myCustomComponent 
    },
    template: `even more fancy html containing <my-custom-component>`

new Vue({
   el: '#app'
   components: {
      'tab': Tab
    }
})

}