¿Cuál es el principio de Vue para implementar el salto de enrutamiento y cómo se llama el método js subyacente?
1.
2. Utilice la función window.history de H5, utilizando el hash de la URL. El valor simula la URL completa.
Al empaquetar y crear una aplicación
Al crear una aplicación, el paquete de Javascript puede volverse muy grande y afectar la carga de la página. Sería más eficiente si pudiéramos dividir los componentes correspondientes a diferentes rutas en diferentes bloques de código y luego cargar solo los componentes correspondientes al acceder a la ruta.
Estructura de directorios
Echemos un vistazo a la estructura general de directorios
Las principales preocupaciones relacionadas con el proceso son los componentes y los directorios históricos, y create-matcher. js, crear-ruta-map.js, index.js, install.js, etc. Comenzaremos con application.js básico. A continuación, comenzaremos con el portal de aplicaciones básico y analizaremos todo el proceso de vue-router.
importar Vue desde 'vue'
importar VueRouter desde 'vue-router'
// 1. Complementos
// Instalación componentes lt;router-viewgt; y lt;router-linkgt;
// E inyectar objetos $router y $route en todos los componentes de la aplicación actual
Vue.use(VueRouter)
/ 2. Definición Los componentes utilizados en cada ruta se denominan componentes de enrutamiento
const Home = { template: 'lt.divgt;homelt;/divgt;'
const Foo = { template: 'lt;divgt ;foolt;/divgt;' }
const Bar = { template: 'lt;divgt;barlt;/divgt;' }
// 3. Crear enrutador de instancia VueRouter p>
enrutador constante = nuevo VueRouter({
modo: 'historial',
base: __dirname,
rutas: [
{ ruta: '/', componente: Inicio },
{ ruta: '/foo', componente: Foo },
{ ruta: ' /bar', componente: Bar }
]
})
// 4. Cree e inicie la aplicación
// Asegúrese de que el enrutador se inyecta
// El componente de enrutamiento estará en new Vue({ router, template; :`lt;div id="app"gt; lt;h1gt;Basiclt;/h1gt; lt;ulgt; lt;ligt ; lt;router-link to="/"gt;/lt;/router-linkgt;lt;/ligt; lt;ligt;lt;router-link to="/foo"gt; tonto;/router-linkgt;lt;/ligt; lt;ligt;lt;router-link to="/bar"gt;/barlt;/router-linkgt;lt;/ligt; /p> lt; etiqueta de enlace del enrutador="li" to="/bar"gt;/barlt;/router-linkgt; lt;/ulgt; lt; enrutador-vista class="view"gt;/router-viewgt; lt;/divgt ` }) . $mount('#app')123456789101112131415161718192021222324252627282930313233343536373839404142 Como complemento El paso clave 1 en el código anterior utiliza el mecanismo de complemento proporcionado por Vue.js.use ( complemento) para instalar VueRouter, que llama al método de instalación del objeto del complemento (si el complemento en sí no tiene dicho método, se llama a la función propia del complemento, echemos un vistazo a la implementación específica de); vue-router como complemento. El objeto VueRouter está expuesto en src/index.js y tiene un método de instalación estático: /* @flow */ // Importa la instalación módulo importar {instalar} desde './install'// ... .importar {inBrowser,supportHistory} desde './util/dom'// ... .exportar la clase predeterminada VueRouter { p> // ...} // Asignar instalación VueRouter.install = install // Automáticamente use el complemento if (inBrowser amp ;amp; window.Vue) { window.Vue.use(VueRouter ) }123456789101112131415161718 Puede Mira, esto está escrito Vue.js El enfoque clásico de los complementos. El método de escritura clásico del complemento js es agregar el método de instalación en el objeto del complemento para instalar la lógica específica del complemento. Al mismo tiempo, al final del juicio, si window.Vue. js existe en el entorno del navegador, instálelo en el complemento Vue.js. Vista. install es un módulo separado aquí, así que continuaremos discutiendo la lógica principal de src/install.js en el mismo nivel: //router-view router-link importar componente Ver desde './components/view' importar enlace desde './components/link'// exportar una referencia de Vue exportar let _Vue// instalar función exportar función instalar (Vue) { if (instalar .installed ) return install.installed = true // Asignar referencia privada de Vue _Vue = Vue // inyectar $router $route Object.Object.defineProperty(Vue.prototype, '$router', { get () { return this.$root._router } }) Object.defineProperty (Vue .prototype, '$route', { get () { return this.$root._route } })// beforeCreate mixin Vue. mixin({ beforeCreate () { // Determinar si hay un enrutador if (this.$options.router) { // Asignar _router this ._ router = this.$options.// Inicializar init this._router.init(this) // Definir el objeto _route de respuesta Vue.util.defineReactive (this, '_route'.this._router.history.current) } } } })// Registrar componente Vue.component('router-view', Ver) Vue.component('router-link', Enlace) // ...}. 12345678910111213141516171819202122232425262728293031323334353637383940414243 ¿Algunas preguntas aquí? - ¿Por qué exportar referencias de Vue? El complemento definitivamente no quiere que Vue sea una dependencia al empaquetar, pero sí quiere usar algunos métodos del objeto Vue en sí. Esto se puede lograr de una manera similar a la anterior, es decir. , asignando variables en el momento de la instalación a Vue para que pueda usar ciertos métodos de Vue en otros lugares sin incorporar la dependencia de vue (siempre que prometa usarlo después de la instalación). - ¿Puedo inyectar $router y $route en todos los componentes definiéndolos como propiedades $router y $route de Vue.prototype? Todos los componentes de Vue.js son instancias extendidas de Vue, lo que significa que todos los componentes pueden acceder a las propiedades definidas en el prototipo de la instancia. antes de crear mixin. Esto se discutirá en detalle más adelante al crear instancias de Vue. Crear una instancia de VueRouter En el archivo de entrada, primero crea una instancia de un VueRouter y lo pasa a las opciones de la instancia de Vue. Ahora vaya a la clase VueRouter expuesta en src/index.js: // ... .import { createMatcher } from './create-matcher'// ... .export default class VueRouter { // ... constructor (opciones: RouterOptions = {}) { this.app = null this. opciones = opciones this.beforeHooks = [] this.afterHooks = [] // Crear función de coincidencia this. match = createMatcher(options.routes || []) // Crear una instancia de un registro histórico específico según el modo let mode = options.mode || 'hash' p> this.fallback = modo === 'historia' amp; !supportsHistory if (this.fallback) { modo = 'hash' } if (! inBrowser) { mode = 'abstracto' } this.mode = cambio de modo (modo) { caso 'historial ': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this , opciones.base, this.fallback) break caso 'abstracto': this.history = new AbstractHistory(this) break predeterminado: p> p> assert(false, `modo no válido: ${mode}`) } } // . ..}. 123456789101112131415161718192021222324252627282930313233343536373839 Internamente contiene un paso importante: crear una función de coincidencia. función de coincidencia La función de coincidencia es creada por createMatcher en src/create-matcher.js: /* @flow */ importar Regexp desde 'path-to-regexp'// .import { createRouteMap } desde './.export function createMatcher (rutas: Arraylt; RouteConfiggt;): Matcher { // Crear ruta map const { pathMap, nameMap } = createRouteMap (rutas) // Coincidencia de función de coincidencia ( raw: RawLocation, currentRoute ?Ruta, redirectedFrom?: Ubicación ): Ruta { // ... } función de redireccionamiento ( } p> registro: RouteRecord, ubicación: Ubicación ): Ruta { // ... } alias de función ( registro: RouteRecord, ubicación: Ubicación, matchAs: cadena ) : Ruta { // ... } función _createRoute ( registro: ?RouteRecord, ubicación: Ubicación, redirectedFrom ?) Ruta { if (record amp; record.redirect) { return redirección(record, redirigidoFrom || ubicación) } if (record amp; record.matchAs) { return alias(registro, ubicación, record.matchAs) } return createRoute(registro, ubicación, redirigidoFrom) } // return return match } // ....123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 Se entiende que la ruta correspondiente se genera en base a la configuración de enrutamiento entrante y luego devolver directamente la función coincidente. Continúe usando la función createRouteMap en src/create-route-map.js: /* @flow */import { afirmar, advertir } desde './util/warn ' importar { cleanPath } desde './util/path'// Crear ruta mapexport función createRouteMap (rutas: Arraylt; RouteConfiggt;): { pathMap: Dictionarylt;, nombreMapa:Diccionariolt;RouteRecordgt; }. { // mapa de ruta const pathMap: Dictionarylt; = Object.create(null) // nombre mapa de ruta const nameMap: Dictionarylt; (nulo) // Recorre el objeto de configuración de enrutamiento para agregar registros de enrutamiento routes.forEach(route =gt; { addRouteRecord(pathMap, nameMap, route) }) devuelve { pathMap, nameMap } } } } }//Agregar función de registro de ruta parent?: RouteRecord, matchAs?: string ){ //Obtener ruta y nombre const { ruta, nombre }= ruta assert(ruta! = nulo, se requiere `"ruta" en una configuración de ruta.`) // Objeto de registro de ruta registro constante: RouteRecord = { ruta: normalizePath(ruta, padre), componentes: ruta.componentes || {predeterminado: ruta.components }, instancias: {}, nombre, padre, matchAs, redirección.ruta.redirect, antes de ingresar: ruta.antes de ingresar, meta: ruta.meta || p> if (ruta.niños) {// ... ... ruta.niños.forEach(niño =gt; { addRouteRecord(pathMap, nameMap, child, registro) }) }}) }// Procesar la lógica del alias y agregar los registros correspondientes if (route.children ) { // .../p> if (ruta.alias ! == indefinido) { if (Array.isArray(ruta.alias)) { ruta.alias .forEach (alias =gt; { addRouteRecord(pathMap, nameMap, {path.alias}, parent, record.path) }) } else { addRouteRecord(pathMap, nameMap, { ruta: ruta.alias}, padre, re cord.path) } }//Actualizar mapa de ruta pathMap[record.path] = record //Actualizar mapa de nombres if (nombre) { if (!nameMap[nombre]) { nameMap[nombre] = registro } else { warn(false, `Definición de rutas con nombre duplicadas: { nombre: "${name}", ruta: "${record.path}" }) } } } Función normalizePath (ruta: cadena, padre?: RouteRecord): cadena { ruta = ruta.replace(/\/$/, '') if (ruta[0] === ' / ') ruta de retorno if ( parent == null) ruta de retorno return cleanPath(`${parent.path}/${path}`) }123456789101112131415161718192021222324252627282930313233343536373839404142434445 464 7484950515253545556575859606162636465666768697071727374757677787980818283 Puede ser Como se ve, el trabajo principal a realizar es generar un mapeo de registros de enrutamiento de acuerdo con el objeto de configuración de enrutamiento del usuario, que corresponde al registro de enrutamiento ordinario según la ruta y el nombre, para facilitar la coincidencia posterior. Establecer registros históricos Este también es un paso muy importante. Todas las clases de registros históricos están en el directorio src/history/. No necesitamos preocuparnos por la implementación de cada historial. clase de registro. Para diferencias específicas, solo sepa que ambos heredan de src/history/base.js. Clase de historial: /* @flow *//...import { inBrowser }.import { inBrowser } from './util/dom'import { runQueue } from './util/async' import { START, isSameRoute } de './util/route'// Aquí está el install.js analizado antes de exportar _Vueimport { _Vue } del historial de clases de exportación './install' {// ... constructor (router: VueRouter, base: ?string) { this.router = router this.base = normalizeBase(base) // Comience con un objeto de enrutamiento que represente "ninguna parte" this.current = INICIAR esto. pendiente = null }// ...}// Obtener la función de valor base normalizeBase (base: ?string): string { if (!base) { if (inBrowser) { // respect lt; basegt; etiqueta const baseEl = document. querySelector('base') base = baseEl.getAttribute('href'): '/' } else { base = ' /' } } }// Asegúrate de que haya una barra diagonal inicial if (base.charAt( 0) ! == '/') { base = '/' base