JSX指南 3个月前

前端开发
337
JSX指南

前言

根据 React 官方定义,React 是一个构建使用者介面的 JavaScritp Library。以 MVC 模式来说,ReactJS 主要是负责 View 的部份。过去一段时间,我们被灌输了许多前端分离的观念,在前端三兄弟中(或三姊妹、三剑客):HTML 掌管内容结构、CSS 负责外观样式,JavaScript 主管逻辑互动,千万不要混在一块。然而,在 React 世界里,所有事物都是 以 Component 为基础,将同一个 Component 相关的程式和资源都放在一起,而在撰写 React Component 时我们通常会使用 JSX 的方式来提升程式撰写效率。事实上,JSX 并非一种全新的语言,而是一种语法糖(Syntatic Sugar),一种语法类似 XML 的 ECMAScript 语法扩充。在 JSX 中 HTML 和组建这些元素标签的程式码有紧密的关系。因此你可能要熟悉一下以 Component 为单位的思考方式(本文主要使用 ES6 语法)。

此外,React 和 JSX 的思维在于善用 JavaScript 的强大能力,放弃蹩脚的模版语言,这和 Angular 强化 HTML 的理念也有所不同。当然 JSX 并非强制使用,你也可以选择不用,因为最终 JSX 的内容会转化成 JavaScript(浏览器只看的懂 JavaScript)。不过等你阅读完接下来的内容,你或许会开始发现 JSX 的好,认真考虑使用 JSX 的语法。

一、使用 JSX 的好处

1. 提供更加语意化且易懂的标签

由于 JSX 类似 XML 的语法,让一些非开发人员也更容易看懂,且能精确定义包含属性的树状结构。一般来说我们想做一个回馈表单,使用 HTML 写法通常会长这样:

<form class="messageBox">
  <textarea></textarea>
  <button type="submit"></button>
</form>

使用 JSX,就像 XML 语法结构一样可以自行定义标签且有开始和关闭,容易理解:

<MessageBox />

React 思路认为使用 Component 比起模版(Template)和显示逻辑(Display Logic)更能实现关注点分离的概念,而搭配 JSX 可以实现声明式 Declarative(注重 what to),而非命令式 Imperative(注重 how to)的程式撰写方式:

image

以 Facebook 上面按赞功能来说,若是命令式 Imperative 写法大约会是长这样:

if(userLikes()) {
  if(!hasBlueLike()) {
    removeGrayLike();
    addBlueLike();
  }
} else {
  if(hasBlueLike()) {
    removeBlueLike();
    addGrayLike();
  }
}

若是声明式 Declarative 则是会长这样:

if(this.state.liked) {
  return (<BlueLike />);
} else {
  return (<GrayLike />);
}

看完上述说明是不是感觉 React 结合 JSX 的写法更易读易懂?事实上,当 Component 组成越来越复杂时,若使用 JSX 将可以让整个结构更加直观,可读性较高。

2. 更加简洁

虽然最终 JSX 会转换成 JavaScript,但使用 JSX 可以让程式看起来更加简洁,以下为使用 JSX 和不使用 JSX 的范例:

<a href="https://facebook.github.io/react/">Hello!</a>

不使用 JSX(记得我们说过 JSX 是选用的):

// React.createElement(组件/HTML标签, 组件属性,以物件表示, 子组件)
React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

3. 结合原生 JavaScript 语法

JSX 并非一种全新的语言,而是一种语法糖(Syntatic Sugar),一种语法类似 XML 的 ECMAScript 语法扩充,所以并没有改变 JavaScript 语意。透过结合 JavaScript ,可以释放 JavaScript 语言本身能力。下面例子就是运用 map 方法,轻易把 result 值迭代出来,产生无序清单(ul)的内容,不用再使用蹩脚的模版语言(这边有个小地方要留意的是每个 <li> 元素记得加上独特的 key 这边用 map function 迭代出的 index,不然会出现问题):

// const 为常数
const lists = ['JavaScript', 'Java', 'Node', 'Python'];

class HelloMessage extends React.Component {
  render() {
    return (
    <ul>
      {lists.map((result, index) => {
        return (<li key={index}>{result}</li>);
      })}
    </ul>);
  }
}

二、JSX 用法摘要

1. 环境设定与使用方式

初步了解为何要使用 JSX 后,我们来聊聊 JSX 的用法。一般而言 JSX 通常有两种使用方式:

  1. 使用 browserifywebpackCommonJS bundler 并整合 babel 预处理
  2. 于浏览器端做解析

在这边简单起见,我们先使用第二种方式,先让大家专注熟悉 JSX 语法使用,等到后面章节再教大家使用 bundler 的方式去做解析(可以试着把下面的原始码贴到 JSbin 的 HTML 看结果):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 请先于 index.html 中引入 react.js, react-dom.js 和 babel-core 的 browser.min.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">
      // 程式码写在这边!
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
  </body>
</html>

一般载入 JSX 方式有:

  • 内嵌
