How to load routes on initialization (Framework7+Vue) - vuejs2

I am trying to build an app with framework7 and vue. All is well, except that when I start the app, it does not load the component specified on routes.js. I want it to load the component specified by the root url. How can I do this?
main.js
new Vue({
el: '#app',
// Init Framework7 by passing parameters here
framework7: {
root: '#app',
/* Uncomment to enable Material theme: */
material: true,
swipePanel: 'left',
routes: Routes,
pushState: true,
animateNavBackIcon: true,
input: {
}
},
})
routes.js
export default [
{
path: '/',
component: require('./assets/vue/pages/home.vue')
}
]

I decided to use the preroute object on framework7 Initialization, so that even before '/' route is loaded, I can manipulate the request and redirect to a particular route. Read more on preroute here: https://framework7.io/docs/init-app.html

I'm not sure it is the same case as yours:
At first time, I did not add f7-view in my application.html, and the route did not work.
After adding <f7-view main>, the route started work and show the page.
I think f7-view is almost like router-view, is a output interface of the routing result.
If you add f7-view already, then just ignore this answer :-)

Related

How to implement permalinks in a serverless Vue SPA

I made this little app which is a simple Vue serverless SPA. I wish to pass an array of strings and a an array of numbers through the URL so that I can share "states" of the websites with colleagues. I understand vue-routercan update the route's parameters as per their documentation, but I do not have enough perspective to see how to implement this to solve my problem. I would love some help or guidance so I actually learn from this. Thank you all.
EDIT: after Mr. Luis Brito's hint.
I added the following to my code (props)
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: require('#/views/Home').default,
props: { myNumbers: [1,2,3]}
},
]
})
in a component I did
mounted () {
this.$router.push({ name: 'myNumbers', params: {myNumbers: [1,2,3,4] }})
const myNumbers = this.$route.params.myNumbers
console.log(myNumbers);
}
But now my App throws a Vue-Router error [vue-router] Route with name 'myNumbers' does not exist but it does console log the numbers I pushed. Is it possible to make my app look for props and only if they are there to do something with them? Otherwise I get a white screen.
The way I see to solve this problem is use vue-router with a route that passes props to the component, that prop can be an object containing the two arrays that you mentioned.
Referer to Vue Router - Obect Mode
Here is an example for the router:
const routes = {
path: '/promotion/from-newsletter',
component: Promotion,
props: { myNumbers: [1,2,3,5,8], myStrings: ['first', 'second', 'third']
}
}
On the component side, you can access those props on created() lifecycle hook, or mounted()
props: ['myNumbers','myStrings '],
mounted() {
if ( this.myNumbers !== undefined && this.myStrings !== undefined ) {
console.log(thys.myNumbers, this.myStrings);
}
}
So that http://localhost:8080/?myStrings=layer1,layer2,layer3&myNumbers=-1,2,3-4 would console log layer 1-3 and the numbers.
EDITED
TO pass the values programatically, would be better to use Function Mode to capture the URL params and pass it to component. Another way would be to create a component where you can input the numbers and strings that you want, and then call the router and pass those values to the route for the final destination component.

Is there any way to have dynamic routes/components in vuejs router?

