-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
feat: Vue components, mount options, global options, and v3 support #1409
Changes from all commits
35ad5c5
cd8f2d3
ecd053b
5fa79eb
a2386e5
bc2e091
1774ab8
6d152e2
758538c
0193659
8a56f72
5a2dde1
1a52e97
86dae61
2946c06
871e48f
131aae5
af7e713
25084f8
6a5e84b
febe7f8
b6d5407
8362ed0
f0a8d69
5ec2256
a9be6f2
3af1cfa
b33d750
cafdd62
d9e491a
a5a431f
4e5dae7
eae3ad8
421ef1d
52cce02
727ee8f
69efae3
51451a4
a10fcbd
9a1935a
43a73bb
7cf1e7c
7878c60
90b67e2
ffa7c90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -245,10 +245,10 @@ window.$docsify = { | |
// Custom file name | ||
coverpage: 'cover.md', | ||
|
||
// mutiple covers | ||
// multiple covers | ||
coverpage: ['/', '/zh-cn/'], | ||
|
||
// mutiple covers and custom file name | ||
// multiple covers and custom file name | ||
coverpage: { | ||
'/': 'cover.md', | ||
'/zh-cn/': 'cover.md', | ||
|
@@ -410,7 +410,7 @@ window.$docsify = { | |
}; | ||
``` | ||
|
||
?> If this options is `false` but you dont want to emojify some specific colons , [Refer this](https://github.com/docsifyjs/docsify/issues/742#issuecomment-586313143) | ||
?> If this options is `false` but you don't want to emojify some specific colons , [Refer this](https://github.com/docsifyjs/docsify/issues/742#issuecomment-586313143) | ||
|
||
## mergeNavbar | ||
|
||
|
@@ -494,15 +494,15 @@ window.$docsify = { | |
``` | ||
|
||
## crossOriginLinks | ||
- type: `Array` | ||
|
||
When `routerMode: 'history'`, you may face the cross-origin issues, See [#1379](https://github.com/docsifyjs/docsify/issues/1379). | ||
In Markdown content, there is a simple way to solve it, see extends Markdown syntax `Cross-Origin link` in [helpers](helpers.md). | ||
- type: `Array` | ||
|
||
When `routerMode: 'history'`, you may face the cross-origin issues, See [#1379](https://github.com/docsifyjs/docsify/issues/1379). | ||
In Markdown content, there is a simple way to solve it, see extends Markdown syntax `Cross-Origin link` in [helpers](helpers.md). | ||
|
||
```js | ||
window.$docsify = { | ||
crossOriginLinks:[ | ||
"https://example.com/cross-origin-link", | ||
], | ||
crossOriginLinks: ['https://example.com/cross-origin-link'], | ||
}; | ||
``` | ||
|
||
|
@@ -604,7 +604,7 @@ window.$docsify = { | |
}; | ||
``` | ||
|
||
Load the right 404 page according to the localisation: | ||
Load the right 404 page according to the localization: | ||
|
||
```js | ||
window.$docsify = { | ||
|
@@ -629,3 +629,104 @@ window.$docsify = { | |
topMargin: 90, // default: 0 | ||
}; | ||
``` | ||
|
||
## vueComponents | ||
|
||
- type: `Object` | ||
|
||
Creates and registers global [Vue components](https://vuejs.org/v2/guide/components.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> | ||
``` | ||
|
||
<output data-lang="output"> | ||
<button-counter></button-counter> | ||
</output> | ||
|
||
## vueGlobalOptions | ||
|
||
- type: `Object` | ||
|
||
Specifies [Vue options](https://vuejs.org/v2/api/#Options-Data) for use with Vue content not explicitly mounted with [vueMounts](#mounting-dom-elements), [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> | ||
|
||
## vueMounts | ||
|
||
- type: `Object` | ||
|
||
Specifies DOM elements to mount as [Vue instances](https://vuejs.org/v2/guide/instance.html) 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, | ||
}; | ||
}, | ||
}, | ||
}, | ||
}; | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel that there's explanation missing here as to what exactly this does. If the vueMountOptions contains 5 selectors, does that mean Vue instantiates 5 components and mounts to those five areas on the page? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @trusktr Agreed. Good catch. This question is answered on the
For example: window.$docsify = {
vueMountOptions: {
// The CSS selector "p" could match multiple elements.
// However, only the first <p> element will be mounted.
// Think `querySelector()`, not `querySelectorAll()`
'p': {
data() {
return {
count: 0,
};
},
},
},
}; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not have it apply to all matches? That would be convenient I imagine (one definition, but multiple instances of it across the page). Thinking Also people may wonder if the following examples will work: Exampe 1 Does it render both? <p class="one">{count}</p>
<p class="two">{count}</p> window.$docsify = {
vueMounts: {
'p.one': {
data: () => ({ count: 1 },
},
'p.two': {
data: () => ({ count: 2 },
},
},
}; Example 2 What happens? <p class="one">
{count}
<p class="two">
{count}
</p>
</p> window.$docsify = {
vueMounts: {
'p.one': {
data: () => ({ count: 1 },
},
'p.two': {
data: () => ({ count: 2 },
},
},
}; Example 3 What happens? <component-one inline-template>
{count}
<component-two inline-template>
{count}
</component-two>
</component-one> window.$docsify = {
vueComponents: {
'component-one': {
data: () => ({ count: 1 },
},
'component-two': {
data: () => ({ count: 2 },
},
},
}; Example 4 User opens feature request saying "can we render all of them?" <p>{count}</p>
<p>{count}</p>
<p>{count}</p>
<p>{count}</p>
<p>{count}</p> let pCount = 0
window.$docsify = {
vueMounts: {
'p': {
data: () => ({ count: ++pCount },
}
},
}; Exampe 5 How do I make this work? <p class="one">{count}{foo}</p>
<p class="two">{count}{foo}</p> window.$docsify = {
vueMounts: {
'p.one': {
data: () => ({ count: 1 },
},
'p.two': {
data: () => ({ count: 2 },
},
'p': {
data: () => ({ foo: 'bar' },
},
},
}; |
||
|
||
```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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we want to use
vueMountOptions
with a selector, when we could specify components usingvueComponents
?Trying to get a more clear picture just from the docs (will read source next).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trusktr --
Fair question considering there is quite a bit of overlap between mounting DOM elements directly (
vueMounts
) and components (vueComponents
). I'm not sure if you're asking why "we" as users or "we" as maintainers of docsify, so I'll try to touch on both.The short answer is that all of the reasons why a user might opt to mount a DOM element directly instead of creating a component apply here. Similarly, all of the reasons why the Vue team provide the option to mount DOM elements directly instead of forcing devs to create Vue components for every scenario also apply here.
Here are a few items worth considering:
Vue supports mounting both DOM elements and components. So should we.
Mounting DOM elements is the first concept found in the Vue docs and introductory Vue tutorials. It is the fastest and simplest way to be productive with a library like Vue and requires the least amount of expertise. Allowing code from these docs and tutorials to be easily ported to docsify is an important consideration for our users--especially junior and non-developer users.
Components are typically presented as reusable building blocks that combine to make larger applications. Obviously this doesn't have to be the case, but it's how they are often conceptualized. Users shouldn't have to think in these terms or learn about Vue components if they only want to do simple things like render
data
on a docsify page.There are technical differences to consider when choosing to mount a DOM element or a component. For example,
vueMountOptions
vueMounts
allows Vue templates to be defined inline (in.md
pages) and include markdown syntax:Vue components more commonly define templates via the
template
property:The drawback to defining templates this way is that
template
markup cannot contain markdown syntax, will not be processed by docsify plugins, will not have syntax highlighting or linting while authoring, will not render default content outside of docsify (e.g., GitHub), etc. You can work around some of these things, but doing so requires a level of expertise that not all docsify users will have.FWIW, Vue components can do inline templates, but doing so requires adding an
inline-template
attribute to the component tag (which is not intuitive) and repeating inline template markup kinda defeats the purpose of simple, reusable components.I'm sure there are other items worth considering that I haven't thought of, but hopefully the above items are helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that explanation! I know about the starting the root of a Vue tree and components used in the Vue tree, but these are two features additional to Vue (for Docsify).
Knowing Vue, I know I can put
new Vue
in a script that I can load with<script src="...">
on every page.I suppose what I'm really asking is the following.
Here are two ways to basically do the same thing with the new system.
Method 1:
Method 2:
Both have about the same ease-of-use (learning to use
inline-template
is as easy as writing an id or class name). The question is, why have both?Is the difference only the inline-template vs no inline-template thing? If so, is it worth having two options just for that small difference?