React 的"外骨骼" 神器 —— JSX

68 阅读5分钟

JSX

简介

Facebook 的 React 团队在打造 React 战舰的时候同时也给战舰配备了刚健有力的外骨骼 JSX。从前面的文章中能发现,当我们需要创建复杂 DOM 树的时候,我们需要不断的 React.createElement() 元素与子元素,使用起来也显得格外麻烦,所以打造了类似于 HTML 和 XMl 一样易于阅读的 JSX。

我们先来打造一个周计划,尽可能的把JSX的一些常用语法点都囊括进去:

const weekPlanList = [
  {
    title: '周一的计划',
    index: 1,
    todoItems: [
      {
        index: 1,
        time: '7:00 PM',
        matters: '运动健身'
      },
      {
        index: 2,
        time: '9:00 PM',
        matters: '阅读'
      }
    ]
  },
  {
    title: '周二的计划',
    index: 2,
    todoItems: [
      {
        index: 1,
        time: '7:00 PM',
        matters: '练习萨克斯'
      },
      {
        index: 2,
        time: '8:00 PM',
        matters: '看一部电影'
      }
    ]
  },
  {
    title: '周三的计划',
    index: 3,
    todoItems: [
      {
        index: 1,
        time: '7:00 PM',
        matters: '练习毛笔字'
      },
      {
        index: 2,
        time: '8:00 PM',
        matters: '短距离夜骑'
      }
    ]
  },
  {
    title: '周四的计划',
    index: 4,
    todoItems: [
      {
        index: 1,
        time: '7:00 PM',
        matters: '运动健身'
      },
      {
        index: 2,
        time: '8:00 PM',
        matters: '高数学习'
      }
    ]
  },
  {
    title: '周五的计划',
    index: 5,
    todoItems: [
      {
        index: 1,
        time: '7:00 PM',
        matters: '云顶之奕'
      }
    ]
  },
  {
    title: '周六的计划',
    index: 6,
    todoItems: [
      {
        index: 1,
        time: '7:00 AM',
        matters: '绿道骑行'
      },
      {
        index: 2,
        time: '7:00 PM',
        matters: '线代学习'
      }
    ]
  },
  {
    title: '周日的计划',
    index: 7,
    todoItems: [
      {
        index: 1,
        time: '8:00 AM',
        matters: '学习,整理,总结'
      },
      {
        index: 2,
        time: '3:00 PM',
        matters: '追番,追剧,追综艺'
      }
    ]
  }
];

// 每日待办的函数组件
const TodoItems = ({ todoItems }) => (
  <>
    <ul> 
    {todoItems.map(item => (
      { /* 定义标签 class 属性时,JSX 中要用 className,因为 class 是 JavaScript 声明 类的保留字 */ }
      <li clsssName="todo-item" key={item.index}>{`${item.time}:${item.matters}` }</li>
    	)
     )}
    </ul>
  </>
);

// 周计划的函数组件
const WeekPlan = (weekPlanList) => (
  {weekplanList.map(weekplan => (
   	<React.Fragment key={weekplan.index}>
      <h2>{weekplan.title.replace('的', '') + ':'}</h2>
			<TodoItems {...weekplan} />
    </React.Fragment>
   )
	)}
);

// 渲染 DOM
ReactDOM.render(
	<WeekPlan weekPlanList={weekPlanList} />,
  document.getElementById('root')
);

1. JavaScript 表达式

JSX 中 JavaScript 表达式放在大括号内,可以是一个变量也可以是变量的拼接或加减,甚至是表达式内的函数也会被调用,可以看到 WeekPlan 组件 <h2> 标签中的表达式就是一个 函数的调用并进行了字符串的拼接。

2. 组件嵌套

JSX 可以把组件添加作为组件的子元素。在 WeekPlan 组件中,我们嵌套了 TodoItems 每日待办组件,也就是,组件直接当标签用。

3. JSX 代码注释

如上代码,我们对 class 属性 用 className 代替的解释,就是用的代码注释方法 *{/ */}**, 还有一种单行注释为 {// ... }

4. 数组映射

JSX 中数组映射: 直接将数组映射为JSX元素,常用到的方法: Array.map 。上边的两个函数组件中也有体现。在数组映射的时候,我们会给元素绑定一个key属性,在日常的业务代码中,可能根本用不上这个属性,但是这个属性尤其重要,在讲这个属性之前,我们来聊聊电视剧。

最近在看《潜行者》时,黄晓明饰演的方嘉树,在军统地下党,共产党潜伏者,76号副处长这三个组织关系处理得游刃有余,我记得只有共产党的潜伏者的上下线联络的时候,用的是暗号对接,我猜测哈,用暗号对接,估计可能是比较安全,还有一个可能就是"太穷"了吧,但也因为他们这么多的英雄们,也才有了现在的这整个社会…感恩感谢!

哈哈哈,中途插了个电视广告,我们要说的这个 key 就是 props 携带的属性 与 DOM 元素间对接的暗号。也就是说,上线 props 要行动, 通过"暗号" key 快速通知下线 DOM 作出相应的行动。

5. Fragment 碎片化节点

React,Vue 都不能在一个组件中渲染两个或两个以上的同辈或同级元素,必须要把这些标签放在一个标签内,比如 div, Vue2.x 就只能这样处理。这种情况对上面的周计划组件就相当难受,好在 Vue3.x 和 React 都提供了 Fragment。

Fragment:可以模拟容器的行为,但不会创建真正的标签

我们在中计划组件中用到了 <React.Fragment> 标签,就是为了解决碎片化节点的渲染问题。我们在待办组件中看到一个 <></>空标签,这个空标签其实就是 <React.Fragment>的精简代码,这样易于编写。

当然这两者的用处还是有所区别的,当我们在做数据映射时,需要绑定属性值时,就必须要用<React.Fragment>,只有在只是作为一个容器标签时才可以简写。在实际的开发中,TodoItems 组件中的空标签是没有必要写的,这里只是作为一个例子进行讲解用到。

总结

来回忆一下,这篇文章讲了些啥?

  1. JSX:是由 Facebook 的 React 团队创建的类似于 HTML,XML 的代码格式;
  2. JavaScript 表达式:{} 中可以赋值,也可以添加计算,串联,甚至可以调用函数;
  3. className 属性:对应的是 DOM 标签中的 class 属性;
  4. 嵌套组件:一个组件可以作为另一个组件可以重复引用的子元素;
  5. 数据映射:{} 中,可将数据映射为 JSX 元素,key 属性具有关联性,常用的数据映射方法 Array.map;
  6. JSX 代码注释: 多行 {/* */},单行 {// }
  7. Fragment 标签:一个多根元素标签容器,不会被渲染出对应的标签,简写为 <></>,需要绑定属性时,只能用 <React.Fragment> 标签。