vue render函数初级学习使用

render函数的基本使用

render函数能够接受三个参数,其中第一个参数是必填的能够是String | Object | Function
好比说直接写一个div的字符串javascript

render(createElement) {
    return createElement("div")
}

上边的代码你在审查代码的时候你会发现他渲染出来了一个div的标签,或者你输入了一个你不认识的字符串,他也会渲染成一个html标签好比说html

render(createElement) {
    return createElement("xxx")
}

他会渲染出一个XXX的标签vue

因此若是render函数的第一个参数是String的话,表示的是HTML 标签java

另外这个参数能够是一个组件的名字好比说咱们须要渲染一个element的input组件json

render(createElement) {
    return createElement("el-input")
}

上边的代码中你会获得一个el-input的组件,其实原本的初衷就是看到以前项目中用到的大表单千篇一概,想改造一下,感受用template太累赘因此才学习的render,render函数并不能所有替代template,你须要在合适的场景下选择使用它,好比element源码中tag标签数组

render(h) {
   const classes = [ 'el-tag', this.type ? `el-tag--${this.type}` : '',
     this.tagSize ? `el-tag--${this.tagSize}` : '',
     {'is-hit': this.hit},
     {'is-circle': this.circle}
   ];
   const tagEl = (<span class={classes} style={{backgroundColor: this.color}} on-click={this.handleClick}>
     { this.$slots.default }
     {
       this.closable && <i class={{'el-tag__close': !this.circle, 'el-icon-close': !this.circle }}on-click={this.handleClose}></i>
     }
   </span>);
   
   return this.disableTransitions ? tagEl : <transition name="el-zoom-in-center">{ tagEl }</transition>;
 }

这个组件中 他们用的就是renderdom

在封装组件时,不知道到底须要一个什么样的标签组件。若是去加一堆的判断的话,代码量太大,但用render()函数来实现就很简单。函数

待会咱们再来讲一个不适合用render函数的地方学习

上边element的源码中能够看到 render函数中 是容许使用jsx语法的,其实jsx语法说白了,我感受他就是一个语法糖,它会被编译成一个树状的json树,里边有被渲染出来的标签所须要的属性,是一个对象this

最后你能够选择传入一个方法 把你的json数据return出去好比说

fun() {
     return {template: '<div></div>'}
 };
 return createElement(fun());

render函数的第二个和第三个参数是可选的,若是大家动手去使用一下上边的代码大家会发现,若是传入的是字符串的话,被渲染的这个标签除了一个标签之外什么都没有,那么第二个参数就是用来定义这个标签上边的属性的

举例说明比较常见的几个属性classstyle,attrs,domPropson

  • class style 这俩不用解释

  • attrs 这个能够定义标签上的属性 好比说id啊 src啊 placeholder什么什么的

  • domProps 这个是原生的一些属性 好比说value 可是这个是根据你渲染的标签有关的,加入你渲染了一个el-input的话 加value是不起做用的

  • on 标签的原生方法

举个例子

//高级搜索搜索图标按钮样式
 let iconSearchClass = ["search-icon","icon-sousuo", "iconfont"];
// 等待渲染的原生属性
 let componentProps = {};
// 高级搜索的input事件
 let selectInputOn={
   input:this.change,
   keyup:this.keyup,
   focus:this.focus,
   blur:this.blur
 }
 
  // 父组件属性存储
 for (const key in this.$attrs) {
   componentProps[key] = this.$attrs[key];
 }
 // 搜索图标
 let searchIcon =createElement('div',{
   class: iconSearchClass
 })
 
 // 渲染input
 let searchInput = createElement("input", {
   props: componentProps,
   on: selectInputOn
 });

上边是我以前写的一个小demo,还有一些其余的属性好比说

  • props 组件的props

  • directives 自定义指令

  • scopedSlots 做用域插槽

还有一些不经常使用的属性,具体的请参考vue官网的vue属性那一篇

另外 在render函数里边是没有v-for v-if v-model v-show 什么什么的这些指令的
能够经过本身封装函数达到相应的效果,这篇博客先作一个简单的介绍,下一篇我会把全部的属性作一个demo分享出来

第三个参数能够给上边那个标签里边添加东西 好比

<div>
    <div></div>
</div>

若是你想实现这样的效果 你能够在第三个参数里边再写一个div的字符串,第三个参数正常来说接收的是一个字符串或者一个数组,通常数组用的是比较多的,我以前的用法是数组里边放的是一个返回一个标签的变量,代码以下

// 父组件属性存储
 for (const key in this.$attrs) {
   componentProps[key] = this.$attrs[key];
 }
 // 搜索图标
 let searchIcon =createElement('div',{
   class: iconSearchClass
 })
 
 // 渲染input
 let searchInput = createElement("input", {
   props: componentProps,
   on: selectInputOn
 });

 // 高级搜索图标按钮
 let iconBtn = createElement("div", {
   class: iconBtnClass
 });

 // 高级搜索图标按钮盒子
 let iconBtnBox = createElement(
   "div",
   {
     class: iconBtnBoxClass
   },
   [iconBtn]
 );
 
 // 高级搜索input栏
 let inputRow = createElement(
   "div",
   {
     class: searchBoxClass
   },
   [searchIcon,searchInput, iconBtnBox]
 );


// 渲染高级搜索
 return createElement(
   "div",
   {
     attrs: {
       id: "advancedSearch"
     }
   },
   [inputRow, (this.listShow||this.notDestruc)&&searchSlotBox]
 );

大概就是这个意思 代码就不全沾出来了,有充字数的嫌疑,同时也能够看到,这是一个没有必要使用render函数的地方。。。。不灵活 并且我也没有使用jsx,使用jsx可能还好些 被咱们组长一顿喷 没有后续了

我这个demo巴拉巴拉写了100多行 实际生成了大概15行html包括一些事件,并非说render很差,是要提醒你们不要为了用而去用,要找到适合的地方再去用

render函数中插槽

  • 插槽用法
render(createElement) {
  // 等同于:<div><slot></slot></div>
  return createElement('div', this.$slots.default)
}
  • 插槽传值
props: ['message'],
render(createElement) {
  // 等同于`<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

放一个双向数据绑定demo

render: function(createElement) {
    var self = this;
    return createElement("input", {
      domProps: {
        value: self.name
      },
      on: {
        input: function(event) {
          self.$emit("input", event.target.value);
        }
      }
    });
  },

外边组件

<template>
        <demo :value='value' @input="demoInput"></demo>
        {{value}}
    </template>
    export default {
    data(){
        return{
         value:null,//demo  
        }
    },
    methods:{
        demoInput(val){
          this.value=val
        },
    }

效果图

今天说了一下render的基本使用 ,下一篇会分享一个render函数的demo和其余的用法,若有不足之处,但愿批评指正

相关文章
相关标签/搜索