Skip to content

Commit 35ad5c5

Browse files
committed
Add vueOptions and vueGlobalOptions
Fixed #752
1 parent 62cd35e commit 35ad5c5

File tree

1 file changed

+82
-35
lines changed

1 file changed

+82
-35
lines changed

src/core/render/index.js

Lines changed: 82 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { Compiler } from './compiler';
1313
import * as tpl from './tpl';
1414
import { prerenderEmbed } from './embed';
1515

16+
let vueGlobalData;
17+
1618
function executeScript() {
1719
const script = dom
1820
.findAll('.markdown-section>script')
@@ -41,58 +43,103 @@ function formatUpdated(html, updated, fn) {
4143
}
4244

4345
function renderMain(html) {
46+
const docsifyConfig = this.config;
47+
const markdownElm = dom.find('.markdown-section');
48+
const vueVersion =
49+
'Vue' in window &&
50+
window.Vue.version &&
51+
Number(window.Vue.version.charAt(0));
52+
53+
const isMountedVue = elm => {
54+
const isVue2 = Boolean(elm.__vue__ && elm.__vue__._isVue);
55+
const isVue3 = Boolean(elm._vnode && elm._vnode.__v_skip);
56+
57+
return isVue2 || isVue3;
58+
};
59+
4460
if (!html) {
4561
html = '<h1>404 - Not found</h1>';
4662
}
4763

48-
this._renderTo('.markdown-section', html);
64+
if ('Vue' in window) {
65+
const mountedElms = dom
66+
.findAll('.markdown-section > *')
67+
.filter(elm => isMountedVue(elm));
68+
69+
// Store global data() return value as shared data object
70+
if (!vueGlobalData && docsifyConfig.vueGlobalOptions.data) {
71+
vueGlobalData = docsifyConfig.vueGlobalOptions.data();
72+
}
73+
74+
// Destroy/unmount existing Vue instances
75+
for (const mountedElm of mountedElms) {
76+
if (vueVersion === 2) {
77+
mountedElm.__vue__.$destroy();
78+
} else if (vueVersion === 3) {
79+
mountedElm.__vue_app__.unmount();
80+
}
81+
}
82+
}
83+
84+
this._renderTo(markdownElm, html);
4985

5086
// Render sidebar with the TOC
51-
!this.config.loadSidebar && this._renderSidebar();
87+
!docsifyConfig.loadSidebar && this._renderSidebar();
5288

5389
// Execute markdown <script>
5490
if (
55-
this.config.executeScript ||
56-
('Vue' in window && this.config.executeScript !== false)
91+
docsifyConfig.executeScript ||
92+
('Vue' in window && docsifyConfig.executeScript !== false)
5793
) {
5894
executeScript();
5995
}
6096

61-
// Handle Vue content not handled by markdown <script>
97+
// Handle Vue content not mounted by markdown <script>
6298
if ('Vue' in window) {
63-
const mainElm = document.querySelector('#main') || {};
64-
const childElms = mainElm.children || [];
65-
const vueVersion =
66-
window.Vue.version && Number(window.Vue.version.charAt(0));
67-
68-
for (let i = 0, len = childElms.length; i < len; i++) {
69-
const elm = childElms[i];
70-
const isValid = elm.tagName !== 'SCRIPT';
71-
72-
if (!isValid) {
73-
continue;
74-
}
99+
const vueMountData = [];
100+
101+
if (docsifyConfig.vueOptions) {
102+
vueMountData.push(
103+
...Object.entries(docsifyConfig.vueOptions || {})
104+
.map(([cssSelector, vueConfig]) => [
105+
dom.find(markdownElm, cssSelector),
106+
vueConfig,
107+
])
108+
.filter(([elm, vueConfig]) => elm)
109+
);
110+
}
75111

76-
// Vue 3
77-
if (vueVersion === 3) {
78-
const isAlreadyVue = Boolean(elm._vnode && elm._vnode.__v_skip);
112+
if (docsifyConfig.vueGlobalOptions) {
113+
vueMountData.push(
114+
...dom
115+
.findAll('.markdown-section > *')
116+
// Remove duplicates
117+
.filter(elm => !vueMountData.some(([e, c]) => e === elm))
118+
.map(elm => [
119+
elm,
120+
!docsifyConfig.vueGlobalOptions.data
121+
? docsifyConfig.vueGlobalOptions
122+
: // Replace data() return value with shared data object. This
123+
// mimics the behavior of a global store when using the same
124+
// configuration with multiple Vue instances.
125+
Object.assign({}, docsifyConfig.vueGlobalOptions, {
126+
data() {
127+
return vueGlobalData;
128+
},
129+
}),
130+
])
131+
);
132+
}
79133

80-
if (!isAlreadyVue) {
81-
const app = window.Vue.createApp({});
134+
for (const [mountElm, vueConfig] of vueMountData) {
135+
const isValidTag = mountElm.tagName !== 'SCRIPT';
136+
const hasBrackets = /{{2}[^{}]*}{2}/.test(mountElm.outerHTML);
82137

83-
app.mount(elm);
84-
}
85-
}
86-
// Vue 2
87-
else if (vueVersion === 2) {
88-
const isAlreadyVue = Boolean(elm.__vue__ && elm.__vue__._isVue);
89-
90-
if (!isAlreadyVue) {
91-
new window.Vue({
92-
mounted: function() {
93-
this.$destroy();
94-
},
95-
}).$mount(elm);
138+
if (isValidTag && hasBrackets && !isMountedVue(mountElm)) {
139+
if (vueVersion === 2) {
140+
new window.Vue(vueConfig).$mount(mountElm);
141+
} else if (vueVersion === 3) {
142+
window.Vue.createApp(vueConfig).mount(mountElm);
96143
}
97144
}
98145
}

0 commit comments

Comments
 (0)