Vue之render函数

概述

render函数从名字上看就可以看出,它是一个用于渲染的函数,在Vue中我们要将我们写的界面展示到屏幕上时,使用的方式都是组件中的template:标签下编写内容后,由Vue将我们编写的界面渲染到屏幕上。而这个render函数就是比template更底层的函数,我们可以利用它直接渲染我们想渲染的内容。这样做的好处是性能更高,并且使用更加灵活。

实例解析

假设我们要在屏幕上展示如下图所示的内容:
Vue之render函数即编写一个组件,这个组件接收一个来自父组件的展示内容和展示的字体大小,子组件负责根据父组件的内容和展示的字体大小展示内容。上图分别是<h1></h1>-<h6></h6>的展示效果。根据我们前面学习的知识实现这个需求也不难,大致思路为:编写一个子组件,通过组件间传值,获得父组件传递过来的字体展示的level,level是多少,子组件就展示<h level>,展示的内容我们使用插槽相关的内容解决,步骤如下:
首先我们定义一个子组件,代码如下:

  app.component('my-title',{
        props:['level'],
        template:
        `
            <h1 v-if="level===1"><slot /></h1>
            <h2 v-if="level===2"><slot /></h2>
            <h3 v-if="level===3"><slot /></h3>
            <h4 v-if="level===4"><slot /></h4>
            <h5 v-if="level===5"><slot /></h5>
            <h6 v-if="level===6"><slot /></h6>
        `
    });

如上面代码所示吗,我们使用props接收一个来自父组件的展示标题是多少,然后通过slot接收父组件传递过来的内容,使用v-if来判断level是否是本标签需要展示的level类型,不是则不展示。

然后在父组件中我们可以使用定义的组件来展示我们想要展示的内容和level了,代码如下:

 const app = Vue.createApp({
        template: 
        `
         <my-title :level="1"> 
            hello world111
         </my-title>
         <my-title :level="2"> 
            hello world222
         </my-title>
         <my-title :level="3"> 
            hello world333
         </my-title>
         <my-title :level="4"> 
            hello 
         </my-title>
         <my-title :level="5"> 
            walt
         </my-title>
         <my-title :level="6"> 
            zhongxj
         </my-title> 
        `
    }); 

注意:在父组件中我们传递level值使用的是 :level=“6”的方式,前面学过这种方式,这里加冒号就表示我们传递的是一个数字,不加冒号表示的是字符串
这样我们就实现了我们想要展示的内容了,但是我们可以看到子组件中的展示内容部分的代码逻辑都差不多,显得有点冗余:

     template:
        `
            <h1 v-if="level===1"><slot /></h1>
            <h2 v-if="level===2"><slot /></h2>
            <h3 v-if="level===3"><slot /></h3>
            <h4 v-if="level===4"><slot /></h4>
            <h5 v-if="level===5"><slot /></h5>
            <h6 v-if="level===6"><slot /></h6>
        `

假设我们还有h6,h7,h8 ……,难道也要一直按照这个逻辑写下去吗?答案是否定的,所以这时候,render函数就派上用场了。我们看下如何使用render函数实现我们展示不同标题的需求。我们只需要修改子组件中的代码就可以了,我们直接使用render函数替代template就可以了,代码如下:

    app.component('my-title',{
        props:['level'],
        render(){
           const {h} = Vue;
           return h('h'+this.level,{},this.$slots.default()); 
        }
    });

如上所示,我们使用了Vue的一个render()函数,然后返回一个h函数,这个h函数传递的参数分别为:

h(标签名称,属性,需要渲染的内容)
标签名称:就是div,h1,span这类的html标签的名称
属性:属性就是我们在描述界面时在标签中定义的属性,例如:<div name="123"></div> 中的name=”123″就是属性
需要渲染的内容:这里可以直接是内容,可以是一个h函数的返回值,也就是虚拟DOM

比如我们直接将需要渲染的内容改成字符串,代码如下:

 app.component('my-title',{
        props:['level'],
        render(){
           const {h} = Vue;
           return h('h'+this.level,{},'zhongxj'); 
        }
    });

运行结果:
Vue之render函数需要渲染的内容还可以使用一个数组表示多个渲染内容,比如我们不仅需要渲染父组件的内容,还要增加一个自己定义的内容,代码如下:

  app.component('my-title',{
        props:['level'],
        render(){
           const {h} = Vue;
           return h('h'+this.level,{},[this.$slots.default(),'walt-zhong']); 
        }
    });

运行结果:
Vue之render函数本文完整示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>render函数</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
    <div id="hello"></div>
</body>
<script>

 const app = Vue.createApp({
    // :level="1" 加冒号是一个数字,不加冒号后面的1就是一个字符串
        template: 
        `
         <my-title :level="1"> 
            hello world111
         </my-title>

         <my-title :level="2"> 
            hello world222
         </my-title>
         <my-title :level="3"> 
            hello world333
         </my-title>
         <my-title :level="4"> 
            hello 
         </my-title>
         <my-title :level="5"> 
            walt
         </my-title>

         <my-title :level="6"> 
            zhongxj
         </my-title> 
        `
    });  

    app.component('my-title',{
        props:['level'],
        render(){
            const{h} = Vue;
            // 虚拟DOM 

            // h函数返回一个虚拟DOM,Vue会做一个虚拟dom到真实DOM的映射然后渲染出来
            // template->render函数->h函数->虚拟DOM(JS对象) -> 真实DOM->展示到页面上
            return h('h' + this.level,{}, [
                this.$slots.default(),
            h('div',{name:1234},''),'zhongxj']) 
            // {} 中传的是<h1 name = "123" 
           //v-if="level===1"><slot /></h1> 中的name属性
        }
        // template:
        // `
        //     <h1 v-if="level===1"><slot /></h1>
        //     <h2 v-if="level===2"><slot /></h2>
        //     <h3 v-if="level===3"><slot /></h3>
        //     <h4 v-if="level===4"><slot /></h4>
        //     <h5 v-if="level===5"><slot /></h5>
        //     <h6 v-if="level===6"><slot /></h6>
        // `
    });
    const vm = app.mount('#root');
</script>

我们读者或许会很奇怪为啥使用h函数可以让我们的内容被渲染出来,其实h函数的返回值是一个虚拟DOM,这个虚拟DOM是一个JS对象,这个对象描述了我们要展示的界面描述,然后Vue会做一个转换,将虚拟DOM转换成真实DOM渲染出来。这个转换的流程大致如下:

template->render函数->h函数->虚拟DOM(JS对象) -> 真实DOM->展示到页面上

Vue为我们提供了template供我们简单描述界面,然后就会通过render函数将我们编写的界面转换成虚拟DOM,最后由Vue转化成真实DOM渲染出来,在特殊情况下,如本文例子中,需要优化简化代码,所以使用了render函数。所以render()函数可以用来做优化和代码简化用

总结

本文主要介绍了render()函数的使用,并且简单的解释了Vue的页面渲染原理,使用render函数可以优化我们页面的渲染速度和简化我们的逻辑重复的冗余代码。Vue的渲染过程可以描述为:template->render函数->h函数->虚拟DOM(JS对象) -> 真实DOM->展示到页面上

原文链接:https://juejin.cn/post/7227730538575806522 作者:海塔灯

(0)
上一篇 2023年5月1日 上午10:26
下一篇 2023年5月1日 上午10:36

相关推荐

发表回复

登录后才能评论