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 DOM 学习第二章 编辑文本
Feb 19 Javascript
JavaScript中this关键词的使用技巧、工作原理以及注意事项
May 20 Javascript
jquery trigger伪造a标签的click事件取代window.open方法
Jun 23 Javascript
jQuery中mouseover事件用法实例
Dec 26 Javascript
Angularjs中如何使用filterFilter函数过滤
Feb 06 Javascript
Jquery表单验证失败后不提交的解决方法
Oct 18 Javascript
基于JavaScript实现前端数据多条件筛选功能
Aug 19 Javascript
vue+mousemove实现鼠标拖动功能(拖动过快失效问题解决方法)
Aug 24 Javascript
解决vue脚手架项目打包后路由视图不显示的问题
Sep 20 Javascript
个人小程序接入支付解决方案
May 23 Javascript
JS将时间秒转换成天小时分钟秒的字符串
Jul 10 Javascript
jQuery实现轮播图效果demo
Jan 11 jQuery
关于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 MVC框架skymvc支持多文件上传
2016/05/26 PHP
自制PHP框架之路由与控制器
2017/05/07 PHP
laravel 实现向公共模板中传值 (view composer)
2019/10/22 PHP
javascript实现的网页局布刷新效果
2008/12/01 Javascript
javascript 获取图片颜色
2009/04/05 Javascript
js 自定义的联动下拉框
2010/02/07 Javascript
10个实用的脚本代码工具
2010/05/04 Javascript
js下利用控制器载入对应脚本
2010/07/17 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
2011/06/21 Javascript
用js实现trim()的解决办法
2013/04/16 Javascript
javascript实现表格增删改操作实例详解
2015/05/15 Javascript
jquery ajax双击div可直接修改div中的内容
2016/03/04 Javascript
node.js基于express使用websocket的方法
2017/11/09 Javascript
vue实现图片加载完成前的loading组件方法
2018/02/05 Javascript
jQuery+css last-child实现选择最后一个子元素操作示例
2018/12/10 jQuery
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
ES5和ES6中类的区别总结
2020/12/21 Javascript
[01:07:47]Secret vs Optic Supermajor 胜者组 BO3 第一场 6.4
2018/06/05 DOTA
9种python web 程序的部署方式小结
2014/06/30 Python
简介Python的collections模块中defaultdict类型的用法
2016/07/07 Python
Python爬虫:通过关键字爬取百度图片
2017/02/17 Python
Python实现简易版的Web服务器(推荐)
2018/01/29 Python
Python实现的HMacMD5加密算法示例
2018/04/03 Python
python 利用文件锁单例执行脚本的方法
2019/02/19 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
python运用sklearn实现KNN分类算法
2019/10/16 Python
pytorch实现建立自己的数据集(以mnist为例)
2020/01/18 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
2020/04/08 Python
python requests包的request()函数中的参数-params和data的区别介绍
2020/05/05 Python
科长竞聘演讲稿
2014/05/16 职场文书
保险公司开门红口号
2014/06/21 职场文书
活动总结结尾怎么写
2014/08/30 职场文书
致我们终将逝去的青春观后感
2015/06/10 职场文书
2016领导干部廉洁从政心得体会
2016/01/19 职场文书
企业转让协议书(范文2篇)
2019/08/15 职场文书