preface
The rise of single page is inseparable from front-end routing. I remember when I first came into contact with the concept of SPA single page application in my childhood, I once doubted the reliability of this technology and was filled with a lot of puzzlement, such as: Is there no performance problem to write everything on one page? Does the page crash if something goes wrong?
Later, as I did one SPA project after another, I gradually dispelled such concerns. Now let’s study the soul of the order page, routing is how to achieve the logic of it.
The meaning of #(hash) in the URL
For example, vue-Rouer has two working modes: hash and history. Let’s take a look at #hash
The anchor
See # is the most easy to associate with the anchor point, just like reading the nuggets article, you can use the anchor point to realize the jump
This is probably the most essential use of #(hash)
change#
Does not trigger web page reloading
Another important feature of # is that changing the content after # does not cause a page refresh
It is this feature that makes it possible to implement front-end routing using #, and we will make a bold assumption here that the hash implementation will listen for changes after # and dynamically render the corresponding component
History Api
From the perspective of hash, we can draw a simple conclusion that to realize front-end routing, the condition that the page cannot be refreshed when the PAGE URL changes must be met
We found in the History Api that pushState seems to satisfy this condition as well
Next we use code verification, code is also very simple, set a timer, after a period of time through this API to change the page URL, to see if the page refresh
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<title>Document</title>
</head>
<body>
<script>
setTimeout(() = > {
history.pushState(null.""."/a"); // Core code
}, 3000);
</script>
</body>
</html>
Copy the code
Notice that the following URL changes from 127.0.0.1/aa.html to 127.0.0.1/a without refreshing the page.
This also opens up the possibility of implementing front-end routing. Let’s take vue-Router as an example to learn how to realize the front-end routing of SPA.
Vue-router workflow
Vue plug-in
Vue-router is essentially a vUE plug-in
import Vue from "vue";
import VueRouter from "vue-router";
import Home from ".. /views/Home.vue";
Vue.use(VueRouter); // Plugins are used
const routes = [
{
path: "/".name: "Home".component: Home,
},
{
path: "/about".name: "About".component: () = >
import(/* webpackChunkName: "about" */ ".. /views/About.vue"),},];const router = new VueRouter({
routes,
});
export default router;
Copy the code
Since it is a plug-in, we will first clarify the vue plug-in operation mechanism, first to clarify a few questions.
-
What did Vue.Use do?
We can find the answer in the vue2.0 source code
export function initUse(Vue: GlobalAPI) { Vue.use = function (plugin: Function | Object) { const installedPlugins = this._installedPlugins || (this._installedPlugins = []); if (installedPlugins.indexOf(plugin) > -1) { return this; } const args = toArray(arguments.1); args.unshift(this); // Set the first parameter to the vue instance // Core code if (typeof plugin.install === "function") { plugin.install.apply(plugin, args); } else if (typeof plugin === "function") { plugin.apply(null, args); } installedPlugins.push(plugin); return this; }; } Copy the code
The main thing the vue.use() method does is call the plug-in’s install method and pass the vue instance to the plug-in for use. So we must expose an install method for vUE to call when we develop the plug-in
-
Why does vue-rouer need to be mounted in main.js when some plug-ins don’t
This is usually the case when we use vue-Router
//router/index.js import Vue from "vue"; import VueRouter from "vue-router"; Vue.use(VueRouter); // Call vue-router with the use method const routes = []; const router = new VueRouter({ routes, }); export default router; Copy the code
Then mount it in main.js
import Vue from "vue"; import App from "./App.vue"; import router from "./router"; Vue.config.productionTip = false; new Vue({ router / / a mount }).$mount("#app"); Copy the code
When using vue-Router for the first time, I wondered why I would mount it when I already called it using the use method. This is obviously superfluous
However, when I read about vue-Router on the VUE website, I felt there was more to it than that
When we look at the vue-Router source code, we find that adding some component options through global blending means getting the vue-Rouer configuration items through blending
// vue-router src/install.js
Vue.mixin({
beforeCreate () {
// Determine whether it is the root component
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this.'_route'.this._router.history.current) // Set to responsive data
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this.this)
},
destroyed () {
registerInstance(this)}})Copy the code
The question is, why blend in the vue-Router configuration? Vue. Use (vueRouter) is executed before new vue()… It’s too hard to describe in words. Let’s draw pictures
The router is also used in new Vue, but sometimes I think it is unnecessary to mount the router in new Vue. We can also pass the router as an argument, for example:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import VueRouter from "vue-router";
Vue.use(VurRouter,router) // Call use in main.js, passing router as the second parameter
Copy the code
Vue-rotuer configuration items are also available in vue-Router, as shown below:
class VueRouter{}
VueRouter.install=(vue,option) = >{}
Copy the code
So why didn’t Vue-Rotuer do that? Welcome to comment in the comments
vue-router
Operation mechanism
The core function of vue-Router is to automatically render the corresponding component when the URL changes
A picture is worth a thousand words. Let’s summarize vue-Rouer’s main workflow flow chart
There may be some details involved, such as:
<router-view>
and<router-link>
How to achieve;- How components are rendered;
- How to render nested routines
and
are vue global components registered in vue-Rotuer.
is a simple note, which is actually a router-link. We will focus on how to render
and nested routines
It should be noted that component rendering is from outside to inside. Render the parent component first. If there is
in the parent component, render the corresponding child component until all components are rendered. Render is rendered by the H method of the render function. The following is vue-Rouer’s core code about router-View
Simple version ofvue-rotuer
implementation
Vue-rotuer source code is not long, but it is not easy to read it completely. I removed the core code and implemented a simple version of vue-Router, as shown below:
The main functions are:
- Implement the corresponding components according to the route rendering, and achieve nested rendering
- implementation
this.$rouer.push()
Method, and other methods are freely extensible
The details are as follows:
The router – the link
function isActive(location) {
return window.location.hash.slice(1) === location;
}
export default {
functional: true.render(h, { props, slots }) {
const active = isActive(props.to) ? "my-vue-router-active" : "";
return h(
"a",
{
attrs: {
href: ` #${props.to}`.class: [`${active}`],
},
},
slots().default[0].text ); }};Copy the code
The router – the view
export default {
functional: true.render(h, { parent, data }) {
let route = parent.$route;
let matched = route.matched;
data.routerView = true;
let deep = 0;
while (parent) {
if (parent.$vnode && parent.$vnode.data.routerView) {
deep++;
}
parent = parent.$parent;
}
let record = matched[deep];
if(! record) {return h();
}
let component = record.component;
returnh(component, data); }};Copy the code
Source address: simple-vue-router
Personal project: Webpack based automatic routing packaging multi-page application LYh-Pages, welcome everyone star oh, thank you!
The last
If there is help, welcome to praise attention oh! 😘