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 相关文章推荐
Javascript - HTML的request类
Jan 09 Javascript
ie 处理 gif动画 的onload 事件的一个 bug
Apr 12 Javascript
验证码在IE中不刷新而谷歌等浏览器正常的解决方案
Mar 18 Javascript
纯JS实现根据CSS的class选择DOM
Mar 22 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
Feb 21 Javascript
JS生成随机打乱数组的方法示例
Dec 23 Javascript
深入理解JavaScript和TypeScript中的class
Apr 22 Javascript
vue下history模式刷新后404错误解决方法
Aug 18 Javascript
基于JS实现web端录音与播放功能
Apr 17 Javascript
ElementUI多个子组件表单的校验管理实现
Nov 07 Javascript
微信sdk实现禁止微信分享(使用原生php实现)
Nov 15 Javascript
原生js实现自定义难度的扫雷游戏
Jan 22 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
php依赖注入知识点详解
2019/09/23 PHP
如何在Laravel5.8中正确地应用Repository设计模式
2019/11/26 PHP
共享自己写一个框架DreamScript
2007/01/20 Javascript
javascript while语句和do while语句的区别分析
2007/12/08 Javascript
JavaScript脚本性能优化注意事项
2008/11/18 Javascript
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
JS对象转换为Jquery对象实现代码
2013/12/29 Javascript
js实现仿京东2级菜单效果(带延时功能)
2015/08/27 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
jQuery可见性过滤选择器用法示例
2016/09/09 Javascript
微信小程序 本地数据存储实例详解
2017/04/13 Javascript
解决ztree搜索中多级菜单展示不全问题
2017/07/05 Javascript
vue-resource拦截器设置头信息的实例
2017/10/27 Javascript
VUE重点问题总结
2018/03/19 Javascript
详解vue axios二次封装
2018/07/22 Javascript
详解使用WebPack搭建React开发环境
2019/08/06 Javascript
vue transition 在子组件中失效的解决
2019/11/12 Javascript
使用Python脚本实现批量网站存活检测遇到问题及解决方法
2016/10/11 Python
再谈Python中的字符串与字符编码(推荐)
2016/12/14 Python
Python复制Word内容并使用格式设字体与大小实例代码
2018/01/22 Python
解决python大批量读写.doc文件的问题
2018/05/08 Python
使用python获取邮箱邮件的设置方法
2019/09/20 Python
使用Python 自动生成 Word 文档的教程
2020/02/13 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
keras绘制acc和loss曲线图实例
2020/06/15 Python
CSS3的RGBA中关于整数和百分比值的转换
2015/08/04 HTML / CSS
处理HTML5新标签的浏览器兼容版问题
2017/03/13 HTML / CSS
幼儿园亲子活动方案
2014/01/29 职场文书
关于抽烟的检讨书
2014/02/25 职场文书
金融事务专业求职信
2014/04/25 职场文书
产品开发计划书
2014/04/27 职场文书
留守儿童工作方案
2014/06/02 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
先进班集体事迹材料
2014/12/25 职场文书
2016年春季运动会广播稿
2015/08/19 职场文书
Redis高并发缓存架构性能优化
2022/05/15 Redis