Skip to content

Fix Vue Reactivity #1271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 8, 2020
70 changes: 37 additions & 33 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,31 @@
<html lang="en">

<head>
<meta charset="UTF-8">
<title>docsify</title>
<link rel="icon" href="_media/favicon.ico">
<meta name="google-site-verification" content="6t0LoIeFksrjF4c9sqUEsVXiQNxLp2hgoqo0KryT-sE" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="keywords" content="doc,docs,documentation,gitbook,creator,generator,github,jekyll,github-pages">
<meta name="description" content="A magical documentation generator.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css" title="vue">
<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>
<meta charset="UTF-8">
<title>docsify</title>
<link rel="icon" href="_media/favicon.ico">
<meta name="google-site-verification" content="6t0LoIeFksrjF4c9sqUEsVXiQNxLp2hgoqo0KryT-sE" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="keywords" content="doc,docs,documentation,gitbook,creator,generator,github,jekyll,github-pages">
<meta name="description" content="A magical documentation generator.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css" title="vue">
<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 {
min-width: 100px;
}
</style>
<style>
nav.app-nav li ul {
min-width: 100px;
}
</style>
</head>

<body>
<div id="app">Loading ...</div>
<script>
window.$docsify = {
<div id="app">Loading ...</div>
<script>
window.$docsify = {
alias: {
'.*?/awesome': 'https://raw.githubusercontent.com/docsifyjs/awesome-docsify/master/README.md',
'.*?/changelog': 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG.md',
Expand Down Expand Up @@ -78,6 +79,7 @@
url = 'https://github.com/docsifyjs/docsify/blob/master/docs/' + vm.route.file
}
var editHtml = '[:memo: Edit Document](' + url + ')\n'

return editHtml
+ html
+ '\n\n----\n\n'
Expand All @@ -92,20 +94,22 @@
}
]
}
</script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/ga.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/matomo.min.js"></script>
<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>
((window.gitter = {}).chat = {}).options = {
</script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/ga.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/matomo.min.js"></script>
<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'
};
</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
</body>

</html>
</html>
140 changes: 93 additions & 47 deletions docs/vue.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,145 @@
# 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.

*README.md*
## Basic rendering

````markdown
# Vue guide
Docsify will automatically render basic Vue content that does not require `data`, `methods`, or other instance features.

`v-for` usage.
```markdown
<button v-on:click.native="this.alert('Hello, World!')">Say Hello</button>

```html
<ul>
<li v-for="i in 10">{{ i }}</li>
<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 10">{{ i }}</li>
<li v-for="i in 3">{{ i }}</li>
</ul>
````

You can manually initialize a Vue instance.
## Advanced usage

*README.md*
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
# Vue demo
<div id="example-1">
<p>{{ message }}</p>

<button v-on:click="hello">Say Hello</button>

<div id="main">hello {{ msg }}</div>
<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:

<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>

## Combine Vuep to write playground
!> 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](https://github.com/QingWei-Li/vuep) is a component for rendering Vue components with live editor and preview. Supports Vue component spec and JSX.
## Vuep playgrounds

*index.html*
[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*
```markdown
# Vuep
Add vuep markup to a markdown file (e.g. `README.md`):

<vuep template="#example"></vuep>
```markdown
<vuep template="#example-2"></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' }
}
}
</script>
</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>
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>
43 changes: 27 additions & 16 deletions src/core/render/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ function executeScript() {
return false;
}

setTimeout(_ => {
window.__EXECUTE_RESULT__ = new Function(code)();
}, 0);
new Function(code)();
}

function formatUpdated(html, updated, fn) {
Expand All @@ -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);
}
}
}
}

Expand Down