When I do the Vue quickstart and it creates a HelloWorld application, I see that App.vue line 20 contains this line:
<RouterView />
I can't find any documentation for RouterView. It seems odd that a quickstart / tutorial would include an undocumented tag. I do see router-view, is that the same thing?
The RouterView or router-view component is used to display the component or template that corresponds to the current route.
Source: vue-router.d.ts
/**
* Component to display the current route the user is at.
*/
export declare const RouterView: new () => {
$props: AllowedComponentProps & ComponentCustomProps & VNodeProps & RouterViewProps;
$slots: {
default: (arg: {
Component: VNode;
route: RouteLocationNormalizedLoaded;
}) => VNode[];
};
};
Here is a webpage detailing how to use the RouterView component: How to Use Vue Router's router-view Component
After doing some of my own experimenting, I created a vue app (with Vue Router), I found that my components were not being displayed even if I was at the specified route. After adding the RouterView component to my App.vue template, I was able to see the view that was specified by the route.
Edit:
I'd suggest looking through the following tutorial:
Create your own Vue.js Router. After I created my own router I can now understand why this component is present. The component will render the component that the route specifies, therefore, when the route changes the component rendered will change.
From Vue docs for Component Registration > Name Casing:
When defining a component with PascalCase, you can use either case when referencing its custom element. That means both <my-component-name> and <MyComponentName> are acceptable. Note, however, that only kebab-case names are valid directly in the DOM (i.e. non-string templates).
So <RouterView /> is the same as <router-view />.
Related
When I search for something I came across this post
Here, something, I believe it is component, is defined as below.
export default {
name: 'app',
methods: {
testFunction: function (event) {
console.log('test clicked')
}
},
components: {
Test
}
}
As per the documentation, I came across this
import BaseButton from './BaseButton.vue'
import BaseIcon from './BaseIcon.vue'
import BaseInput from './BaseInput.vue'
export default {
components: {
BaseButton,
BaseIcon,
BaseInput
}
}
I really not sure, whether app is a component which contains Test. Is it the component definition in export? How do we understand that is a component from vue code?
Is it only by the below ways?
Vue.component
components in Vue instance
Not sure - the export default way?
I understand that I sound different because it is Javascript. Could someone help me with this?
There are conventionally, three different types of components in Vue JS.
Root Component
View Component
Normal Component
In a conventional structure the Root component is named 'app' and is passed to the Vue instance when initializing the App for the first time. This component can not be imported and reused inside other components as it will cause a recursive effect. For example this App.vue file is a Root component. It is used inside this main.js file and passed to the Vue instance using new Vue.
The View components are dynamically added or removed from the Root component based on the route. They are written and act as normal component and are only used for Vue router component property. For example the Home and Comments components inside this Router index file are known as View components. They are passed inside the route objects as components inside individual routes. When the app navigates to that particular route, the <router-view> template inside the App.vue file gets replace with the template of the corresponding View component.
Normal components can be used anywhere and are imported by other components. They can be imported inside the View components as well as the Root components. For example, in root component App.vue we see the component Navbar is used. In View component Comments.vue the Replies component is used.
All these components are identical in declaration and behavior but differ in usage.
In order to use a dynamically-defined single page component, we use the component tag, thusly:
<component v-bind:is="componentName" :prop="someProperty"/>
...
import DynamicComponent from '#/components/DynamicComponent.vue';
...
components: {
DynamicComponent
},
props: {
componentName: String,
someProperty: null,
}
The problem is, this isn't really very dynamic at all, since every component we could ever possibly want to use here needs to be not only imported statically, but also registered in components.
We tried doing this, in order at least to avoid the need to import everything:
created() {
import(`#/components/${this.componentName}.vue`);
},
but of course this fails, as it seems that DynamicComponent must be defined before reaching created().
How can we use a component that is truly dynamic, i.e. imported and registered at runtime, given only its name?
From the documentation: Emphasis mine
<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component>
In the example above, currentTabComponent can contain either:
the name of a registered component,
or a component’s options object
If currentTabComponent is a data property of your component you can simply import the component definition and directly pass it to the component tag without having to define it on the current template.
Here is an example where the component content will change if you click on the Vue logo.
Like this:
<component :is="dynamic" />
...
setComponentName() {
this.dynamic = () => import(`#/components/${this.componentName}.vue`);
},
Solution for Nuxt only
As of now its possible to auto-import components in Nuxt (nuxt/components). If you do so, you have a bunch of components ready to be registered whenever you use them in your vue template e.g.:
<MyComponent some-property="some-value" />
If you want to have truly dynamic components combined with nuxt/components you can make use of the way Nuxt prepares the components automagically. I created a package which enables dynamic components for auto-imported components (you can check it out here: #blokwise/dynamic).
Long story short: with the package you are able to dynamically import your components like this:
<NuxtDynamic :name="componentName" some-property="some-value" />
Where componentName might be 'MyComponent'. The name can either be statically stored in a variable or even be dynamically created through some API call to your backend / CMS.
If you are interested in how the underlying magic works you can checkout this article: Crank up auto import for dynamic Nuxt.js components
According to the official Documentation: Starting from v2.13, Nuxt can auto import your components when used in your templates, to activate this feature, set components: true in your configuration
you are talking about async components. You simply need to use the following syntax to return the component definition with a promise.
Vue.component('componentName', function (resolve, reject) {
requestTemplate().then(function (response) {
// Pass the component definition to the resolve callback
resolve({
template: response
})
});
})
Should I always be using <router-link> over <a> even if I am linking to something like a social media page outside the app?
<router-link> is intended for in-app links (e.g., to a page within your app). Use <a> for external links.
Router link : if we use router link the page will not reload but with <a> link the navigation occured through page refresh.
‘vue-router’ is a separate package to Vue and is installed by ‘webpack’.
Routes are set up in router/index.js
Import to Router from vue-router which is in node_modules.
import Router from 'vue-router'
... new Router...
creates an instance of Router which is an object with a property ‘routes’ which is an array of object. Each of those objects is a route with properties for ‘path’, ‘name’ which is what it is called and ‘component’, the component that is called when the route is used.
{
path: '/about',
name: 'About',
component: About
}
We need to import the component and we use the # which brings the path to the root of the project which is the ‘src’ directory.
import About from '#/components/About'
The component gets loaded into the root component App.vue using,
<router-view/>
and where that tag is in the App.vue. This would allow us to place a navbar, header and footer for example around this About component. So that when you go to …/about only the about component in the page changes and the whole page doesn’t refresh.
Next create a NavBar component and place it in the App.vue template.
This will work,
About
however in vue it should be done like this,
<router-link to="/about>About</router-link>
When <router-link> is rendered to the browser it becomes <a> so in the css we still reference it as ‘a’ not as ‘router-link’.
We can data bind using the ‘to’ attribute in <router-link>like this,
:to={ name: 'About'}
where ‘name’ is the property in the ‘routes’ array of object in the main.js routes. This makes the route dynamic.
Using this data bind to change to ‘/about’ to something else such as ‘abt’ you only need to change,
path: 'abt',
in the routes array of objects.
Consider about routes below:
/form/1
/form/2
/form/3
When the address is / and I click on /form/1 VueRouter loads my component inside router-view but when I'm in /form/1 by clicking on /form/2 nothing happens!
You need to watch for param changes in the $route and perform the correct action (e.g. making an ajax call to retrieve the information for the given id), so:
watch: {
'$route' (to, from) {
// React to route change
}
}
You may also use the beforeRouteUpdate guard (see: https://router.vuejs.org/en/essentials/dynamic-matching.html)
You can also add a unique key attribute to the router-view so that vue forcefully replaces the component instead of reusing it
<router-view :key="$route.path"></router-view>
Can anybody tell me if there is a way to access the route params directly inside the route objects?, I need to require different components based on the route object.
router.map({
'/dashboard/*': {
component: Home
},
'/dashboard/:module': {
component: Module,
subRoutes: {
'/': {
component: require('./components/'+this.$route.params.module+'.vue')
},
'/:tab': {
component: require('./components/'+this.$route.params.tab+'.vue')
}
}
}
});
You can't require one or another component depending on the route parameters directly in the router configuration. What you can do instead is create a wrapper component that will use a component or another depending on the route parameters, as the route parameters are accessible from any components.
As written in the vue-router documentation:
The route object will be injected into every component in a vue-router-enabled app as this.$route, and will be updated whenever a route transition is performed.
Every of your components have access to the current route through this.$route therefore you could do something like this:
<template>
<component-a v-if="$route.params.param1 === 'a'></component-a>
<component-b v-if="$route.params.param1 === 'b'></component-b>
</template>
I haven't seen the use of $route.params inside the route objects. What you can do though, in your vue you can dynamically load different components based on your $route.params
<component-a v-if="$route.params == 'a'"></component-a>