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 相关文章推荐
重定向实现代码
Nov 20 Javascript
几个常用的JavaScript字符串处理函数 - split()、join()、substring()和indexOf()
Jun 02 Javascript
jQuery ui1.7 dialog只能弹出一次问题
Aug 27 Javascript
javascript instanceof,typeof的区别
Mar 24 Javascript
jQuery中使用data()方法读取HTML5自定义属性data-*实例
Apr 11 Javascript
jquery form 加载数据示例
Apr 21 Javascript
Js与Jq获取浏览器和对象值的方法
Mar 18 Javascript
Three.js学习之网格
Aug 10 Javascript
JS中SetTimeout和SetInterval使用初探
Mar 23 Javascript
JS Input里添加小图标的两种方法
Nov 11 Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
Mar 05 Javascript
vue实现动态表格提交参数动态生成控件的操作
Nov 09 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往windows中添加用户
2006/12/06 PHP
PHP字符过滤函数去除字符串最后一个逗号(rtrim)
2013/03/26 PHP
PHP错误Warning: Cannot modify header information - headers already sent by解决方法
2014/09/27 PHP
php天翼开放平台短信发送接口实现方法
2014/12/22 PHP
PHP实现采集抓取淘宝网单个商品信息
2015/01/08 PHP
通过event对象的fromElement属性解决热区设置主实体的一个bug
2008/12/22 Javascript
JavaScript flash复制库类 Zero Clipboard
2011/01/17 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
探讨javascript是不是面向对象的语言
2013/11/21 Javascript
使用AngularJS实现可伸缩的页面切换的方法
2015/06/19 Javascript
JQuery datepicker 用法详解
2015/12/25 Javascript
利用Node.js制作爬取大众点评的爬虫
2016/09/22 Javascript
JQuery PHP图片在线裁剪实例
2020/07/27 Javascript
vue.js表格组件开发的实例详解
2016/10/12 Javascript
Vue.Draggable实现拖拽效果
2020/07/29 Javascript
使用Nuxt.js改造已有项目的方法
2018/08/07 Javascript
详解Vue改变数组中对象的属性不重新渲染View的解决方案
2018/09/21 Javascript
解决vue-cli脚手架打包后vendor文件过大的问题
2018/09/27 Javascript
利用JS动态生成隔行换色HTML表格的两种方法
2018/10/09 Javascript
详解小程序不同页面之间通讯的解决方案
2018/11/23 Javascript
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
浅谈Javascript常用正则表达式应用
2019/03/08 Javascript
基于Vue2-Calendar改进的日历组件(含中文使用说明)
2019/04/14 Javascript
Vue函数式组件的应用实例详解
2019/08/30 Javascript
浅析vue中的nextTick
2020/12/28 Vue.js
Python登录并获取CSDN博客所有文章列表代码实例
2017/12/28 Python
python机器学习理论与实战(一)K近邻法
2021/01/28 Python
python实现桌面壁纸切换功能
2019/01/21 Python
彻底搞懂python 迭代器和生成器
2020/09/07 Python
HTML5+CSS3实现机器猫
2016/10/17 HTML / CSS
赫里福德的一家乡村零售商店:Philip Morris & Son
2017/06/25 全球购物
Hertz荷兰:荷兰和全球租车
2018/01/07 全球购物
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
酒店管理专业学生求职信
2013/09/27 职场文书
创业开店,这样方式更合理
2019/08/26 职场文书
阿里云国际版 使用Nginx作为HTTPS转发代理服务器
2022/05/11 Servers