Hi beautiful Vuejs developers out there!
I have a little problem with routing many Vue components/pages dynamically. In this scenario I am using nested routes to have a couple of routes for my layout components and hundreds of child routes for my pages and as you can imagine I'll have to type many child routes statically or manually, and then add more when I need more child routes in the future code changes but I need a solution to simplify/solve this problem with more efficient/better way like adding those routes from what user types after the layout in the url... here is my example code code:
const routes: RouteRecordRaw[] = [
{
{
path: '/student',
component: () => import('layouts/StudentLayout.vue'),
children: [
{
path: 'dashboard',
component: () => import('pages/student/Dashboard.vue'),
},
{
path: 'profile',
component: () => import('pages/student/Profile.vue'),
},
],
},
}
As you see in this code I have a layout named Student and it has two children but I'll have to type manually hundreds of child routes for this layout and other layouts is there any way to dynamically set up those routes with what users enter after the layout name like /student/dashboard or /layout/page and match it with a component name? I mean like params in Angular, can I use the param value itself inside the router to say?
{
path: ':pagename',
component: (pagename) => import('pages/student/' + pagename + '.vue'),
},
let me know if there is an efficient way to solve this problem.
Thanks in advance!
I would, personally, not use this, or advise such an approach, nor have I done it, but this idea came to me when I read your question:
My best guess would be to have a handler component which renders a component dynamically based on a route parameter (say you have /:subpage as a child to /student and the handler component is set to that route), and an exception handler around that to show a 404 page when the user types in an inexistent/unsupported route.
For example, I would dynamically import the component by the route parameter into a predefined let (e.g. let SubpageComponent; outside the try catch block), have a try catch block around the dynamic import assignment for the respective error where catch would set the variable to a 404 page. Then I would add the SubpageComponent into the data() of the component doing the rendering of the route.
Edit
I've written out come code that, maybe, makes sense.
It's based on https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components
your routes definition, changed
const routes: RouteRecordRaw[] = [
{
path: '/student',
component: () => import('layouts/StudentLayout.vue'),
children: [
{
path: '/:subpage',
component: () => import('pages/student/SubpageRenderer.vue'),
props: true,
},
],
},
]
SubpageRenderer.vue
<script>
export default {
props: ['subpage'],
data() {
return {
currentSubpage: () => import(`./${subpage}.vue`)
}
}
}
</script>
<template>
<component :is="currentSubpage"></component>
</template>
Instead of using the currentSubpage import, you can also use the subpage route prop to bind :is if subpage is the name of a registered component.
Since this would get only "dashboard" from the route, you'd need some namespacing, like "student-dashboard" with the help of template literals. You could make currentSubpage into a template literal that creates the student-${subpage} name.
I'd probably recommend importing the options object of the component designated by the subpage route parameter instead of registering all the components - if you're registering them, you might as well use vue-router the usual way :)
Also, I only think this could work! It should be tested out, and perhaps casing should be kept in mind, and maybe the Layout suffix as well (subpage will probably be all lowercase, and you'll probably have the components named in PascalCase). After uppercasing the first letter, this could also obviously lead to both /student/Dashboard and /student/dashboard being valid routes

How to pre-render multiple Vue app pages?

I'm trying (unsuccessfully) to pre-render the HTML of multiple Vue apps within the same project scaffolded with Vue CLI. I do not want to use Vue Router or Nuxt etc for multiple reasons.
I've tried using prerender-spa-plugin, but since I don't use routes, it only pre-renders the index.
My vue.config.js looks like this:
const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
module.exports = {
pages: {
index: 'src/index.js',
about: 'src/about.js',
},
configureWebpack: {
plugins: [
new PrerenderSPAPlugin({
staticDir: path.join(__dirname, 'dist'),
routes: ['/'],
postProcess(route) {
route.html = route.html.replace('</script><div>', '</script><div id="app" data-server-rendered="true">');
return route;
},
renderer: new Renderer({
headless: true,
renderAfterDocumentEvent: 'render-event',
}),
}),
],
},
};
and my index.js and about.js essentially look like this:
import Vue from 'vue';
import App from './Index.vue';
new Vue({
render: h => h(App),
mounted() {
document.dispatchEvent(new Event('render-event'));
},
}).$mount('#app');
I also have unique public/ index.html and about.html pages.
The routes parameter of prerender-spa-plugin doesn't seem to recognise things like '/about.html'. Is there an easy way of achieving multiple pre-rendered pages?
Do I have to wrestle with the SSR module?
Thanks in advance.
The solution I've found is to call new PrerenderSPAPlugin multiple times, one for each route.
I'm also facing the same issue, i have static html uses vue component and i want to pre-render the vue component in output build directory. I'm using laravel-mix package for build process.
Could you post the full solution for this i.e calling new PrerenderSPAPlugin multiple times, one for each route.
If i can get the full webpack.config.js, it would easy for me to understand and implement the same using laravel-mix.

VueJS cshtml component

I want to use VueJS with .NET Core Razor pages.
boot.ts
import './css/site.css';
import 'bootstrap';
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [
{ path: '/', component: require('./components/home/home.vue.html') },
{ path: '/counter', component: require('./components/counter/counter.vue.html') },
{ path: '/fetchdata', component: require('./components/fetchdata/fetchdata.vue.cshtml') }
];
new Vue({
el: '#app-root',
router: new VueRouter({ mode: 'history', routes: routes }),
render: h => h(require('./components/app/app.vue.html'))
});
Notice the fetchdata.vue.cshtml in the code above. When I run the application, I get the following error:
ERROR in ./ClientApp/components/fetchdata/fetchdata.vue.cshtml
Module parse failed: .\NetCoreVueJs\ClientApp\components\fetchdata\fetchdata.vue.cshtml Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| <template>
| <div>
| <h1>Weather forecast</h1>
# ./ClientApp/boot.ts 9:37-91
# multi event-source-polyfill webpack-hot-middleware/client?
path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.ts
Is it possible to use .cshtml files as components in VueJS?
Yes, you can use Vue in your razor pages, but I think you're approaching it in the wrong way. Remember that the .cshtml files are compiled in the backend side into html markup that is sent to the browser.
If you want to use razor views you will have to mount your VueJS code on the HTML that is generated and sent to the browser. See [his example I created on Codepen to illustrate this, I'm using Pug to mimic something that generates the HTML template and once it is generated I mount Vue JS on it. https://codepen.io/jaireina/pen/MNvvgd
Pug
#app
input(type="text", placeholder="type your name", v-model="name")
each val in [1,2,3]
p.name {{name}}
JS
var app = new Vue({
el: '#app',
data: {
name: ''
}
})
You won't be able to use Vue in the way you're trying, as a single page application and passing it the cshtml files as templates. If you really need to use razor views you can do something to what I mentioned before. But if you want to create a SPA, I would recommend creating an API with .NET and having your Vue app consuming that API.
I hope this helps.

How to add a route in vue.js

I'm a newbie in javascript and vue.js and I'm facing some issue when trying to add a new route in an existing programme.
I created my new component in a separate file called Miniature.vue
I added the new route in the router definition:
export default new Router({
routes: [
{
path: '/certificat/:id',
name: 'Certificat',
component: Certificat
},
{
path: '/miniature/:id',
name: 'Miniature',
component: Miniature
}
]
})
And then, in the vue instantiation, I added my new components and updated the template :
new Vue({
el: '#app',
router,
components: { Certificat, Miniature } ,
template: '<div>
<Certificat></Certificat>
<Miniature></Miniature>
</div>'
})
The previous template was simply
template: '<Certificat/>'
Problem is, the url is either mywebsite/certificat/123 or mywebsite/miniature/123, both routes are executed, and my two components are displayed !
What is the purpose of the template in the Vue constructor anyway? If I remove it, nothing happens.
What am I missing here ??
Those components are supposed to be loaded from your route, so they shouldn't be in your app template (i.e., they should be removed from #app's components and template).
Your app should contain <router-view> somewhere for the route to be rendered. In your case, replace the app template string with <router-view/>.
It should look similar to this:
new Vue({
el: '#app',
router,
template: '<router-view/>'
})
I should mention your router setup is missing a route for / and 404, so the default path and unknown routes will render nothing in your app. Users would have to navigate to the exact routes you've configured to see anything.
Vue doesn't have routing built-in, for routing you'll need the vue-router package.
To get a better understanding of template and Vue in general, I recommend reading the Introduction guide