Preface
Still the same, if you know how to use a common library, you also need to understand its principles or how to simulate and implement it. Today, you will implement vue-router.
I mentioned some knowledge in this article, so I won't write it step by step here. Please see meHandwritten a simple Vuex
Basic skeleton
- The way to use plugins in Vue is
(plugin)
, here is the usage of it:
Install the plugin. If the plugin is an object, the install method must be provided. If the plugin is a function, it will be used as the install method. When the install method is called, Vue will be passed in as a parameter. The first parameter of this method is the Vue constructor, and the second parameter is an optional option object.
- Global mixing
use(mixin)
Global registration is a mixed in, affecting every Vue instance created after registration. You can use blending to inject custom behavior into components, which will affect each Vue instance created later.
- Routing usage
For example, simple:
//Route arrayconst routes = [ { path: '/', name: 'Page1', component: Page1, }, { path: '/page2', name: 'Page2', component: Page2, }, ] const router = new VueRouter({ mode: 'history', // model routes, })
It's passed inmode
androutes
When we realize it, we need toVueRouter
Received in the constructor.
When using routing titles:
<p> <!-- use router-link Components to Navigate. --> <!-- By passing `to` Properties specify link. --> <!-- <router-link> By default it will be rendered into one `<a>` Label --> <router-link to="/page1">Go to Foo</router-link> <router-link to="/page2">Go to Bar</router-link> </p> <!-- Routing exit --> <!-- The component that the route matches will be rendered here --> <router-view></router-view>
Therefore we need to use( id, [definition] )
Register a global component.
After understanding the general situation, we can write a basic skeleton
let Vue = null class VueRouter { constructor(options) { = || 'hash' = || [] } } = function (_Vue) { Vue = _Vue ({ beforeCreate() { // Root component if (this.$options && this.$) { this._root = this // Save the current vue instance to _root this._router = this.$ // Mount the router instance on _router } else if (this.$parent && this.$parent._root) { // For child components, inherit the instance of the parent component and let all components share a router instance this._root = this.$parent && this.$parent._root } }, }) ('router-link', { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: 'a', // router-link is rendered to a tag by default }, }, render(h) { let tag = || 'a' return <tag href={}>{this.$}</tag> }, }) ('router-view', { render(h) { return h('h1', {}, 'Where the view is displayed') // Temporarily set it to h1 tag, it will be changed below }, }) } export default VueRouter
mode
vue-router
There are two modes, and the default is hash mode.
history mode
pass
Add browser history and listen throughpopState
Events, that is, listen for changes in history to load the corresponding content.
- popstate event
The popstate event is triggered when the activity history entry changes. If the activated history entry is created by a call to () or is affected by a call to (), the state property of the popstate event contains a copy of the state object of the history entry.
- ()method
(state, title, url)
This method is used to add a record in the history and receive three parameters, in turn:
- state: A state object associated with the added record, mainly used for popstate events. When this event is fired, the object is passed into the callback function. In other words, the browser will serialize the object and keep it locally. When reloading this page, you can get the object. If this object is not needed, you can fill in null here.
- title: The title of the new page. However, all browsers now ignore this parameter, so you can fill in the blank string here.
- url: The new URL must be in the same domain as the current page. The browser's address bar will display this URL.
hash mode
Use the hash of the URL to simulate a complete URL. , listen for hashchange event, and then load the corresponding content according to the hash value (can be read through attributes).
Continue to add code,
let Vue = null class HistoryRoute { constructor() { = null // Current path } } class VueRouter { constructor(options) { = || 'hash' = || [] = () = new HistoryRoute() // Current route () // Initialize the routing function } createMap(routes) { return ((pre, current) => { pre[] = return pre }, {}) } initRoute() { if ( === 'hash') { // First determine whether the user has a hash value when opening it. If not, jump to #/ ? '' : ( = '/') ('load', () => { = (1) }) ('hashchange', () => { = (1) }) } else { // history mode ? '' : ( = '/') ('load', () => { = }) ('popstate', () => { = }) } } } = function (_Vue) { Vue = _Vue ({ beforeCreate() { if (this.$options && this.$) { this._root = this this._router = this.$ (this, '_route', this._router.history) // Listen to history path changes } else if (this.$parent && this.$parent._root) { this._root = this.$parent && this.$parent._root } // Return the router instance when accessing this.$router (this, '$router', { get() { return this._root._router }, }) // When accessing this.$route, the current page routing information is returned (this, '$route', { get() { return this._root._router. }, }) }, }) } export default VueRouter
router-link and router-view components
= function (_Vue) { Vue = _Vue ('router-link', { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: 'a', }, }, methods: { handleClick(event) { // Prevent the default jump of a tag event && && () let mode = this._self._root._router.mode let path = this._self._root._router. = path if (mode === 'hash') { (null, '', '#/' + (1)) } else { (null, '', (1)) } }, }, render(h) { let mode = this._self._root._router.mode let tag = || 'a' let to = mode === 'hash' ? '#' + : ('render', ) return ( <tag on-click={} href={to}> {this.$} </tag> ) // return h(tag, { attrs: { href: to }, on: { click: } }, this.$) }, }) ('router-view', { render(h) { let current = this._self._root._router. // Current is already a dynamic response let routesMap = this._self._root._router.routesMap return h(routesMap[current]) // Dynamic rendering of corresponding components }, }) }
At this point, a simple vue-router has been implemented, and the complete code of the case is attached:
let Vue = null class HistoryRoute { constructor() { = null } } class VueRouter { constructor(options) { = || 'hash' = || [] = () = new HistoryRoute() // Current route // Initialize the routing function () } createMap(routes) { return ((pre, current) => { pre[] = return pre }, {}) } initRoute() { if ( === 'hash') { // First determine whether the user has a hash value when opening it. If not, jump to #/ ? '' : ( = '/') ('load', () => { = (1) }) ('hashchange', () => { = (1) }) } else { // history mode ? '' : ( = '/') ('load', () => { = }) ('popstate', () => { = }) } } } = function(_Vue) { Vue = _Vue ({ beforeCreate() { // Root component if (this.$options && this.$) { this._root = this // Save the current vue instance to _root this._router = this.$ // Mount the router instance on _router (this, '_route', this._router.history) // Listen to history path changes } else if (this.$parent && this.$parent._root) { // For child components, inherit the instance of the parent component and let all components share a router instance this._root = this.$parent && this.$parent._root } // Return the router instance when accessing this.$router (this, '$router', { get() { return this._root._router }, }) // When accessing this.$route, the current page routing information is returned (this, '$route', { get() { return this._root._router. }, }) }, }) ('router-link', { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: 'a', }, }, methods: { handleClick(event) { // Prevent the default jump of a tag event && && () // Prevent the default jump of a tag let mode = this._self._root._router.mode let path = this._self._root._router. = path if (mode === 'hash') { (null, '', '#/' + (1)) } else { (null, '', (0)) } }, }, render(h) { let mode = this._self._root._router.mode let tag = || 'a' let to = mode === 'hash' ? '#' + : return ( <tag on-click={} href={to}> {this.$} </tag> ) // return h(tag, { attrs: { href: to }, on: { click: } }, this.$) }, }) ('router-view', { render(h) { let current = this._self._root._router. // Current is already dynamic let routesMap = this._self._root._router.routesMap return h(routesMap[current]) // Dynamic rendering of corresponding components }, }) } export default VueRouter
ps: Personal Technology Blog Github Repository, if you think it's good, welcome star, give me some encouragement and continue writing ~
The above is the detailed content of how to write simple Vue Router. For more information about simple Vue Router, please follow my other related articles!