Sitio web de prueba de alta frecuencia para entrevistas front-end: principio de Vue (algoritmo de diferencias, compilación de plantillas, representación y actualización de componentes, enrutamiento de implementación de JS)

Directorio de artículos de la serie

contenido Link de referencia
Uso básico de Vue El uso básico de Vue (un artículo para dominar los puntos de conocimiento más básicos de Vue)
Comunicación Vue y funciones avanzadas Comunicación entre los componentes de Vue y funciones avanzadas (comunicación entre varios componentes, modelo v personalizado, nextTick, tragamonedas)
Funciones avanzadas de Vue Funciones avanzadas de Vue (componentes dinámicos, carga asíncrona, keep-alive, mixin, Vuex, Vue-Router)
Vue Principio 1 Principio de Vue (comprensión del modelo MVVM, cambios de datos en profundidad/supervisión, cambios de matriz de supervisión, comprensión profunda del DOM virtual)
Vue Principio 2 Principio de Vue (algoritmo de diferencias, compilación de plantillas, representación y actualización de componentes, enrutamiento de implementación de JS)
Preguntas de la entrevista de Vue Sitio web de prueba de alta frecuencia para entrevistas front-end: preguntas de la entrevista Vue


1. Descripción general del DOM virtual - algoritmo diff

Enlace de referencia del algoritmo de diferencias

  • El algoritmo diff es la parte central y más crítica de vdom
  • El algoritmo diff se puede reflejar en el uso diario de vue react (como key)

Descripción general del algoritmo diff:

  • diff es contraste, que es un concepto amplio, como el comando linux diff, el comando git diff
  • Dos objetos js también pueden hacer diferencias.
  • Dos árboles hacen diferencias, como vdom diff aquí

Fuente: https://codificación.imooc.com/lesson/419.html#mid=33875

inserte la descripción de la imagen aquí
La complejidad temporal de la diferencia del árbol es O(n^3)

  • Primero, atraviesa el árbol1
  • Segundo, atravesar tree2
  • Tercero, ordenar
  • 100 nodos, para calcular 1 millón de veces, el algoritmo no está disponible

Optimizar la complejidad del tiempo a O(n)

  • Compare solo el mismo nivel, no entre niveles
  • Si las etiquetas no son las mismas, elimine y reconstruya directamente, y ya no compare en profundidad
  • Si la etiqueta y la clave son iguales, se considera que son el mismo nodo y no se requiere ninguna comparación adicional.

Fuente: https://codificación.imooc.com/lesson/419.html#mid=33875
inserte la descripción de la imagen aquí

2. Compilación de plantillas

1. Compilación de plantillas - con sintaxis

  • Las plantillas son la parte más utilizada del desarrollo de vue, es decir, los principios asociados con el uso
  • No es html, tiene directivas, interpolación, expresiones JS, ¿qué diablos es?

Compilación de plantillas:

  • Requisitos previos: JS con sintaxis
  • vue template complier compila plantillas en funciones de renderizado
  • Ejecute la función render para generar vnode

con sintaxis:

  • Cambie las reglas de búsqueda para variables libres en {}, como atributos obj para buscar
  • Si no se encuentra ninguna propiedad obj coincidente, se informará un error
  • with debe usarse con precaución, rompe las reglas de alcance y es poco legible

Ejemplo: Sin con, la propiedad indefinida en el objeto es indefinida

const obj = {
    
    a: 100, b: 200}

console.log(obj.a) // 100
console.log(obj.b) // 200
console.log(obj.c) // undefined

Usando with, la propiedad que no está definida en el objeto reportará un error

const obj = {
    
    a: 100, b: 200}

// 使用 with,能改变 {} 内自由变量的查找方式
// 将 {} 内自由变量,当作 obj 的属性来查找
with (obj) {
    
    
    console.log(a) // 100
    console.log(b) // 200
    console.log(c) // Uncaught ReferenceError: c is not defined
}

2. ¿En qué se compila la plantilla vue?

Compilación de plantillas:

  • La plantilla no es html, tiene instrucciones, interpolación y expresiones JS, que pueden realizar juicios y bucles.
  • HTML es un lenguaje de etiquetas, solo JS puede realizar juicios y bucles
  • Por lo tanto, la plantilla debe convertirse en algún tipo de código JS, es decir, compilación de plantilla

Ejemplo:

(1) Instalaciónvue-plantilla-compilador

npm i vue-template-compiler --save

(2) Cree el archivo index.js

const compiler = require('vue-template-compiler')

......

// 编译
const res = compiler.compile(template)
console.log(res.render)

(3) Demostración (las siguientes demostraciones están en el archivo index.js...)

