JSX在render函數中的應用

一.JSX簡介

const element = <h1>Hello, world!</h1>;

JSX 能夠很好地描述 UI 應該呈現出它應有交互的本質形式。JSX 可能會令人聯想到模版語言,但它具備 JavaScript 的所有功能。javascript

Babel 會把 JSX 轉譯成一個名爲 React.createElement() 函數調用。
如下兩種示例代碼徹底等效:html

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement() 會預先執行一些檢查,以幫助你編寫無錯代碼,但實際上它建立了一個這樣的對象:前端

const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

二.模板缺陷

模板的最大特色是擴展難度大,不易擴展。可能會形成邏輯冗餘:vue

<Level :type="1">哈哈</Level>
<Level :type="2">哈哈</Level>
<Level :type="3">哈哈</Level>

Level組件須要對不一樣的type產生不一樣的標籤java

<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會讓代碼看起來更加簡潔、易於讀取iview

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">
  <ul v-for="(item,index) in data" :key="index">
   <li>{{item}}</li>
  </ul>
 </div>
</template>
<script>
export default {
 props: {
  data: Array,
  default: () => []
 }
};
</script>

經過render方法來定製組件,在父組件中傳入render方法this

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

咱們須要createElement方法,就會想到能夠編寫個函數組件,將createElement方法傳遞出來spa

<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>

想要了解更多關於JSX的內容,歡迎關注【前端優選】

圖片描述

相關文章
相關標籤/搜索