Vuepress dynamic routes and render as page? - vue.js

I use vuepress as a mixed solution of static generated pages and dynamic pages in the SPA approach. The dynamic data source is a large database server, hence it can not use the additionalPages feature introduced in vurepress 1.x. That means dynamic routes was added using enhanceApp.js as below. Dynamic pages are rendered with extended layouts to share same page structure (header, footer).
// Foo is a layout component extends from Layout.vue
import Foo from './layouts/Foo.vue'
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData // site metadata
}) => {
router.addRoutes([
{ path: '/foo/:id', component: Foo },
]);
}
It works, however the layouts/Foo.vue is a component. It missing frontmatter, markdown syntax like normal markdown page does. The question is how to load a markdown page and pass to routes as component?

I'm still new to Vuepress, but I come across this comment in the source code that might be able to help you.
When Vue SFCs are source files, make them as layout components directly
I haven't finished reading all source code, so I'm not very sure I understand it correctly. But I guess when Vuepress find a vue component, it will not render it like a markdown file. It assumes you have your own style inside the .vue file. So I think that may be why you are missing what normal markdown page has.
However, if you need to mix a dynamic data source with static pages, you can try to use Vue in markdown to get what you want to achieve.

Related

Vue-Router add new route dynamically when there is a new component

I need to create a fully modular Vue project and I can't figure out how do I add or remove routes when there is a new component or a component is deleted.
Now I statically type all the routes that are available in my Sidebar menu. Let's say there are 10 menus in my sidebar, it means that I should type 10 routes in my routes.js file.
But I need this project to be modular. By saying modular what I mean is, I need to give the component list to the project, I think that I should do that with a .json file and let's say this file says that it has only 5 component available, then the related routes will be dynamically created in the routes.js file, and when one of them is deleted, the related route should be removed from the routes list as well. That is what I want.
I want to do that because I develop a single frontend with Vue for more than one device. These devices may have different options and menus, when the device and the frontend matches, only the available menus will be put in the sidebar, so I can't type all the routes statically as I've been doing the whole time.
Any advice would be appreciated.
You can loop through a list of routes and use the router.addRoute function to dynamically add them to your router instance (requires vue-router 3.5.0+), instead of loading them by default. You could do this from the created() hook of your main layout for example.
// app.vue
<template>
<router-view />
</template>
<script>
export default {
created() {
let routes = loadRoutes(); // insert your own function to get the correct routes here
routes.forEach(route => this.$router.addRoute(route))
},
};
</script>
If you need to be able to switch between different layouts on the same device (like a shared terminal for managers and employees) you can reset the routes array by creating a new router instance, or removeRoute (if you use v4.0+).

Gridsome: How to add Vue.use(MyPlugin) for a single page only?

I have added ReCaptcha plugin using Vue.use(ReCaptcha, {some options}) in Gridsome main.js which is displaying on all pages.
How to add plugin for a particular page only in gridsome?
I've never used ReCaptcha or Gridsome before, but generally, if you install a plugin using npm, then the simplest way to use it on a single page would be to import the plugin to the specific component rendered on the route you want to use it on. i.e
/* === MyComponent.vue === */
<script>
import plugin from 'packageName';
// or
import { pluginExport } from 'packageName';
export Default{
// You can then use the plugin/pluginExport here
}
From there you should be able to use the package in that specific component as you normally would if you implemented it app-wide with Vue.use. In some cases, depending on how the plugin is meant to be used, you may need to register the imported plugin Module as a child component in the components object. Like this vuejs QR Code generator for example.

How do I load a Vue template from a hosted html file (no webpack, etc)

I am trying a new way of writing my ui and I am using straight ESM loading with Vue. As such I am trying to load my HTML files like I would with say Webpack. I have a simple example of what I am talking about. I basically want to take...
export default {
template: "<div>Here is the component. I want this template to be an html file without webpack</div>"
// I want this to be from a url say mysite.net/viewport.html
}
I tried the simple things like
import Template from "/viewport.html"
But of course that didn't work
I think there might be something I can do with dynamic components. Has anyone tried this an come up with a good solution?

path-to-regexp Find regular expression matching the route

I am adding dynamic child components while the page loads. Adding child routes in OnCreated of parent does not make the page work when we refresh the page.
Hence, I am parsing the page templates (as I know them when the page loads).
I am now looking for a way to know the route which matches the href. Vue-js uses path-to-regexp and my question is very simple.
I want to know the matching component
const router = new VueRouter({
routes: [
// dynamic segments start with a colon
{ path: '/user/:id', component: User },
{ path: '/foo/bar', component: FooBar },
]
})
// Reverse of this
var matchingComponent = howDoIDothis(/foo/bar) // this should give me the matching
I need this so that I can remove from the path and then add the child component to the parent dynamically.
You need to use Vue router's router.getMatchedComponents method. However, this method needs that your router is fully initialized with all the routes. Otherwise, there is no way. Vue-router doesn't expose underlying parsed Regular expressions against which you can compare your href.
Also, what you are trying to do is not the most idiomatic way of doing things in Single Page Applications. A good practice is to declare all your routes upfront in some JS file using which you should initialize your router. Of course, you will want to protect certain routes for which you should use Route guards.
Finally, when you have all your routes declared upfront means you have all the components bundled upfront in one big JS file. To avoid this, wrap your component in async wrappers and bundler like Webpack would be smart enough to split the bundle into multiple smaller files.

How to implement a sidebar that is bound to the route in nuxtjs

so I structured my pages folder like this
pages/
--index/
----page1/
------_slug.vue
----page2/
------_slug.vue
----page1.vue // contains different content
----page2.vue // contains different content
--index.vue
so the routes can be accessed like
/index
/index/page1
/index/page2
/index/page1/some-slug-here
/index/page2/some-slug-here
now, what I want to achieve is, when I access the route /index/page2/some-slug-here. it will show the sidebar component based on that route param.
so to show some visual, take a look at the attached image.
since nuxt don't seem to support named view routes. are there any other ways to achieve what I want?
thanks.
Nuxt.js does support named views. They are referenced as layouts in documentation and serve exactly that purpose.
It is possible to create multiple layouts in layouts folder and specify them for each page as following:
<template>
<!-- Your template -->
</template>
<script>
export default {
layout: 'sidebar'
// page component definitions
}
</script>