mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
* Update Vue 3 depenency and docs. Remove Vue 2. * Fix minor lint issue * Remove Vue 2 reference * Swap button positions * Update Vue2 links * Send HTML with _blank to avoid quirks mode * Support Vue text interpolation in code blocks Fix #1812
343 lines
8.5 KiB
Markdown
343 lines
8.5 KiB
Markdown
# Vue compatibility
|
|
|
|
Docsify allows [Vue.js](https://vuejs.org) content to be added directly to your markdown pages. This can greatly simplify working with data and adding reactivity to your site.
|
|
|
|
Vue [template syntax](https://vuejs.org/guide/essentials/template-syntax) can be used to add dynamic content to your pages. Vue content becomes more interesting when [data](#data), [computed properties](#computed-properties), [methods](#methods), and [lifecycle hooks](#lifecycle-hooks) are used. These options can be specified as [global options](#global-options) or within DOM [mounts](#mounts) and [components](#components).
|
|
|
|
## Setup
|
|
|
|
To get started, add Vue.js to your `index.html` file. Choose the production version for your live site or the development version for helpful console warnings and [Vue.js devtools](https://github.com/vuejs/vue-devtools) support.
|
|
|
|
```html
|
|
<!-- Production -->
|
|
<script src="//cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
|
|
|
|
<!-- Development -->
|
|
<script src="//cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
|
|
```
|
|
|
|
## Template syntax
|
|
|
|
Vue [template syntax](https://vuejs.org/guide/essentials/template-syntax) offers several useful features like support for [JavaScript expressions](https://vuejs.org/guide/essentials/template-syntax.html#using-javascript-expressions) and Vue [directives](https://vuejs.org/guide/essentials/template-syntax.html#directives) for loops and conditional rendering.
|
|
|
|
```markdown
|
|
<!-- Hide in docsify, show elsewhere (e.g. GitHub) -->
|
|
<p v-if="false">Text for GitHub</p>
|
|
|
|
<!-- Sequenced content (i.e. loop)-->
|
|
<ul>
|
|
<li v-for="i in 3">Item {{ i }}</li>
|
|
</ul>
|
|
|
|
<!-- JavaScript expressions -->
|
|
<p>2 + 2 = {{ 2 + 2 }}</p>
|
|
```
|
|
|
|
<output data-lang="output">
|
|
<p v-if="false">Text for GitHub</p>
|
|
|
|
<ul>
|
|
<li v-for="i in 3">Item {{ i }}</li>
|
|
</ul>
|
|
|
|
<p>2 + 2 = {{ 2 + 2 }}</p>
|
|
</output>
|
|
|
|
[View output on GitHub](https://github.com/docsifyjs/docsify/blob/develop/docs/vue.md#template-syntax)
|
|
|
|
## Code Blocks
|
|
|
|
Docsify ignores Vue template syntax within code blocks by default:
|
|
|
|
````markdown
|
|
```
|
|
{{ message}}
|
|
```
|
|
````
|
|
|
|
To process Vue template syntax within a code block, wrap the code block in an element with a `v-template` attribute:
|
|
|
|
````markdown
|
|
<div v-template>
|
|
|
|
```
|
|
{{ message}}
|
|
```
|
|
|
|
</div>
|
|
````
|
|
|
|
## Data
|
|
|
|
```js
|
|
{
|
|
data() {
|
|
return {
|
|
message: 'Hello, World!'
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
<!-- prettier-ignore-start -->
|
|
```markdown
|
|
<!-- Show message in docsify, show "{{ message }}" elsewhere (e.g. GitHub) -->
|
|
{{ message }}
|
|
|
|
<!-- Show message in docsify, hide elsewhere (e.g. GitHub) -->
|
|
<p v-text="message"></p>
|
|
```
|
|
<!-- prettier-ignore-end -->
|
|
|
|
<output data-lang="output">
|
|
<p>{{ message }}</p>
|
|
|
|
<p v-text="message"></p>
|
|
</output>
|
|
|
|
[View output on GitHub](https://github.com/docsifyjs/docsify/blob/develop/docs/vue.md#data)
|
|
|
|
## Computed properties
|
|
|
|
```js
|
|
{
|
|
computed: {
|
|
timeOfDay() {
|
|
const date = new Date();
|
|
const hours = date.getHours();
|
|
|
|
if (hours < 12) {
|
|
return 'morning';
|
|
}
|
|
else if (hours < 18) {
|
|
return 'afternoon';
|
|
}
|
|
else {
|
|
return 'evening'
|
|
}
|
|
}
|
|
},
|
|
}
|
|
```
|
|
|
|
```markdown
|
|
Good {{ timeOfDay }}!
|
|
```
|
|
|
|
<output data-lang="output">
|
|
|
|
Good {{ timeOfDay }}!
|
|
|
|
</output>
|
|
|
|
## Methods
|
|
|
|
```js
|
|
{
|
|
data() {
|
|
return {
|
|
message: 'Hello, World!'
|
|
};
|
|
},
|
|
methods: {
|
|
hello() {
|
|
alert(this.message);
|
|
}
|
|
},
|
|
}
|
|
```
|
|
|
|
```markdown
|
|
<button @click="hello">Say Hello</button>
|
|
```
|
|
|
|
<output data-lang="output">
|
|
<p><button @click="hello">Say Hello</button></p>
|
|
</output>
|
|
|
|
## Lifecycle Hooks
|
|
|
|
```js
|
|
{
|
|
data() {
|
|
return {
|
|
images: null,
|
|
};
|
|
},
|
|
created() {
|
|
fetch('https://api.domain.com/')
|
|
.then(response => response.json())
|
|
.then(data => (this.images = data))
|
|
.catch(err => console.log(err));
|
|
}
|
|
}
|
|
|
|
// API response:
|
|
// [
|
|
// { title: 'Image 1', url: 'https://domain.com/1.jpg' },
|
|
// { title: 'Image 2', url: 'https://domain.com/2.jpg' },
|
|
// { title: 'Image 3', url: 'https://domain.com/3.jpg' },
|
|
// ];
|
|
```
|
|
|
|
```markdown
|
|
<div style="display: flex;">
|
|
<figure style="flex: 1;">
|
|
<img v-for="image in images" :src="image.url" :title="image.title">
|
|
<figcaption>{{ image.title }}</figcaption>
|
|
</figure>
|
|
</div>
|
|
```
|
|
|
|
<output data-lang="output">
|
|
<div style="display: flex;">
|
|
<figure v-for="image in images" style="flex: 1; text-align: center;">
|
|
<img :src="image.url">
|
|
<figcaption>{{ image.title }}</figcaption>
|
|
</figure>
|
|
</div>
|
|
</output>
|
|
|
|
## Global options
|
|
|
|
Use `vueGlobalOptions` to specify global Vue options for use with Vue content not explicitly mounted with [vueMounts](#mounts), [vueComponents](#components), or a [markdown script](#markdown-script). Changes to global `data` will persist and be reflected anywhere global references are used.
|
|
|
|
```js
|
|
window.$docsify = {
|
|
vueGlobalOptions: {
|
|
data() {
|
|
return {
|
|
count: 0,
|
|
};
|
|
},
|
|
},
|
|
};
|
|
```
|
|
|
|
```markdown
|
|
<p>
|
|
<button @click="count += 1">+</button>
|
|
{{ count }}
|
|
<button @click="count -= 1">-</button>
|
|
</p>
|
|
```
|
|
|
|
<output data-lang="output">
|
|
<p>
|
|
<button @click="count += 1">+</button>
|
|
{{ count }}
|
|
<button @click="count -= 1">-</button>
|
|
</p>
|
|
</output>
|
|
|
|
Notice the behavior when multiple global counters are rendered:
|
|
|
|
<output data-lang="output">
|
|
<p>
|
|
<button @click="count += 1">+</button>
|
|
{{ count }}
|
|
<button @click="count -= 1">-</button>
|
|
</p>
|
|
</output>
|
|
|
|
Changes made to one counter affect the both counters. This is because both instances reference the same global `count` value. Now, navigate to a new page and return to this section to see how changes made to global data persist between page loads.
|
|
|
|
## Mounts
|
|
|
|
Use `vueMounts` to specify DOM elements to mount as Vue instances and their associated options. Mount elements are specified using a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) as the key with an object containing Vue options as their value. Docsify will mount the first matching element in the main content area each time a new page is loaded. Mount element `data` is unique for each instance and will not persist as users navigate the site.
|
|
|
|
```js
|
|
window.$docsify = {
|
|
vueMounts: {
|
|
'#counter': {
|
|
data() {
|
|
return {
|
|
count: 0,
|
|
};
|
|
},
|
|
},
|
|
},
|
|
};
|
|
```
|
|
|
|
```markdown
|
|
<div id="counter">
|
|
<button @click="count += 1">+</button>
|
|
{{ count }}
|
|
<button @click="count -= 1">-</button>
|
|
</div>
|
|
```
|
|
|
|
<output id="counter">
|
|
<button @click="count += 1">+</button>
|
|
{{ count }}
|
|
<button @click="count -= 1">-</button>
|
|
</output>
|
|
|
|
## Components
|
|
|
|
Use `vueComponents` to create and register global [Vue components](https://vuejs.org/guide/essentials/component-basics.html). Components are specified using the component name as the key with an object containing Vue options as the value. Component `data` is unique for each instance and will not persist as users navigate the site.
|
|
|
|
```js
|
|
window.$docsify = {
|
|
vueComponents: {
|
|
'button-counter': {
|
|
template: `
|
|
<button @click="count += 1">
|
|
You clicked me {{ count }} times
|
|
</button>
|
|
`,
|
|
data() {
|
|
return {
|
|
count: 0,
|
|
};
|
|
},
|
|
},
|
|
},
|
|
};
|
|
```
|
|
|
|
```markdown
|
|
<button-counter></button-counter>
|
|
<button-counter></button-counter>
|
|
```
|
|
|
|
<output data-lang="output">
|
|
<button-counter></button-counter>
|
|
<button-counter></button-counter>
|
|
</output>
|
|
|
|
## Markdown script
|
|
|
|
Vue content can mounted using a `<script>` tag in your markdown pages.
|
|
|
|
!> Only the first `<script>` tag in a markdown file is executed. If you wish to mount multiple Vue instances using a script tag, all instances must be mounted within the first script tag in your markdown.
|
|
|
|
```html
|
|
<script>
|
|
Vue.createApp({
|
|
// Options...
|
|
}).mount('#example');
|
|
</script>
|
|
```
|
|
|
|
## Technical Notes
|
|
|
|
- Docsify processes Vue content in the following order on each page load:
|
|
1. Execute markdown `<script>`
|
|
1. Register global `vueComponents`
|
|
1. Mount `vueMounts`
|
|
1. Auto-mount unmounted `vueComponents`
|
|
1. Auto-mount unmounted Vue template syntax using `vueGlobalOptions`
|
|
- When auto-mounting Vue content, docsify will mount each top-level element in your markdown that contains template syntax or a component. For example, in the following HTML the top-level `<p>`, `<my-component />`, and `<div>` elements will be mounted.
|
|
```html
|
|
<p>{{ foo }}</p>
|
|
<my-component />
|
|
<div>
|
|
<span>{{ bar }}</span>
|
|
<some-other-component />
|
|
</div>
|
|
```
|
|
- Docsify will not mount an existing Vue instance or an element that contains an existing Vue instance.
|
|
- Docsify will automatically destroy/unmount all Vue instances it creates before each page load.
|