mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
Fix Vue compatibility (fix #790)
- Fix inability to instantiate reactive Vue components by 1) handling each child of #main instead of #main itself and 2) skipping elements that are already Vue instances - Retain previous behavior of processing basic Vue rendering without the need for a markdown <script> tag. - Update documentation and add live Vue examples - Update `index.html` files to include Vue.js and Vuep (CSS+JS)
This commit is contained in:
parent
c78cb11292
commit
f385e21a1b
@ -14,6 +14,7 @@
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/dark.css" title="dark" disabled>
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/buble.css" title="buble" disabled>
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/pure.css" title="pure" disabled>
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/vuep/dist/vuep.css">
|
||||
|
||||
<style>
|
||||
nav.app-nav li ul {
|
||||
@ -95,6 +96,8 @@
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs/components/prism-bash.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs/components/prism-markdown.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs/components/prism-nginx.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/vue@2/dist/vue.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/vuep/dist/vuep.min.js"></script>
|
||||
<script>
|
||||
((window.gitter = {}).chat = {}).options = {
|
||||
room: 'docsifyjs/Lobby'
|
||||
|
||||
160
docs/vue.md
160
docs/vue.md
@ -1,94 +1,111 @@
|
||||
# Compatible with Vue
|
||||
# Vue compatibility
|
||||
|
||||
You can write Vue components directly in the Markdown file, and it will be parsed. You can use this feature to write vue demo and documentation together.
|
||||
Docsify allows [Vue.js](https://vuejs.org) components to be added directly to you Markdown files. These components can greatly simplify working with data and adding reactivity to your content.
|
||||
|
||||
## Basic usage
|
||||
|
||||
Load the Vue in `./index.html`.
|
||||
To get started, load either the production (minified) or development (unminified) version of Vue in your `index.html`:
|
||||
|
||||
```html
|
||||
<script src="//cdn.jsdelivr.net/npm/vue"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify"></script>
|
||||
<!-- Production (minified) -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vue@2/dist/vue.min.js"></script>
|
||||
|
||||
<!-- Or use the compressed files -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
|
||||
<!-- Development (unminified, with debugging info via console) -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
|
||||
```
|
||||
|
||||
Then you can immediately write Vue code at Markdown file. `new Vue({ el: '#main' })` script is executed by default to create instance.
|
||||
## Basic rendering
|
||||
|
||||
*README.md*
|
||||
|
||||
````markdown
|
||||
# Vue guide
|
||||
|
||||
`v-for` usage.
|
||||
|
||||
```html
|
||||
<ul>
|
||||
<li v-for="i in 10">{{ i }}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
<ul>
|
||||
<li v-for="i in 10">{{ i }}</li>
|
||||
</ul>
|
||||
````
|
||||
|
||||
You can manually initialize a Vue instance.
|
||||
|
||||
*README.md*
|
||||
Docsify will automatically render basic Vue content that does not require `data`, `methods`, or other instance features.
|
||||
|
||||
```markdown
|
||||
# Vue demo
|
||||
<button v-on:click.native="this.alert('Hello, World!')">Say Hello</button>
|
||||
|
||||
<div id="main">hello {{ msg }}</div>
|
||||
<ul>
|
||||
<li v-for="i in 3">{{ i }}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
The HTML above will render the following:
|
||||
|
||||
<button v-on:click="this.alert('Hello, World!')">Say Hello</button>
|
||||
|
||||
<ul>
|
||||
<li v-for="i in 3">{{ i }}</li>
|
||||
</ul>
|
||||
|
||||
## Advanced usage
|
||||
|
||||
Vue components and templates that require `data`, `methods`, computed properties, lifecycle hooks, etc. require manually creating a new `Vue()` instance within a `<script>` tag in your markdown.
|
||||
|
||||
```markdown
|
||||
<div id="example-1">
|
||||
<p>{{ message }}</p>
|
||||
|
||||
<button v-on:click="hello">Say Hello</button>
|
||||
|
||||
<button v-on:click="counter -= 1">-</button>
|
||||
{{ counter }}
|
||||
<button v-on:click="counter += 1">+</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
```markdown
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#main',
|
||||
data: { msg: 'Vue' }
|
||||
})
|
||||
el: "#example-1",
|
||||
data: function() {
|
||||
counter: 0,
|
||||
message: "Hello, World!"
|
||||
},
|
||||
methods: {
|
||||
hello: function() {
|
||||
alert(this.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
!> In a Markdown file, only the script within the first script tag is executed.
|
||||
The HTML & JavaScript above will render the following:
|
||||
|
||||
## Combine Vuep to write playground
|
||||
<div id="example-1">
|
||||
<p>{{ message }}</p>
|
||||
|
||||
[Vuep](https://github.com/QingWei-Li/vuep) is a component for rendering Vue components with live editor and preview. Supports Vue component spec and JSX.
|
||||
<button v-on:click="hello">Say Hello</button>
|
||||
|
||||
*index.html*
|
||||
<button v-on:click="counter -= 1">-</button>
|
||||
{{ counter }}
|
||||
<button v-on:click="counter += 1">+</button>
|
||||
</div>
|
||||
|
||||
!> Only the first `<script>` tag in a markdown file is executed. If you are working with multiple Vue components, all `Vue` instances must be created within this tag.
|
||||
|
||||
## Vuep playgrounds
|
||||
|
||||
[Vuep](https://github.com/QingWei-Li/vuep) is a Vue component that provides a live editor and preview for Vue content. See the [vuep documentation](https://qingwei-li.github.io/vuep/) for details.
|
||||
|
||||
Add Vuep CSS and JavaScript to your `index.html`:
|
||||
|
||||
```html
|
||||
<!-- Inject CSS file -->
|
||||
<!-- Vuep CSS -->
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/vuep/dist/vuep.css">
|
||||
|
||||
<!-- Inject JavaScript file -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vue"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/vuep"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify"></script>
|
||||
|
||||
<!-- or use the compressed files -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
|
||||
<!-- Vuep JavaScript -->
|
||||
<script src="//cdn.jsdelivr.net/npm/vuep/dist/vuep.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
|
||||
```
|
||||
|
||||
*README.md*
|
||||
Add vuep markup to a markdown file (e.g. `README.md`):
|
||||
|
||||
```markdown
|
||||
# Vuep
|
||||
<vuep template="#example-2"></vuep>
|
||||
|
||||
<vuep template="#example"></vuep>
|
||||
|
||||
<script v-pre type="text/x-template" id="example">
|
||||
<script v-pre type="text/x-template" id="example-2">
|
||||
<template>
|
||||
<div>Hello, {{ name }}!</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function () {
|
||||
data: function() {
|
||||
return { name: 'Vue' }
|
||||
}
|
||||
}
|
||||
@ -96,4 +113,33 @@ You can manually initialize a Vue instance.
|
||||
</script>
|
||||
```
|
||||
|
||||
?> Example Refer to the [Vuep documentation](https://qingwei-li.github.io/vuep/).
|
||||
<vuep template="#example-2"></vuep>
|
||||
|
||||
<script v-pre type="text/x-template" id="example-2">
|
||||
<template>
|
||||
<div>Hello, {{ name }}!</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function() {
|
||||
return { name: 'World' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#example-1",
|
||||
data: {
|
||||
counter: 0,
|
||||
message: "Hello, World!"
|
||||
},
|
||||
methods: {
|
||||
hello: function() {
|
||||
alert(this.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
<link rel="stylesheet" href="/themes/vue.css" title="vue">
|
||||
<link rel="stylesheet" href="/themes/dark.css" title="dark" disabled>
|
||||
<link rel="stylesheet" href="/themes/buble.css" title="buble" disabled>
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/vuep/dist/vuep.css">
|
||||
<style>
|
||||
nav.app-nav li ul {
|
||||
min-width: 100px;
|
||||
@ -85,6 +86,8 @@
|
||||
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-nginx.min.js"></script>
|
||||
<script src="//unpkg.com/vue/dist/vue.js"></script>
|
||||
<script src="//unpkg.com/vuep/dist/vuep.min.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@ -26,9 +26,7 @@ function executeScript() {
|
||||
return false;
|
||||
}
|
||||
|
||||
setTimeout(_ => {
|
||||
window.__EXECUTE_RESULT__ = new Function(code)();
|
||||
}, 0);
|
||||
new Function(code)();
|
||||
}
|
||||
|
||||
function formatUpdated(html, updated, fn) {
|
||||
@ -48,22 +46,35 @@ function renderMain(html) {
|
||||
}
|
||||
|
||||
this._renderTo('.markdown-section', html);
|
||||
|
||||
// Render sidebar with the TOC
|
||||
!this.config.loadSidebar && this._renderSidebar();
|
||||
|
||||
// Execute script
|
||||
if (
|
||||
this.config.executeScript !== false &&
|
||||
typeof window.Vue !== 'undefined' &&
|
||||
!executeScript()
|
||||
) {
|
||||
setTimeout(_ => {
|
||||
const vueVM = window.__EXECUTE_RESULT__;
|
||||
vueVM && vueVM.$destroy && vueVM.$destroy();
|
||||
window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main');
|
||||
}, 0);
|
||||
} else {
|
||||
this.config.executeScript && executeScript();
|
||||
// Execute markdown <script>
|
||||
if (this.config.executeScript || 'Vue' in window) {
|
||||
executeScript();
|
||||
}
|
||||
|
||||
// Handle Vue content not handled by markdown <script>
|
||||
if ('Vue' in window) {
|
||||
const mainElm = document.querySelector('#main') || {};
|
||||
const childElms = mainElm.children || [];
|
||||
|
||||
for (let i = 0, len = childElms.length; i < len; i++) {
|
||||
const elm = childElms[i];
|
||||
const isValid = ['SCRIPT'].indexOf(elm.tagName) === -1;
|
||||
const isVue = Boolean(elm.__vue__ && elm.__vue__._isVue);
|
||||
|
||||
if (isValid && !isVue) {
|
||||
new window.Vue({
|
||||
mounted: function() {
|
||||
if (this.$children.length === 0) {
|
||||
this.$destroy;
|
||||
}
|
||||
},
|
||||
}).$mount(elm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user