Sitio web de prueba de alta frecuencia para entrevistas front-end: principio de Vue (comprender el modelo MVVM, cambios de datos en profundidad/supervisión, cambios de matriz de supervisión, comprensión profunda de DOM virtual)

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. Principio Vue

1. Comprender el modelo MVVM

en componentes

  • La creación de componentes consiste en dividir una página en pequeños módulos funcionales.
  • Cada módulo funcional pertenece a su propia parte de la función independiente
  • Facilita la gestión y el mantenimiento de toda la página.
  • asp jsp php ya está dividido en componentes
  • También hay una creación de componentes similar en nodejs.

vista basada en datos

  • Los componentes tradicionales solo se renderizan estáticamente y las actualizaciones también dependen de la operación del DOM
  • Vistas basadas en datos - Vue MVVM
  • Vistas basadas en datos - React setState

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

2. La API central para monitorear cambios de datos

  • Una vez que los datos de los datos del componente cambian, la actualización de la vista se activa inmediatamente
  • El primer paso para implementar una vista basada en datos
  • API principal - Object.defineProperty
  • Debido a algunas desventajas de Object.defineProperty, Vue3.0 usa Proxy
  • Pero Proxy no es compatible y no se puede polillenar

Uso básico de Object.defineProperty()

Ejemplo: uso básico

const data = {
    
    }
const name = 'zhangsan'

Object.defineProperty(data, "name", {
    
    
    get: function () {
    
    
        console.log('get')
    },
    set: function (newVal) {
    
    
        console.log('set')
        name = newVal
    }
})

console.log(data.name) // get zhangsan
data.name = 'lisi' // set

3. ¿Cómo vue monitorea profundamente los cambios de datos?

Desventajas de Object.defineProperty

  • El monitoreo profundo requiere recursión hasta el final y una gran cantidad de cálculos a la vez
  • No se pueden monitorear propiedades nuevas/eliminadas (Vue.set, Vue.delete)

Ejemplo: la vista se actualiza tres veces y las propiedades nuevas y eliminadas no se pueden monitorear

// 触发更新视图
function updateView() {
    
    
    console.log('视图更新');
}

// 重新定义属性,监听起来
function defineReactive(target, key, value) {
    
    
    // 深度监听
    observer(value)
    // 核心 API
    Object.defineProperty(target, key, {
    
    
        get() {
    
    
            return value
        },
        set(newValue) {
    
    
            if(newValue !== value) {
    
    
                // 深度监听
                observer(value)

                // 设置新值
                // 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
                value = newValue

                // 触发更新视图
                updateView()
            }
        }
    })
}

// 监听对象属性
function observer(target) {
    
    
    if (typeof target !== 'object' || target === null) {
    
    
        // 不是对象或数组
        return target
    }

    // 重新定义各个属性(for in 也可以遍历数组)
    for (let key in target) {
    
    
        defineReactive(target, key, target[key])
    }
}

// 准备数据
const data = {
    
    
    name: 'zhangsan',
    age: 20,
    info: {
    
    
        address: '北京' // 需要深度监听
    }
}

// 监听数据
observer(data)

// 测试
data.name = 'lisi'
data.age = 21
// console.log('age', data.age)
data.x = '100' // 新增属性,监听不到 —— 所以有 Vue.set
delete data.name // 删除属性,监听不到 —— 所以有 Vue.delete
data.info.address = '上海' // 深度监听
// data.nums.push(4) // 监听数组

inserte la descripción de la imagen aquí

4. ¿Cómo cambia la matriz de monitores vue?

Desventajas de Object.defineProperty

  • El monitoreo profundo requiere recursión hasta el final y una gran cantidad de cálculos a la vez
  • No se pueden monitorear propiedades nuevas/eliminadas (Vue.set, Vue.delete)
  • No se pueden monitorear los arreglos de forma nativa, se requiere un manejo especial

Ejemplo:

// 触发更新视图
function updateView() {
    
    
    console.log('视图更新');
}

// 重新定义数组原型
const oldArrayProperty = Array.prototype

// 创建新对象,原型指向 oldArrayProperty,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
    
    
    arrProto[methodName] = function () {
    
    
        updateView() // 触发视图更新
        oldArrayProperty[methodName].call(this, ...arguments)
        // 相当于 Array.prototype.push.call(this, ...arguments)
    }
})

