JSX在render函数中的应用详解


Posted in Javascript onSeptember 04, 2019

一.JSX简介

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

JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言,但它具有 JavaScript 的全部功能。

Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。

以下两种示例代码完全等效:

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!'
 }
};

二.模板缺陷

模板的最大特点是扩展难度大,不易扩展。可能会造成逻辑冗余:

<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">
 <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方法

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JSDoc 介绍使用规范JsDoc的使用介绍
Feb 12 Javascript
Get中文乱码IE浏览器Get中文乱码解决方案
Dec 26 Javascript
jQuery中关于ScrollableGridPlugin.js(固定表头)插件的使用逐步解析
Jul 17 Javascript
JS常用函数使用指南
Nov 23 Javascript
jQuery获得包含margin的outerWidth和outerHeight的方法
Mar 25 Javascript
JavaScript实现在页面间传值的方法
Apr 07 Javascript
QQ登录背景闪动效果附效果演示源码下载
Sep 22 Javascript
js中实现字符串和数组的相互转化详解
Jan 24 Javascript
JavaScript面试题大全(推荐)
Sep 22 Javascript
javascript 动态生成css代码的两种方法
Mar 17 Javascript
layui框架table 数据表格的方法级渲染详解
Aug 19 Javascript
前端监听websocket消息并实时弹出(实例代码)
Nov 27 Javascript
关于layui的动态图标不显示的解决方法
Sep 04 #Javascript
vue本地打开build后生成的dist文件夹index.html问题
Sep 04 #Javascript
简单谈谈javascript高级特性
Sep 04 #Javascript
在layui中使用form表单监听ajax异步验证注册的实例
Sep 03 #Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 #Javascript
mui js控制开关状态、修改switch开关的值方法
Sep 03 #Javascript
Layui给switch添加响应事件的例子
Sep 03 #Javascript
You might like
使用zend studio for eclipse不能激活代码提示功能的解决办法
2009/10/11 PHP
php实现的双向队列类实例
2014/09/24 PHP
浅谈PHP中关于foreach使用引用变量的坑
2016/11/14 PHP
ie下jquery.getJSON的缓存问题的处理方法
2013/03/29 Javascript
使用js的replace()方法查找字符示例代码
2013/10/28 Javascript
jquery mobile动态添加元素之后不能正确渲染解决方法说明
2014/03/05 Javascript
js父页面与子页面不同时显示的方法
2014/10/16 Javascript
jQuery实现鼠标划过添加和删除class的方法
2015/06/26 Javascript
javascript常用功能汇总
2015/07/05 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
浅谈Javascript中的Label语句
2016/12/14 Javascript
AngularJS中的缓存使用
2017/01/11 Javascript
Map.vue基于百度地图组件重构笔记分享
2017/04/17 Javascript
js+html实现周岁年龄计算器
2019/06/25 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
2020/04/10 Javascript
jQuery 实现扁平式小清新导航
2020/07/07 jQuery
[03:04]2018年度DOTA2玩家最喜爱的主播-完美盛典
2018/12/16 DOTA
python利用sklearn包编写决策树源代码
2017/12/21 Python
python批量创建指定名称的文件夹
2019/03/21 Python
linux 下python多线程递归复制文件夹及文件夹中的文件
2020/01/02 Python
python线程池如何使用
2020/05/28 Python
HTML5上传文件显示进度的实现代码
2012/08/30 HTML / CSS
html5视频媒体标签video的使用方法及完整参数说明详解
2019/09/27 HTML / CSS
捷克玩具商店:Bambule
2019/02/23 全球购物
JoJo Maman Bébé爱尔兰官网:英国最受欢迎的精品母婴品牌
2020/12/20 全球购物
SQL里面IN比较快还是EXISTS比较快
2012/07/19 面试题
采购助理岗位职责
2014/02/16 职场文书
2014年安全生产责任书
2014/07/22 职场文书
朋友聚会开场白
2015/06/01 职场文书
电影红河谷观后感
2015/06/11 职场文书
董事长开业致辞
2015/07/29 职场文书
初中班级口号霸气押韵
2015/12/24 职场文书
职业生涯规划书之大学四年
2019/08/07 职场文书
python中sqllite插入numpy数组到数据库的实现方法
2021/06/21 Python
Python中with上下文管理协议的作用及用法
2022/03/18 Python
Android开发手册Chip监听及ChipGroup监听
2022/06/10 Java/Android