# Using Vue in Markdown

# Browser API Access Restrictions

Because VuePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the universal code requirements. In short, make sure to only access Browser / DOM APIs in beforeMounted or mounted hooks.

If you are using or demoing a component that is not SSR friendly (for example containing custom directives), you can wrap them inside the built-in <ClientOnly> component:

<ClientOnly>
  <NonSSRFriendlyComponent/>
</ClientOnly>

Note this does not fix components or libraries that access Browser APIs on import - in order to use code that assumes a browser environment on import, you need to dynamically import them in proper lifecycle hooks:

<script>
export default {
  mounted () {
    import('./lib-that-access-window-on-import').then(module => {
      // use code
    })
  }
}
</script>

# Templating

# Interpolation

Each markdown file is first compiled into HTML and then passed on as a Vue component to vue-loader. This means you can use Vue-style interpolation in text:

Input

{{ 1 + 1 }}

Output

2

# Directives

Directives also work:

Input

<span v-for="i in 3">{{ i }} </span>

Output

1 2 3 

# Access to Site & Page Data

The compiled component does not have any private data but do have access to the site metadata. For example:

Input

{{ $page }}

Output

{
  "path": "/using-vue.html",
  "title": "Using Vue in Markdown",
  "frontmatter": {}
}

# Escaping

By default, fenced code blocks are automatically wrapped with v-pre. If you want to display raw mustaches or Vue-specific syntax inside inline code snippets or plain text, you need to wrap a paragraph with the v-pre custom container:

Input

::: v-pre
`{{ This will be displayed as-is }}`
:::

Output

{{ This will be displayed as-is }}

# Using Components

Any *.vue file found in .vuepress/components are automatically registered as global async components. For example:

.
└─ .vuepress
   └─ components
      ├─ demo-1.vue
      └─ OtherComponent.vue

Inside any markdown file you can then directly use the components (names are inferred from filenames):

<demo-1/>
<OtherComponent/>

IMPORTANT

Make sure a custom component's names either contains a hyphen or is in PascalCase. Otherwise it will be treated as an inline element and wrapped inside a <p> tag, which will lead to hydration mismatch because <p> does not allow block elements to be placed inside it.

# Script & Style Hoisting

Sometimes you may need to apply some JavaScript or CSS only to the current page. In those cases you can directly write root-level <script> or <style> blocks in the markdown file, and they will be hoisted out of the compiled HTML and used as the <script> and <style> blocks for the resulting Vue single-file component.