vue之Render函数

(1)什么是Render函数

    先来看一个场景,在博客网中,一般有一级标题、二级标题、三级标题...,为了方便分享url,它们都做成了锚点,点击后,会将内容加载网址后面,以#分隔。

    例如‘特性’是一个<h2>标签,内容含有一个<a href='#特性'>#</a>的链接,点击后url便带有了锚点信息,别人打开时会直接聚焦到‘特性’所在的位置。如果将其封装成一个组件,一般写法会这样:

<div id="app">
  <app-demo :level="level" title="特性">
    特性{{level}}
  </app-demo>
</div>
<script>
  Vue.component('app-demo',{
    template:`
              <div>
                <h1 v-if="level === 1">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h1>
                <h2 v-if="level === 2">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h2>
                <h3 v-if="level === 3">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h3>
                <h4 v-if="level === 4">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h4>
                <h5 v-if="level === 5">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h5>
                <h6 v-if="level === 6">
                  <a :href=" '#' + title ">
                    <slot></slot>
                  </a>
                </h6>
              </div>
            `,
    props:{
      level:{
        type:Number,
        require:true
      },
      title:{
        type:String,
        default:''
      }
    }
  });
  var app = new Vue({
    el:'#app',
    data:{
      level:2
    }
  });
</script>

效果:

    分析:这样写没有什么错误,只是缺点太明显,代码冗长,组件的template代码大多都是重复的,只是heading标题元素的级别不同,再者必须插入一个根元素<div>,这是组件的要求。

    template写法在大多数时候很好用,但这里有些别扭。我们更像按照拼接字符串的形式来构造heading元素,比如"h"+this.leavel。在Render函数可以这样做。

<div id="app">
  <app-demo :level="level" title="特性">
    特性{{level}}
  </app-demo>
</div>
<script>
  Vue.component('app-demo',{
    props:{
      level:{
        type:Number,
        require:true
      },
      title:{
        type:String,
        default:''
      }
    },
    render(createElement){
      return createElement(
        'h'+this.level,
        [
          createElement(
            'a',{
              domProps:{
                href:'#'+this.title
              }
            },
            this.$slots.default
          )
        ]
      )
    }
  });
  var app = new Vue({
    el:'#app',
    data:{
      level:2
    }
  });
</script>

    Render函数通过createElement参数来创建Virtual Dom虚拟Dom,结构精简了很多。

(2)CreateElement用法 

    ①基本参数

    CreateElement构成了Vue虚拟Dom的模板,它有3个参数:第一个参数是必选的,可以是HTML标签、组件、函数;第二个是可选的数据对象,在template使用;第三个是子节点,也是可选参数,用法一致。

    以往在template里,我们都是在组件的标签上使用形容v-bind:class、v-bind:style额、v-on:click等这样的指令。到Render函数后,都将其写到了数据对象里,比如下面的组件,使用传统的template写法为

<div id="app">
  <ele></ele>
</div>
<script>
  Vue.component('ele',{
    template:`
      <div id="element" v-bind:class="{show:show}" v-on:click="handleClick">
        文本内容
      </div>
    `,
    data(){
      return {
        show:true
      }
    },
    methods:{
      handleClick:function(){
        console.log('您点击了')
      }
    }
  });
  var app = new Vue({
    el:'#app'
  });
</script>

 使用Render改写后的代码为

<div id="app">
  <ele></ele>
</div>
<script>
  Vue.component('ele',{
    /*
    template:`
      <div id="element" v-bind:class="{show:show}" v-on:click="handleClick">
        文本内容
      </div>
    `,
     */
    render:function(createElement){
      return createElement(
        'div',/* 第一个参数是必选的,可以是HTML标签、组件、函数*/
        {
            /*第二个是可选的数据对象,在template使用*/
            /*1、动态绑定class,等价于:class*/
            class:{
              'show':this.show
            },
            /* 2、普通HTML特性 */
            attrs:{
              id:'element'
            },
            /* 3、给div绑定click点击事件 */
            on:{
              click:this.handleClick
            }
        },
        '文本内容'/*第三个是子节点,也是可选参数*/
      )
    },
    data(){
      return {
        show:true
      }
    },
    methods:{
      handleClick:function(){
        console.log('您点击了')
      }
    }
  });
  var app = new Vue({
    el:'#app'
  });
</script>

    就此例来说,template写法比Render函数写法更加简洁,所以要适当使用Render,否则只会增加编码负担。

.

猜你喜欢

转载自www.cnblogs.com/jianxian/p/10676066.html