• 【Vue原理系列】(一)简要总结Vue3运行时+编译时原理


    前言

    要讨论vue3的运行时和编译时框架设计,我们可以先来看看 什么叫命令式什么叫声明式?
    首先我们先确定 Vue3是运行时+编译时的框架,其次我们再来看看为什么是?单纯的运行时或者编译时又有什么优缺点呢?

    一、命令式和声明式

    命令式框架最突出的就是关注编码过程,例如Jquery就是一个命令式框架哟。

    - 获取id为content的div
    - 设置文本内容为 hello vue
    - 绑定点击事件
    - 点击弹出 nice to meet you!
    // 将其翻译为代码
    $('#content').text('hello vue').on('click',()=>{alert('nick to meet you')})
    // 原生写法
    const div = doucument.querySelector('#content')
    div.innerText = 'hello vue'
    div.addEventListener('click',()=>{alert('nice to meet you')})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    所以,命令式就是看中过程,有种隐隐的过程与代码的逻辑一一对应的感觉。

    声明式更关注结果,内部过程则是予以封装了。
    例如上面的代码可以用声明式的方式:

    <div @click="() => alert('nick to meet you')">hello vue</div>
    
    • 1

    看起来很简洁吧,这是Vue封装后的。但Vue的内部实现一定是命令式的,只是暴露给开发者的是声明式的。

    二、二者的性能比较

    结论:声明式性能<=命令式性能
    1.命令式代码更新性能消耗 = 修改消耗
    2.声明式代码更新性能消耗 = 找出差异的消耗+ 修改差异的消耗
    于是,Vue要做的就是,最小化找出差异的消耗,这里vue使用了虚拟DOM
    虚拟DOM理论上不比原生JS性能高,但这是理论上,因为大多数情况下,写出绝对优化了命令式代码是消耗精力的。

    然后,我们需要明确一点:JS对象操作的效率远高于DOM操作

    那么,在创建页面时
    虚拟DOM需要 创建虚拟JS对象(VNode)+新建DOM元素的Dom操作
    命令式需要:渲染HTML字符串(js)+ 新建DOM元素的Dom操作
    到目前为止,虚拟DOM可能性能上是小于等于命令式的

    但轮到修改页面时:命令式需要进行全量的更新:重新获取HTML字符串 + 销毁DOM + 创建所有新DOM
    虚拟DOM:创建js对象 + 找出差异(js层面) + 更新差异DOM
    两者的性能差异随着页面变大也会越来越大。

    三、运行时和编译时

    我们先来看看

    纯运行时模型:一个Render函数 + 符合树形结构的数据对象

    // 数据对象
    const obj = { 
    	tag:'div',
    	children:[
    	  {tag:'span',children:'hello vue'}
    	]
    }
    // render 函数
    function Render(obj, root) {
        const el = document.createElement(obj.tag)
        if (typeof obj.children === 'string') {
            const text = doucument.createTextNode(boj.children)
            el.appendChild(text)
        } else if (obj.children) {
            //递归render,使用el作为root
            obj.children.forEach(child => Render(child, el))
        }
        root.appendChild(el)
    }
    // 用户直接调用
    Render(obj,doucument.body)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行时 + 编译时模型:一个Render函数 + 一个Compiler函数 + html

    const html = `<div><span>hello vue</span></div>`
    const obj = Compiler(html)
    Render(obj,doucument.body)
    
    • 1
    • 2
    • 3

    编译时模型: 一个Compiler函数 + html

    const html = `<div><span>hello vue</span></div>`
    
    const div = document.createElement('div')
    const span = document.createElement('span')
    span.innerText = 'hello vue'
    div.appendChild(span)
    document.body.appendChild(div)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样就将其直接编译成了命令式代码

    总结

    • 纯运行时:没有编译过程,无法分析用户输入,也就只能傻傻的全局改变
    • 运行时 + 编译时:如果加入编译,则可以分析用户输入,有些可能不会改变,有些内容可能改变了,这样我们修改改变的部分就好啦。
    • 纯编译时:代码必须编译好才能运行,性能更好,但是灵活性较差。

    Vue3选择了运行时 + 编译时,并且其核心也是Diff算法。同时,Vue在保留运行时的情况下,性能也在逼近纯编译时。

  • 相关阅读:
    Java面试八股文宝典:初识数据结构-数组的应用扩展之HashTable
    LVGL---基础对象(lv_obj)
    MySQL入门:如何创建数据库?
    linux命令笔记
    SpringBoot集成腾讯云存储COS服务
    深度学习论文: Segment Any Anomaly without Training via Hybrid Prompt Regularization
    SQL函数和高级语句
    E. Monsters
    LeetCode--1.两数之和
    【机器学习笔记】11 支持向量机
  • 原文地址:https://blog.csdn.net/hzy199772/article/details/125558440