vue虚拟DOM和render()函数

@TOC

vue虚拟DOM和render()函数

与其他的前端开发框架相比,Vue.js的优势是执行性能比较高,这里有一个很重要的原因就是Vue.js采用虚拟DOM机制。虽然大多数情况下,Vue.js推荐使用模板构建HTML,但是在某些场景下,可能需要JavaScript的编程能力,这时就需要使用render()函数,它比模板更接近编辑器。通过本章内容的学习,读者可以了解虚拟DOM和render()函数的使用方法。

虚拟DOM

DOM即文档对象模型,它提供了对整个文档的访问模型,将文档作为一个树形结构,树的每个结点表示了一个HTML标签或标签内的文本项。DOM树结构精确地描述了HTML文档中标签间的相互关联性。浏览器在解析HTML文档时,会将文档中的元素、注释、文本等标记按照它们的层级关系转化为DOM树。一个元素要想在页面中显示,则必须在DOM中存在该节点,也就是必须将该元素节点添加到现有DOM树中的某个节点下,才能渲染到页面中。同样地,如果需要删除某个元素,也需要从DOM树中删除该元素对应的节点。如果每次要改变页面展示的内容,只能通过遍历查询DOM树,然后修改DOM树,从而达到更新页面的目的,这个过程相当消耗资源。
为了解决这个问题,虚拟DOM概念随着React的诞生而诞生,其由Facebook提出,其卓越的性能很快得到广大开发者的认可。因为每次查询DOM几乎都需要遍历整个DOM树,如果建立一个与DOM树对应的虚拟DOM对象,也就是JavaScript对象,以对象嵌套的方式来表示DOM树及其层级结构,那么每次DOM的修改就变成了对JavaScript对象的属性的操作,由于操作JavaScript对象比操作DOM要快得多,从而大幅度减少性能的开支。
Vue从2.0开始也在其核心引入了虚拟DOM的概念,Vue.js 3.x重写了虚拟DOM的实现,从而让性能更加优秀。Vue在更新真实的DOM树之前,先比较更新前后虚拟DOM结构中有差异的部分,然后采用异步更新队列的方式将差异部分更新到真实DOM中,从而减少了最终要在真实DOM上执行的操作次数,提高了页面的渲染效率。

render()函数

大多数情况下,Vue通过template来创建HTML。但是在特殊情况下,可能需要JavaScript的编程能力,这时可以使用render()函数,它比模板更接近编译器。
下面通过一个简单的例子,了解render()函数的优势。假设需要生成一些带锚点的标题,基础代码如下:

<h1>
   <a name="hello-world" href="#hello-world">
       Hello world!
   </a>
</h1>

由于锚点标题的使用非常频繁,考虑到标题的级别包括h1~h6,可以将标题的级别定义成组件的prop,在调用组件时,可以通过该prop动态设置标题元素的级别。代码如下:

<anchored-heading :level="1">Hello world!</anchored-heading>

接下来就是组件的实现代码:

const app = createApp({})
app.component(‘anchored-heading’, {
template: `

`, props: { level: { type: Number, required: true } } })

上述通过模板的方式实现起来不仅冗长,而且为每个级别标题都重复书写了。当添加锚元素时,还必须在每个 v-if/v-else-if 分支中再次复制元素。

<div id="app">
        <anchored-heading :level="2">
            <a name="hello-world" href="#hello-world">
                相顾无相识,长歌怀采薇。
            </a>
        </anchored-heading>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const app = Vue.createApp({})
        app.component('anchored-heading', {
            render() {
                const { h } = Vue
                return h(
                  'h' + this.level, // 标签名
                  {}, // prop 或 attribute
                  this.$slots.default() // 包含其子节点的数组
                )
            },
             props: {
                level: {
                    type: Number,
                    required: true
                }
        })
        app.mount('#app')
    </script>

可见使用render()函数的实现要精简得多。需要注意的是,向组件中传递不带v-slot指令的子节点时,比如 anchored-heading 中的 Hello world!,这些子节点被存储在组件实例中的$slots.default中。在谷歌浏览器中运行程序.

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr Robot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值