<script type="text/babel">
  ReactDOM.render(
    <h1>Hello, world!</h1>,
    document.getElementById('example')
  );
</script>
  • 从外部引入

<script type="text/jsx" src="main.jsx"></script>

2. 标签用法

JSX 标签非常类似 XML ,可以直接书写。一般 Component 命名首字大写,HTML Tags 小写。以下是一个建立 Component 的 class:

class HelloMessage extends React.Component {
  render() {
    return (
      <div>
        <p>Hello React!</p>
        <MessageList />
      </div>
    );
  }
}

3. 转换成 JavaScript

JSX 最终会转换成浏览器可以读取的 JavaScript,以下为其规则:

React.createElement(
  string/ReactClass, // 表示 HTML 元素或是 React Component
  [object props], // 属性值,用物件表示
  [children] // 接下来参数皆为元素子元素
)

解析前(特别注意在 JSX 中使用 JavaScript 表达式时使用 {} 括起,如下方范例的 text,里面对应的是变数。若需放置一般文字,请加上 ''):

var text = 'Hello React';
<h1>{text}</h1>
<h1>{'text'}</h1>

解析完后:

var text = 'Hello React';
React.createElement("h1", null, "Hello React!");

另外要特别要注意的是由于 JSX 最终会转成 JavaScript 且每一个 JSX 节点都对应到一个 JavaScript 函数,所以在 Component 的 render 方法中只能回传一个根节点(Root Nodes)。例如:若有多个 <div>render 请在外面包一个 Component 或 <div><span> 元素。

4. 注解

由于 JSX 最终会编译成 JavaScript,注解也一样使用 ///**/ 当做注解方式:

// 单行注解

/*
  多行注解
*/

var content = (
  <List>
      {/* 若是在子组件注解要加 {}  */}
      <Item
        /* 多行
           注解
           喔 */
        name={window.isLoggedIn ? window.name : ''} // 单行注解
      />
  </List>
);

5. 属性

在 HTML 中,我们可以透过标签上的属性来改变标签外观样式,在 JSX 中也可以,但要注意 classfor 由于为 JavaScript 保留关键字用法,因此在 JSX 中使用 classNamehtmlFor 替代。

class HelloMessage extends React.Component {
  render() {
    return (
      <div className="message">
        <p>Hello React!</p>
      </div>
    );
  }
}

Boolean 属性

在 JSX 中预设只有属性名称但没设值为 true,例如以下第一个 input 标签 disabled 虽然没设值,但结果和下面的 input 为相同:

<input type="button" disabled />;
<input type="button" disabled={true} />;

反之,若是没有属性,则预设预设为 false

<input type="button" />;
<input type="button" disabled={false} />;

6. 扩展属性

在 ES6 中使用 ... 是迭代物件的意思,可以把所有物件对应的值迭代出来设定属性,但要注意后面设定的属性会盖掉前面相同属性:

var props = {
  style: "width:20px",
  className: "main",
  value: "yo",  
}

<HelloMessage  {...props} value="yo" />

// 等于以下
React.createElement("h1", React._spread({}, props, {value: "yo"}), "Hello React!");

7. 自定义属性

若是希望使用自定义属性,可以使用 data-

<HelloMessage data-attr="xd" />

8. 显示 HTML

通常为了避免资讯安全问题,我们会过滤掉 HTML,若需要显示的话可以使用:

<div>{{_html: '<h1>Hello World!!</h1>'}}</div>

9. 样式使用

在 JSX 中使用外观样式方法如下,第一个 {} 是 JSX 语法,第二个为 JavaScript 物件。与一般属性值用 - 分隔不同,为驼峰式命名写法:

<HelloMessage style={{ color: '#FFFFFF', fontSize: '30px'}} />

10. 事件处理

事件处理为前端开发的重头戏,在 JSX 中透过 inline 事件的绑定来监听并处理事件(注意也是驼峰式写法),更多事件处理方法请参考官网

<HelloMessage onClick={this.onBtn} />

总结

以上就是 JSX 简明入门教学,希望透过以上介绍,让读者了解在 React 中为何要使用 JSX,以及 JSX 基本概念和用法。最后为大家复习一下:在 React 世界里,所有事物都是以 Component 为基础,通常会将同一个 Component 相关的程式和资源都放在一起,而在撰写 React Component 时我们常会使用 JSX 的方式来提升程式撰写效率。JSX 是一种语法类似 XML 的 ECMAScript 语法扩充,可以善用 JavaScript 的强大能力,放弃蹩脚的模版语言。当然 JSX 并非强制使用,你也可以选择不用,因为最终 JSX 的内容会转化成 JavaScript。当相信阅读完上述的内容后,你会开始认真考虑使用 JSX 的语法。

延伸阅读

  1. Imperative programming or declarative programming
  2. JSX in Depth
  3. 从零开始学 React(ReactJS 101)
image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2223377
累计阅读

热门教程文档

React Native
40小节
Golang
23小节
Djiango
17小节
Spring Cloud
8小节
Docker
62小节