iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >Vue编译优化的实现流程是什么
  • 799
分享到

Vue编译优化的实现流程是什么

2023-07-05 01:07:50 799人浏览 泡泡鱼
摘要

本篇内容主要讲解“Vue编译优化的实现流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue编译优化的实现流程是什么”吧!动态节点收集与补丁标志1.传统diff算法的问题对于一个普通模板

本篇内容主要讲解“Vue编译优化的实现流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue编译优化的实现流程是什么”吧!

    动态节点收集与补丁标志

    1.传统diff算法的问题

    对于一个普通模板文件,如果只是标签中的内容发生了变化,那么最简单的更新方法很明显是直接替换标签中的文本内容。但是diff算法很明显做不到这一点,它会重新生成一棵虚拟DOM树,然后对两棵虚拟DOM树进行比较。很明显,与直接替换标签中的内容相比,传统diff算法需要做很多无意义的操作,如果能够去除这些无意义的操作,将会省下一笔很大的性能开销。其实,只要在模板编译时,标记出哪些节点是动态的,哪些是静态的,然后再通过虚拟DOM传递给渲染器,渲染器就能根据这些信息,直接修改对应节点,从而提高运行时性能。

    2.Block和PatchFlags

    对于一个传统的模板:

    <div>    <div>        foo    </div>    <p>        {{ bar }}    </p></div>

    在这个模板中,只用{{ bar }}是动态内容,因此在bar变量发生变化时,只需要修改p标签内的内容就行了。因此我们在这个模板对于的虚拟DOM中,加入patchFlag属性,以此来标签模板中的动态内容。

    const vnode = {    tag: 'div',    children: [        { tag: 'div', children: 'foo' },        { tag: 'p', children: ctx.bar, patchFlag: 1 },    ]}

    对于不同的数值绑定,我们分别用不同的patch值来表示:

    • 数字1,代表节点有动态的textContent

    • 数字2,代表节点有动态的class绑定

    • 数字3,代表节点有动态的style绑定

    • 数字4,其他&hellip;

    我们可以新建一个枚举类型来表示这些值:

    enum PatchFlags {    TEXT: 1,    CLASS,    STYLE,    OTHER}

    这样我们就在虚拟DOM的创建阶段,将动态节点提取出来:

    const vnode = {    tag: 'div',    children: [        { tag: 'div', children: 'foo' },        { tag: 'p', children: ctx.bar, patchFlag: PatchFlags.TEXT },    ],    dynamicChildren: [        { tag: 'p', children: ctx.bar, patchFlag: PatchFlags.TEXT },    ]}

    3.收集动态节点

    首先我们创建收集动态节点的逻辑。

    const dynamicChildrenStack = []; // 动态节点栈let currentDynamicChildren = null; // 当前动态节点集合function openBlock() {    // 创建一个新的动态节点栈dynamicChildrenStack.push((currentDynamicChildren = []));}function closeBlock() {    // openBlock创建的动态节点集合弹出    currentDynamicChildren = dynamicChildrenStack.pop();}

    然后,我们在创建虚拟节点的时候,对动态节点进行收集。

    function createVNode(tag, props, children, flags) {    const key = props && props.key;    props && delete props.key;    const vnode = {        tag,        props,        children,        key,        patchFlags: flags    }    if(typeof flags !== 'undefined' && currentDynamicChildren) {        currentDynamicChildren.push(vnode);    }    return vnode;}

    然后我们修改组件渲染函数的逻辑。

    render() {    return (openBlock(), createBlock('div', null, [        createVNode('p', { class: 'foo' }, null, 1),        createVNode('p', { class: 'bar' }, null)    ]));}function createBlock(tag, props, children) {    const block = createVNode(tag, props, children);    block.dynamicChildren = currentDynamicChildren;    closeBlock();    return block;}

    4.渲染器运行时支持

    function patchElement(n1, n2) {    const el = n2.el = n1.el;    const oldProps = n1.props;    const newProps = n2.props;    // ...    if(n2.dynamicChildren) {        // 如果有动态节点数组,直接更新动态节点数组        patchBlockChildren(n1, n2);    } else {        patchChildren(n1, n2, el);    }}function pathcBlockChildren(n1, n2) {    for(let i = 0; i < n2.dynamicChildren.length; i++) {        patchElement(n1.dynamicChildren[i], n2.dynamicChildren[i]);    }}

    由于我们标记了不同的动态节点类型,因此我们可以针对性的完成靶向更新。

    function patchElement(n1, n2) {    const el = n2.el = n1.el;    const oldProps = n1.props;    const newProps = n2.props;    if(n2.patchFlags) {        if(n2.patchFlags === 1) {            // 只更新内容        } else if(n2.patchFlags === 2) {            // 只更新class        } else if(n2.patchFlags === 3) {            // 只更新style        } else {            // 更新所有            for(const k in newProps) {                if(newProps[key] !== oldProps[key]) {                patchProps(el, key, oldProps[k], newProps[k]);                }            }            for(const k in oldProps) {                if(!key in newProps) {                    patchProps(el, key, oldProps[k], null);                }            }        }    }    patchChildren(n1, n2, el);}

    5.Block树

    组件的根节点必须作为Block角色,这样,从根节点开始的所有动态子代节点都会被收集到根节点的dynamicChildren数组中。除了根节点外,带有v-if、v-for这种结构化指令的节点,也会被作为Block角色,这些Block角色共同构成一棵Block树。

    静态提升

    假设有以下模板

    <div>    <p>        static text    </p>    <p>        {{ title }}    </p></div>

    默认情况下,对应的渲染函数为:

    function render() {    return (openBlock(), createBlock('div', null, [        createVNode('p', null, 'static text'),        createVNode('p', null, ctx.title, 1 )    ]))}

    在这段代码中,当ctx.title属性变化时,内容为静态文本的p标签节点也会跟着渲染一次,这很明显式不必要的。因此,我们可以使用“静态提升”,即将静态节点,提取到渲染函数之外,这样渲染函数在执行的时候,只是保持了对静态节点的引用,而不会重新创建虚拟节点。

    const hoist1 = createVNode('p', null, 'static text');function render() {    return (openBlock(), createBlock('div', null, [        hoist1,        createVNode('p', null, ctx.title, 1 )    ]))}

    除了静态节点,对于静态props我们也可以将其进行静态提升处理。

    const hoistProps = { foo: 'bar', a: '1' };function render() {    return (openBlock(), createBlock('div', null, [        hoist1,        createVNode('p', hoistProps, ctx.title, 1 )    ]))}

    预字符化

    除了对节点进行静态提升外,我们还可以对于纯静态的模板进行预字符化。对于这样一个模板:

    <templete><p></p>    <p></p>    <p></p>    <p></p>    <p></p>    ...    <p></p>    <p></p>    <p></p>    <p></p></templete>

    我们完全可以将其预处理为:

    const hoistStatic = createStaticVNode('<p></p><p></p><p></p><p></p>...<p></p><p></p><p></p><p></p>');render() {    return (openBlock(), createBlock('div', null, [hoistStatic    ]));}

    这么做的优势:

    • 大块的静态内容可以通过innerhtml直接设置,在性能上具有一定优势

    • 减少创建虚拟节点带来的额外开销

    • 减少内存占用

    缓存内联事件处理函数

    当为组件添加内联事件时,每次新建一个组件,都会为该组件重新创建并绑定一个新的内联事件函数,为了避免这方面的无意义开销,我们可以对内联事件处理函数进行缓存。

    function render(ctx, cache) {    return h(Comp, {        onChange: cache[0] || cache[0] = ($event) => (ctx.a + ctx.b);    })}

    v-once

    v-once指令可以是组件只渲染一次,并且即使该组件绑定了动态参数,也不会更新。它与内联事件一样,也是使用了缓存,同时通过setBlockTracking(-1)阻止该VNode被Block收集。

    v-once的优点:

    • 避免组件更新时重新创建虚拟DOM带来的性能开销

    • 避免无用的Diff开销

    到此,相信大家对“Vue编译优化的实现流程是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    --结束END--

    本文标题: Vue编译优化的实现流程是什么

    本文链接: https://www.lsjlt.com/news/348841.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • Vue编译优化的实现流程是什么
      本篇内容主要讲解“Vue编译优化的实现流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue编译优化的实现流程是什么”吧!动态节点收集与补丁标志1.传统diff算法的问题对于一个普通模板...
      99+
      2023-07-05
    • Vue编译优化实现流程详解
      目录动态节点收集与补丁标志1.传统diff算法的问题2.Block和PatchFlags3.收集动态节点4.渲染器运行时支持5.Block树静态提升预字符化缓存内联事件处理函数v-o...
      99+
      2023-01-28
      Vue编译优化 Vue代码优化
    • android编译打包流程是什么
      Android编译打包流程大致如下:1. 编写代码:根据需求编写Android应用程序的代码。2. 构建项目:使用构建工具(如Gra...
      99+
      2023-08-09
      android
    • vue模板预编译是什么
      本教程操作环境:windows7系统、vue3版,DELL G3电脑。模板预编译当使用 DOM 内模板或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。通常情况下这个过程已经足够快了,但对性能敏感的应用还是最好避免...
      99+
      2023-05-14
      Vue
    • vue模板编译的原理是什么
      这篇文章主要介绍了vue模板编译的原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue模板编译的原理是什么文章都会有所收获,下面我们一起来看看吧。vue提供了模板语法,允许我们声明式地描述状态和DOM...
      99+
      2023-07-05
    • golang的编译过程是什么
      Golang的编译过程可以分为四个主要步骤: 词法分析(Lexical Analysis):将源代码分解为一个个的词法单元(to...
      99+
      2023-10-22
      golang
    • Vue Router中Matcher的初始化流程是什么
      这篇文章主要讲解了“Vue Router中Matcher的初始化流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue Router中Matcher的初始化流程是...
      99+
      2023-06-30
    • Vue组件化编程的方法是什么
      本篇内容主要讲解“Vue组件化编程的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue组件化编程的方法是什么”吧!2.1 模块与组件、模块化与组件化2.1.1.模块理解:向外提供特定...
      99+
      2023-07-05
    • Mysql如何实现编译安装参数优化
      这篇文章主要为大家展示了“Mysql如何实现编译安装参数优化”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Mysql如何实现编译安装参数优化”这篇文章吧。1. ...
      99+
      2024-04-02
    • java程序的编译过程是什么
      Java程序的编译过程分为以下几个步骤:1. 编写源代码:首先需要编写Java程序的源代码,源代码是以.java文件的形式存在,可以...
      99+
      2023-09-28
      java
    • c编译程序指的是什么
      这篇文章给大家分享的是有关c编译程序指的是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。c编译程序又称c语言编译器,是指用c语言书写的源程序,翻译成等价的机器语言格式目标程序的翻译程序。c编译程序首先会检查源...
      99+
      2023-06-06
    • JavaScript预编译过程是什么
      本篇内容介绍了“JavaScript预编译过程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!阶段(三...
      99+
      2024-04-02
    • linux编译安装的过程是什么
      这篇文章主要介绍“linux编译安装的过程是什么”,在日常操作中,相信很多人在linux编译安装的过程是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux编译安装的...
      99+
      2023-02-15
      linux
    • java程序编译的步骤是什么
      Java程序的编译步骤如下:1. 编写Java源代码:使用文本编辑器(如记事本、Sublime Text、Eclipse等)编写Ja...
      99+
      2023-08-29
      java
    • C++ 元编程与编译器优化之间的关系?
      非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
      99+
      2024-05-21
    • Android 性能优化实现全量编译提速的黑科技
      目录一、背景描述二、效果展示2.1、测试项目介绍三、思路问题分析与模块搭建:3.1、思路问题分析3.2、模块搭建四、问题解决与实编译流程启动,需要找到哪一个 module做了修改mo...
      99+
      2024-04-02
    • Java编程中的算法优化技巧是什么?
      随着计算机科学的不断发展,算法优化已经成为了计算机程序设计中不可或缺的一部分。在Java编程中,我们也可以通过一些技巧来优化算法,提高程序的性能和效率。本文将为大家介绍一些Java编程中的算法优化技巧。 一、使用合适的数据结构 在Java...
      99+
      2023-09-25
      编程算法 laravel 对象
    • notepad插件cmake的编译过程是什么
      这篇文章主要讲解了“notepad插件cmake的编译过程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“notepad插件cmake的编译过程是什么”吧!Notepad++ 是一个文本...
      99+
      2023-07-05
    • vc多线程编译的方法是什么
      VC++多线程编译的方法包括以下几种:1. 使用OpenMP:OpenMP是一种用于多线程编程的开放式并行性API,可以通过在代码中...
      99+
      2023-08-09
      vc
    • android源代码的编译过程是什么
      Android源代码的编译过程主要包括以下几个步骤:1. 下载源代码:从Android官方网站下载源代码,并解压到本地目录。2. 配...
      99+
      2023-09-21
      android
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作