欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue之render渲染函数和JSX的应用

程序员文章站 2022-06-04 10:45:45
一.模板缺陷 模板的最大特点是扩展难度大,不易扩展。可能会造成逻辑冗余 Level组件需要对不同的type产生不同的标签 二.函数式组件 函数式组件没有模板,只允许提供render函数 复杂的逻辑变得非常简单 三.JSX应用 使用jsx会让代码看起来更加简洁易于读取 四.render方法订制组件 编 ......

一.模板缺陷

  • 模板的最大特点是扩展难度大,不易扩展。可能会造成逻辑冗余
<level :type="1">哈哈</level>
<level :type="2">哈哈</level>
<level :type="3">哈哈</level>

level组件需要对不同的type产生不同的标签

<template>
 <h1 v-if="type==1">
  <slot></slot>
 </h1>
 <h2 v-else-if="type==2">
  <slot></slot>
 </h2>
 <h3 v-else-if="type==3">
  <slot></slot>
 </h3>
</template>
<script>
export default {
 props: {
  type: {
   type: number
  }
 }
};
</script>

二.函数式组件

  • 函数式组件没有模板,只允许提供render函数
export default {
 render(h) {
  return h("h" + this.type, {}, this.$slots.default);
 },
 props: {
  type: {
   type: number
  }
 }
};

复杂的逻辑变得非常简单

三.jsx应用

  • 使用jsx会让代码看起来更加简洁易于读取
export default {
 render(h) {
  const tag = "h" + this.type;
  return <tag>{this.$slots.default}</tag>;
 },
 props: {
  type: {
   type: number
  }
 }
};

四.render方法订制组件

  • 编写list组件可以根据用户传入的数据自动循环列表
<list :data="data"></list>
<script>
import list from "./components/list";
export default {
 data() {
  return { data: ["苹果", "香蕉", "橘子"] };
 },
 components: {
  list
 }
};
</script>

<!-- list组件渲染列表 -->
<template>
 <div class="list">
  <div v-for="(item,index) in data" :key="index">
   <li>{{item}}</li>
  </div>
 </div>
</template>
<script>
export default {
 props: {
  data: array,
  default: () => []
 }
};
</script>

通过render方法来订制组件,在父组件中传入render方法

<list :data="data" :render="render"></list>
render(h, name) {
   return <span>{name}</span>;
 }

我们需要createelement方法,就会想到可以编写个函数组件,将createelement方法传递出来

<template>
 <div class="list">
  <div v-for="(item,index) in data" :key="index">
   <li v-if="!render">{{item}}</li>
   <!-- 将render方法传到函数组件中,将渲染项传入到组件中,在内部回调这个render方法 -->
   <listitem v-else :item="item" :render="render"></listitem>
  </div>
 </div>
</template>
<script>
import listitem from "./listitem";
export default {
 components: {
  listitem
 },
 props: {
  render: {
   type: function
  },
  data: array,
  default: () => []
 }
};
</script>

listitem.vue调用最外层的render方法,将createelement和当前项传递出来

<script>
export default {
 props: {
  render: {
   type: function
  },
  item: {}
 },
 render(h) {
  return this.render(h, this.item);
 }
};
</script>

五.scope-slot

  • 使用v-slot 将内部值传即可
<list :arr="arr">
    <template v-slot="{item}">
        {{item}}
    </template>
</list>

<div v-for="(item,key) in arr" :key="key">
    <slot :item="item"></slot>
</div>

六.编写可编辑表格

  • 基于iview使用jsx扩展成可编辑的表格
<template>
<div>
  <table :columns="columns" :data="data"></table>
</div>
</template>
<script>
import vue from 'vue';
export default {
  methods:{
    render(h,{column,index,row}){
      let value = row[column.key];
      return <div on-click={(e)=>this.changeindex(e,index)} >
      {this.index === index? 
        <i-input type="text" value={value} on-input={(value)=>{
          this.handlechange(value,column,row)
        }} onon-enter={()=>this.enter(row,index)}/>:
        <span>{value}</span>
      }
      </div>
    },
    enter(row,index){
      this.data.splice(index,1,row);
      this.index = -1;
    },
    handlechange(value,column,row){
      row[column['key']]= value;
    },
    changeindex(e,index){
      this.index = index;
      this.$nexttick(()=>{
        e.currenttarget.getelementsbytagname("input")[0].focus()
      })
    }
  },
  data() {
    return {
      index:-1,
      columns: [
        {
          title: 'name',
          key: 'name',
          render:this.render
        },
        {
          title: 'age',
          key: 'age',
        },
        {
          title: 'address',
          key: 'address',
        },
      ],
      data: [
        {
          name: 'john brown',
          age: 18,
          address: 'new york no. 1 lake park',
          date: '2016-10-03',
        },
        {
          name: 'jim green',
          age: 24,
          address: 'london no. 1 lake park',
          date: '2016-10-01',
        },
        {
          name: 'joe black',
          age: 30,
          address: 'sydney no. 1 lake park',
          date: '2016-10-02',
        },
        {
          name: 'jon snow',
          age: 26,
          address: 'ottawa no. 2 lake park',
          date: '2016-10-04',
        },
      ],
    };
  },
};
</script>