3 Reasons to use components in VuePress markdown

In my last post, I covered some of the fun things you can do in markdown that take advantage the way VuePress converts content into Vue templates, but I saved the best for this post. In VuePress, you can use Vue components directly inside your .md files, like so:

<MyComponent />

In this post I will demo 3 use cases for components in markdown, but first, what would you rather see in my examples?

# 1. Reusing content

The most common reason for using components in your content is simply reusability.

For example, you have a newsletter subscription form that you want to be able to place anywhere in your content, you don't want to have to paste the entire embed code into your .md file every time.

Here's how I do it. In my .vuepress/components folder I have a SubscribeForm.vue file which looks a bit like this:

<template>
    <!-- Form html from your newsletter service, for example: -->
    <form method="post" action="...">
        <h3>Join my mailing list</h3>
        <label>Email <input type="email" /></label>
        <button>Subscribe</button>
    </form>
</template>

<style scoped>
    /* Customise the style of your form here */
</style>

Components in .vuepress/components are automatically available to use in your .md files, so now you can drop this component anywhere in your content:

<SubscribeForm />

Here's mine. Feel free to try it out 😉

Join my mailing list

# 2. Styling content

A great feature of the markdown-to-html conversion in VuePress is that you can write markdown inside html elements by leaving empty lines between the html tags and your markdown like so:

<div>

## Markdown content
> Will be rendered correctly

</div>

This means you can use slots inside your Vue components and fill them with content from your markdown. This is great if you want parts of your content to have a different style. Here's an example of a profile card component, ProfileCard.vue:

<template>
<section class="profile-card">
    <img class="profile-img" :src="$attrs.imgSrc" />
    <div>
        <slot /> <!-- This is where your markdown content will be inserted -->
    </div>
</section>
</template>

<style scoped>
.profile-card {
    display: grid;
    /* ... more styles ...*/
}

.profile-img {
    border-radius: 50%;
    /* ... more styles ...*/
}
</style>

Which you would use like this:

<ProfileCard :imgSrc="https://yourvuepresssite.com/media/image.jpg">

### Profile card example
- Any markdown
- you put here
> will be slotted in 

</ProfileCard>

# Profile card example

  • Any markdown

  • you put here

    will be slotted in

This gives you the freedom to design more interesting content within your pages.

# 3. Adding interactivity

The first two examples showed how useful components can be without even without using <script> in your single file components. Here's an example of a simple quiz component that shows how component data gives you interactivity.

<template>
    <section>
        <div>
            <slot />

            <label><input type="radio" v-model="choice" value="true"> True</label>
            <label><input type="radio" v-model="choice" value="false"> False</label>

            <p v-if="choice && choice == answer" class="correct">CORRECT</p>
            <p v-else-if="choice && choice != answer" class="wrong">WRONG!!!</p>
        </div>
        <div>
            <img :src="imgSrc" />
        </div>
    </section>
</template>

<script>
export default {
    props: {
        answer: String,
        imgSrc: String
    },
    data() {
        return {
            choice: null
        }
    }
}
</script>

<style scoped>
/* your styles here */
</style>

With this saved as .vuepress/components/TrueFalseQuiz.vue add the component anywhere in your .md like this:

<TrueFalseQuiz answer="false" imgSrc="https://yourvuepresssite.com/media/image.jpg">

### True or false...
Quiz question text goes here

</TrueFalseQuiz>

# True or false...

This is a picture of a kitten

You selected box images at the start of this post. Try changing your selection. I've used trick 6 from my previous post to set up the .md file as a single file component, complete with its own data 😄

This is a very simple example. There is so much more you can do in a Vue component and any component you add can have child components of its own. You can see how easy it would be to build web apps into your pages. I'll be sharing my experiments with this in future. Now though, just to reinforce that point about reusability, here's that <SubscribeForm /> component again 😉

Join my mailing list