Web front-end interview high-frequency test site - Vue principle (understand MVVM model, in-depth/monitor data changes, monitor array changes, in-depth understanding of virtual DOM)

Series Article Directory

content Reference link
Basic use of Vue The basic use of Vue (one article to master the most basic knowledge points of Vue)
Vue communication and advanced features Communication between Vue components and advanced features (communication between various components, custom v-model, nextTick, slots)
Vue advanced features Advanced features of Vue (dynamic components, asynchronous loading, keep-alive, mixin, Vuex, Vue-Router)
Vue Principle 1 Vue principle (understanding MVVM model, in-depth / monitoring data changes, monitoring array changes, in-depth understanding of virtual DOM)
Vue Principle 2 Vue principle (diff algorithm, template compilation, component rendering and updating, JS implementation routing)
Vue Interview Questions Web front-end interview high-frequency test site - Vue interview questions


1. Vue principle

1. Understand the MVVM model

componentized

  • Componentization is to split a page into small functional modules
  • Each functional module belongs to its own part of the independent function
  • Makes the management and maintenance of the entire page very easy.
  • asp jsp php is already componentized
  • There is also a similar componentization in nodejs

data-driven view

  • Traditional components are only statically rendered, and updates also depend on operating the DOM
  • Data Driven Views - Vue MVVM
  • Data Driven Views - React setState

MVVM model
insert image description here

2. The core API for monitoring data changes

  • Once the data of the component data changes, the update of the view is triggered immediately
  • The first step in implementing a data-driven view
  • Core API - Object.defineProperty
  • Due to some disadvantages of Object.defineProperty, Vue3.0 uses Proxy
  • But Proxy is not compatible and cannot be polyfilled

Object.defineProperty() basic usage

Example: Basic Usage

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. How does vue deeply monitor data changes

Object.defineProperty Disadvantages

  • Deep monitoring requires recursion to the end, and a large amount of calculation at one time
  • Unable to monitor new/deleted properties (Vue.set, Vue.delete)

Example: The view is updated three times, and the new and deleted properties cannot be monitored

// 触发更新视图
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) // 监听数组

insert image description here

4. How does vue monitor array changes

Object.defineProperty Disadvantages

  • Deep monitoring requires recursion to the end, and a large amount of calculation at one time
  • Unable to monitor new/deleted properties (Vue.set, Vue.delete)
  • Unable to natively monitor arrays, special handling is required

Example:

// 触发更新视图
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) // 监听数组

insert image description here

5. Virtual DOM

  • vdom is an important cornerstone for implementing vue and react
  • The diff algorithm is the core and most critical part of vdom
  • DOM manipulation is very performance-intensive
  • Before using jQuery, you can control the timing of DOM operations by yourself and manually adjust
  • Vue and React are data-driven views, using VDOM

(1) Solution: VDOM

  • With a certain complexity, it is difficult to reduce the number of calculations
  • Can the calculation, more transferred to JS calculation? Because JS executes very fast
  • vdom - Simulate DOM structure with JS, calculate minimal changes, manipulate DOM

(2) Simulate DOM structure with JS

Example: JS simulates DOM structure

HTML code

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

JS code

{
    
    
    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) Learning vdom through snabbdom

  • Simple and powerful vdom library, easy to learn and use
  • Vue refers to its implementation of vdom and diff
  • snabbdom reference link

Example:

<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 都是新旧对比
})

Before changing:

insert image description here
After changing:
insert image description here

(4) vdom summary

  • Simulate DOM structure with JS (vnode)
  • Compare the old and new vnodes, get the smallest update range, and finally update the DOM
  • Effectively control DOM operations in a data-driven view mode

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

Click to follow and don't get lost, continue to update...

Guess you like

Origin blog.csdn.net/qq_45902692/article/details/126516912