Interpolar:

  • El resultado de la impresión es: cree una etiqueta p, el elemento secundario es TextVNode, que es una cadena
  • _c: crearElemento, crear elemento
  • _v: createTextVNode, crea un nodo de texto
  • _s: toString, convertir a tipo de cadena
  • esto: const vm = new Vue({…}), que es la instancia de vm
// 插值
const template = `<p>{
     
     {message}}</p>`
// with(this){return _c('p',['p',[_v(_s(message))]])}
// h -> vnode
// createElement -> vnode

expresión:

  • Las expresiones en la plantilla se ejecutan como código JS
// 表达式
const template = `<p>{
     
     {flag ? message : 'no message found'}}</p>`
//with(this){return _c('p',[_v(_s(flag ? message : 'no message found'))])}

Propiedades y propiedades dinámicas:

  • contenedor, div1 es una cadena estática, por lo que debe estar entre comillas después de la compilación
  • imgUrl es un atributo dinámico y una variable, por lo que no está entre comillas después de la compilación
// 属性和动态属性
const template = `
     <div id="div1" class="container">
         <img :src="imgUrl"/>
     </div>
 `
// with(this){return _c('div',
//      {staticClass:"container",attrs:{"id":"div1"}},
//      [_c('img',{attrs:{"src":imgUrl}})]
// )}

condición:

  • Convertir a una expresión ternaria
// 条件
const template = `
    <div>
        <p v-if="flag === 'a'">A</p>
        <p v-else>B</p>
    </div>
`
// with(this){return _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}

ciclo:

  • _l: renderList, lista de renderizado
  • La segunda devolución, el primer parámetro devuelto es la etiqueta, el segundo parámetro es el atributo y el tercer parámetro es el elemento secundario
// 循环
const template = `
    <ul>
        <li v-for="item in list" :key="item.id">{
     
     {item.title}}</li>
    </ul>
`
// with(this){return _c('ul',_l((list),function(item){return _c('li',{key:item.id},[_v(_s(item.title))])}),0)}

evento:

  • Hay un evento en on, y el nombre de la función es una variable, sin comillas.
// 事件
const template = `
    <button @click="clickHandler">submit</button>
`
// with(this){return _c('button',{on:{"click":clickHandler}},[_v("submit")])}

v-modelo:

// v-model
const template = `<input type="text" v-model="name">`
// 主要看 input 事件
// with(this){return _c('input',{directives:[{name:"model",rawName:"v-model",value:(name),expression:"name"}],attrs:{"type":"text"},domProps:{"value":(name)},on:{"input":function($event){if($event.target.composing)return;name=$event.target.value}}})}

Compile la plantilla:

  • La plantilla se compila en una función de representación y la función de representación se ejecuta para devolver el vnode
  • Ejecutar parche y diff basado en vnode
  • Usando webpack vue-loader, la plantilla se compilará en el entorno de desarrollo

3. Use render en lugar de plantilla en componentes vue

  • En algunos casos complejos, no se puede usar la plantilla y se puede considerar el renderizado.
  • React siempre ha usado render (sin plantillas)
Vue.component('heading', {
    
    
    // template: `xxx`,
    render: function (createElement) {
    
    
        return createElement(
            'h' + this.level,
            [
                createElement('a', {
    
    
                    attrs: {
    
    
                        name: 'headerId',
                        href: '#' + 'headerId'
                    }
                }, 'this is a tag')
            ]
        )
    }
})

Resumir:

  • con sintaxis
  • Plantilla para renderizar función, para vnode, para renderizar y actualizar
  • Los componentes de Vue pueden usar render en lugar de plantilla

4. Resumir el proceso de renderizado/actualización del componente

  • Un componente se representa en la página, la modificación de los datos desencadena una actualización (vista basada en datos)
  • ¿Cuál es la lógica detrás de esto y qué puntos deben dominarse?
  • Examinar la exhaustividad de la comprensión del proceso.

Tres puntos de conocimiento:

  • Responsivo: escuche el setter de getter de propiedad de datos
  • Compilación de plantillas: plantilla para representar la función, luego para vnode
  • vdom:parche(elemento,vnodo) 和 parche(vnodo, nuevoVnodo)

Tres procesos:

  • Proceso de renderizado inicial
  • proceso de actualización
  • Representación asíncrona

3. Cómo se procesan y actualizan los componentes de vue

1. El proceso de renderizado inicial

  • Analice la plantilla en una función de representación (o completada en el entorno de desarrollo, vue-loader)
  • Disparador receptivo, escuche el setter de obtención de propiedades de datos
  • Ejecute la función render para generar vnode, patch(elem, vnode)

