I am fairly new to Vue, so if what I am doing is absurd, please let me know.
A common convention in many of my components is something like this (only showing relevant parts of code):
thing = {text:"some text", href: "https://a.link"}
<template>
<div>
<a v-if="thing.href" :href="thing.href">{{thing.text}}</a>
<span v-else>{{thing.text}}</span>
</div>
</template>
I dislike this as thing.text
may in actuality be a lot of stuff (not just text).
Further, I dislike the redundancy for rendering the anchor tag i.e. if there is an href
be an anchor tag with an href
.
Thus I would like to shorten and clean this up like so:
<template>
<div>
<div :is="complexThing.href ? 'a' : 'span'" :href="complexThing.href">{{complexThing.lotsOfStuff}}</div>
</div>
</template>
Which is nice, we are down to one line, but at the cost of href
being bound to nothing when it doesn’t exist…
So is there a way to conditionally bind a prop?
Of course I could wrap this convention into a component of its own. However, I find that what it is, is very dependent on the component I am using it in. I do not like having to copy and paste a chunk of identical code between an if-else statement just to get an href.
Thoughts? Ideas?
e.g.
<template>
<div :is="href ? 'a' : or" :href="href">
<!-- href=(unknown) will show in inspector if href is undefined -->
<slot></slot>
</div>
</template>
<script>
export default {
name: 'AnchorOr',
props: ['or', 'href']
}
</script>
<style>
</style>
which can then be used like:
<AnchorOr class="inline-text" :or="span">{{text}}</AnchorOr>
<AnchorOr class="linked-module" :or="div">{{component}}</AnchorOr>
Advertisement
Answer
In your small example, I would leave it as-is; however if {{ thing.text }}
were instead a larger template partial then duplicating it is a no-no.
You would normally use <component>
for situations like this:
<component v-bind="thingProps">{{ thing.text }}</component>
computed: {
thingProps() {
return this.thing.href
? { is: 'a', href: this.thing.href }
: { is: 'span' };
}
}