// 重新定义属性,监听起来
function defineReactive(target, key, value) {
    
    
    // 深度监听
    observer(value)
    // 核心 API
    Object.defineProperty(target, key, {
    
    
        get() {
    
    
            return value
        },
        set(newValue) {
    
    
            if(newValue !== value) {
    
    
                // 深度监听
                observer(value)

                // 设置新值
                // 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
                value = newValue

                // 触发更新视图
                updateView()
            }
        }
    })
}

// 监听对象属性
function observer(target) {
    
    
    if (typeof target !== 'object' || target === null) {
    
    
        // 不是对象或数组
        return target
    }

    // 如果是数组,就把 arrProto 赋值给数组的原型
    if (Array.isArray(target)) {
    
    
        target.__proto__ = arrProto
    }

    // 重新定义各个属性(for in 也可以遍历数组)
    for (let key in target) {
    
    
        defineReactive(target, key, target[key])
    }
}

// 准备数据
const data = {
    
    
    name: 'zhangsan',
    age: 20,
    info: {
    
    
        address: '北京' // 需要深度监听
    },
    nums: [10, 20, 30]
}

// 监听数据
observer(data)

// 测试 - 监听数组
data.nums.push(4) // 监听数组

inserte la descripción de la imagen aquí

5. DOM virtuales

  • vdom es una piedra angular importante para implementar vue y reaccionar
  • El algoritmo diff es la parte central y más crítica de vdom
  • La manipulación de DOM requiere mucho rendimiento
  • Antes de usar jQuery, puede controlar el tiempo de las operaciones DOM usted mismo y ajustar manualmente
  • Vue y React son vistas basadas en datos que usan VDOM

(1) Solución: VDOM

  • Con cierta complejidad, es difícil reducir el número de cálculos.
  • ¿Puede el cálculo, más trasladado al cálculo JS? Porque JS se ejecuta muy rápido
  • vdom: simule la estructura DOM con JS, calcule cambios mínimos, manipule DOM

(2) Simular la estructura DOM con JS

Ejemplo: JS simula la estructura DOM

Código HTML

<div id="div1" class="container">
    <p>vdom</p>
    <ul style="font-size: 20px">
        <li>a</li>
    </ul>
</div>

codigo js

{
    
    
    tag: 'div',
    props: {
    
    
        className: 'container',
        id: 'div1'
    }
    children: [
        {
    
    
            tag: 'p',
            children: 'vdom'
        },
        {
    
    
            tag: 'ul',
            props: {
    
    style: 'font-size: 20px'}
            children: [
                {
    
    
                    tag: 'li',
                    children: 'a'
                }
            ]
        }
    ]
}

(3) Aprender vdom a través de snabbdom

Ejemplo:

<div id="container"></div>
<button id="btn-change">change</button>

<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>


const snabbdom = window.snabbdom

// 定义 patch
const patch = snabbdom.init([
    snabbdom_class,
    snabbdom_props,
    snabbdom_style,
    snabbdom_eventlisteners
])

// 定义 h
const h = snabbdom.h

const container = document.getElementById('container')

// 生成 vnode
const vnode = h('ul#list', {
    
    }, [
    h('li.item', {
    
    }, 'Item 1'),
    h('li.item', {
    
    }, 'Item 2')
])
patch(container, vnode)

document.getElementById('btn-change').addEventListener('click', () => {
    
    
    // 生成 newVnode
    const newVnode = h('ul#list', {
    
    }, [
        h('li.item', {
    
    }, 'Item 1'),
        h('li.item', {
    
    }, 'Item B'),
        h('li.item', {
    
    }, 'Item 3')
    ])
    patch(vnode, newVnode)

    // vnode = newVnode // patch 之后,应该用新的覆盖现有的 vnode ,否则每次 change 都是新旧对比
})

Antes de cambiar:

inserte la descripción de la imagen aquí
Después de cambiar:
inserte la descripción de la imagen aquí

(4) resumen vdom

  • Simule la estructura DOM con JS (vnode)
  • Compare los vnodes antiguos y nuevos, obtenga el rango de actualización más pequeño y finalmente actualice el DOM
  • Controle de manera efectiva las operaciones DOM en un modo de vista basado en datos

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

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

Supongo que te gusta

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