2. Ejecutar la función de renderizar activará el getter

  • Los que se usan en la plantilla activarán obtener
  • Los que no se usan en la plantilla no activarán la obtención, porque no tienen nada que ver con la vista.
<p>{
    
    {
    
    message}}</p>

export default {
    
    
  data() {
    
    
    return {
    
    
      message: '杂货铺', // 会触发 get
      city: '北京' // 不会触发 get,因为模板没用到,即和视图没关系
    }
  }
}

3. Proceso de actualización

  • Modifique los datos y active el setter (se ha monitoreado antes en el getter)
  • Vuelva a ejecutar la función render para generar newVnode
  • parche(vnodo, nuevoVnodo)

inserte la descripción de la imagen aquí

4. Cómo renderizar de forma asíncrona con componentes vue

  • $nextTick es asíncrono
  • Resuma la modificación de datos y actualice la vista al mismo tiempo
  • Reduzca el número de operaciones DOM y mejore el rendimiento

4. Cómo implementar el enrutamiento hash con JS

  • El modo de enrutamiento de vue-router: modo hash, historial H5

1. Componentes de la URL de una página web

http://127.0.0.1:8881/01-hash.html?a=100&b=20#/aaa/bbb

location.protocol // 'http:' 【协议】
location.hostname // '127.0.0.1' 【IP地址/域名】
location.host // '127.0.0.1:8881' 【IP地址带端口】
location.port // '8881' 【端口】
location.pathname // '/01-hash.html' 【文件路径名】
location.search // '?a=100&b=20' 【参数】
location.hash // '#/aaa/bbb' 【#及后面的部分】

2. Características del hachís

  • Los cambios hash activarán saltos de página web, es decir, el navegador hacia adelante y hacia atrás
  • Los cambios hash no actualizarán la página, una característica necesaria de SPA
  • El hash nunca se enviará al lado del servidor (el front-end se las arreglará solo)

3. Ejemplo de cambio de hash

  • onhashchange: se usa para monitorear cambios en los valores hash
  • El atributo href es una cadena legible y escribible que establece o devuelve la URL completa del documento que se muestra actualmente.
<p>hash test</p>
<button id="btn1">修改 hash</button>

// hash 变化,包括
// a. JS 修改 url
// b. 手动修改 url 的 hash
// c. 浏览器前进、后退
window.onhashchange = (event) => {
    
    
    console.log('old url', event.oldURL)
    console.log('new url', event.newURL)

    console.log('hash', location.hash)
}

// 页面初次加载,获取 hash
document.addEventListener('DOMContentLoaded', () => {
    
    
    console.log('hash:', location.hash)
})

// JS 修改 url
document.getElementById('btn1').addEventListener('click', () => {
    
    
    location.href = '#/user'
})

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

5. Cómo implementar el enrutamiento de historial H5 con JS

  • Ruta con especificación de URL, pero no actualice la página al saltar
  • historia.pushState
  • ventana.onpopstate

1. Ejemplo

  • history.pushState(estado,título,url)
  • estado: un objeto de estado relacionado con la URL especificada. Cuando se activa el evento popstate, el objeto se pasará a la función de devolución de llamada. Si no necesita este objeto, puede completar nulo aquí
  • título: el título de la nueva página, pero todos los navegadores actualmente ignoran este valor, por lo que puede completar nulo aquí
  • url: La nueva URL, que debe estar en el mismo dominio que la página actual. La barra de direcciones de su navegador mostrará esta URL
<p>history API test</p>
<button id="btn1">修改 url</button>

// 页面初次加载,获取 path
document.addEventListener('DOMContentLoaded', () => {
    
    
    console.log('load', location.pathname)
})

// 打开一个新的路由
// 【注意】用 pushState 方式,浏览器不会刷新页面
document.getElementById('btn1').addEventListener('click', () => {
    
    
    const state = {
    
    name: 'page1'}
    console.log('切换路由到', 'page1')
    history.pushState(state, '', 'page1')
})

// 监听浏览器前进、后退‘
window.onpopstate = (event) => {
    
    
    console.log('onpopstate', event.state, location.pathname)
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

2. Cómo elegir

  • Se recomienda que los sistemas B (para empresas o grupos de usuarios específicos) usen hash, que es fácil de usar e insensible a las especificaciones de URL
  • Para el sistema C (para consumidores individuales), puede considerar elegir el historial H5, pero necesita soporte del servidor
  • Puede elegir simple, no usar complejo, considerar costo y beneficio

不积跬步无以至千里,不积小流无以成江海

Pulsa para seguir y no te pierdas, sigue actualizando...

Supongo que te gusta

Origin blog.csdn.net/qq_45902692/article/details/126565768
Recomendado
Clasificación