React:JSX环境配置和基础语法,列表等操作

Posted 黑马程序员官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React:JSX环境配置和基础语法,列表等操作相关的知识,希望对你有一定的参考价值。

第一篇:React入门以及学习资料汇总分享

JSX

html 语言直接写在 javascript 语言中,不加任何引号,这就是 JSX 语法。它允许 HTML 与 JavaScript 的混写。

环境配置

  • 非模块化环境
    • babel-standalone
  • 模块化环境
    • babel-preset-react
  • Babel REPL 赋值查看编译结果

基本语法规则

  • 必须只能有一个根节点

  • 遇到 HTML 标签 (以 < 开头) 就用 HTML 规则解析

    • 单标签不能省略结束标签。
  • 遇到代码块(以 开头),就用 JavaScript 规则解析

  • JSX 允许直接在模板中插入一个 JavaScript 变量

    • 如果这个变量是一个数组,则会展开这个数组的所有成员添加到模板中
  • 单标签必须结束 />

基本语法:

const element = <h1>Hello, world!</h1>;

在 JSX 中嵌入 JavaScript 表达式

  • 语法
  • 如果 JSX 写到了多行中,则建议包装括号避免自动分号的陷阱
function formatName(user) 
  return user.firstName + ' ' + user.lastName;


const user = 
  firstName: 'Harper',
  lastName: 'Perez'
;

const element = (
  <h1>
    Hello, formatName(user)!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

在 JavaScript 表达式中嵌入 JSX

function getGreeting(user) 
  if (user) 
    return <h1>Hello, formatName(user)!</h1>;
  
  return <h1>Hello, Stranger.</h1>;

JSX 中的节点属性

  • 动态绑定属性值
  • class 使用 className
  • tabindex 使用 tabIndex
  • for 使用 htmlFor

普通的属性:

const element = <div tabIndex="0"></div>;

在属性中使用表达式:

const element = <img src=user.avatarUrl></img>;

声明子节点

如果标签是空的,可以使用 /> 立即关闭它。

const element = <img src=user.avatarUrl />;

JSX 子节点可以包含子节点:

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

JSX 自动阻止注入攻击

const element = <div>'<h1>this is safe</h1>'</div>

在 JSX 中使用注释

写法一:


  // 注释
  // ...

写法二(单行推荐):

/* 单行注释 */

写法三(多行推荐):


  /*
   * 多行注释
   */

JSX 原理

Babel 会把 JSX 编译为 React.createElement() 函数。

  • 每个 React 元素都是一个真实的 JavaScript 对象

下面两种方式是等价的:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  className: 'greeting',
  'Hello, world!'
);
// Note: this structure is simplified
const element = 
  type: 'h1',
  props: 
    className: 'greeting',
    children: 'Hello, world'
  
;

列表循环

JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。

var arr = [
  <h1>Hello world!</h1>,
  <h2>React is awesome</h2>,
];
ReactDOM.render(
  <div>arr</div>,
  document.getElementById('example')
);

综上所述,我们可以这样:

var names = ['Alice', 'Emily', 'Kate'];

ReactDOM.render(
  <div>
  
    names.map(function (name) 
      return <div>Hello, name!</div>
    )
  
  </div>,
  document.getElementById('example')
);

DOM Elements

参考文档:https://reactjs.org/docs/dom-elements.html

列表渲染

参考文档:https://reactjs.org/docs/lists-and-keys.html

语法高亮

http://babeljs.io/docs/editors

条件渲染

参考文档:https://reactjs.org/docs/conditional-rendering.html

示例1:

function UserGreeting(props) 
  return <h1>Welcome back!</h1>;


function GuestGreeting(props) 
  return <h1>Please sign up.</h1>;


function Greeting(props) 
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) 
    return <UserGreeting />;
  
  return <GuestGreeting />;


ReactDOM.render(
  // Try changing to isLoggedIn=true:
  <Greeting isLoggedIn=false />,
  document.getElementById('root')
);

示例2:

function LoginButton(props) 
  return (
    <button onClick=props.onClick>
      Login
    </button>
  );


function LogoutButton(props) 
  return (
    <button onClick=props.onClick>
      Logout
    </button>
  );


class LoginControl extends React.Component 
  constructor(props) 
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = isLoggedIn: false;
  

  handleLoginClick() 
    this.setState(isLoggedIn: true);
  

  handleLogoutClick() 
    this.setState(isLoggedIn: false);
  

  render() 
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) 
      button = <LogoutButton onClick=this.handleLogoutClick />;
     else 
      button = <LoginButton onClick=this.handleLoginClick />;
    

    return (
      <div>
        <Greeting isLoggedIn=isLoggedIn />
        button
      </div>
    );
  


ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

示例3(行内判断):

function Mailbox(props) 
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      unreadMessages.length > 0 &&
        <h2>
          You have unreadMessages.length unread messages.
        </h2>
      
    </div>
  );


const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages=messages />,
  document.getElementById('root')
);

示例4(if-else):

render() 
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>isLoggedIn ? 'currently' : 'not'</b> logged in.
    </div>
  );

render() 
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      isLoggedIn ? (
        <LogoutButton onClick=this.handleLogoutClick />
      ) : (
        <LoginButton onClick=this.handleLoginClick />
      )
    </div>
  );

示例5(阻止组件渲染):

function WarningBanner(props) 
  if (!props.warn) 
    return null;
  

  return (
    <div className="warning">
      Warning!
    </div>
  );


class Page extends React.Component 
  constructor(props) 
    super(props);
    this.state = showWarning: true
    this.handleToggleClick = this.handleToggleClick.bind(this);
  

  handleToggleClick() 
    this.setState(prevState => (
      showWarning: !prevState.showWarning
    ));
  

  render() 
    return (
      <div>
        <WarningBanner warn=this.state.showWarning />
        <button onClick=this.handleToggleClick>
          this.state.showWarning ? 'Hide' : 'Show'
        </button>
      </div>
    );
  


ReactDOM.render(
  <Page />,
  document.getElementById('root')
);

事件处理

参考文档:https://reactjs.org/docs/handling-events.html

示例1

<button οnclick="activateLasers()">
  Activate Lasers
</button>
<button onClick=activateLasers>
  Activate Lasers
</button>

示例2

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>
function ActionLink() 
  function handleClick(e) 
    e.preventDefault();
    console.log('The link was clicked.');
  

  return (
    <a href="#" onClick=handleClick>
      Click me
    </a>
  );

示例3(this 绑定问题)

class Toggle extends React.Component 
  constructor(props) 
    super(props);
    this.state = isToggleOn: true;

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  

  handleClick() 
    this.setState(prevState => (
      isToggleOn: !prevState.isToggleOn
    ));
  

  render() 
    return (
      <button onClick=this.handleClick>
        this.state.isToggleOn ? 'ON' : 'OFF'
      </button>
    );
  


ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

箭头函数:

class LoggingButton extends React.Component 
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => 
    console.log('this is:', this);
  

  render() 
    return (
      <button onClick=this.handleClick>
        Click me
      </button>
    );
  

更简单的方式:

class LoggingButton extends React.Component 
  handleClick() 
    console.log('this is:', this);
  

  render() 
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick=(e) => this.handleClick(e)>
        Click me
      </button>
    );
  

示例4(传递参数)

<button onClick=(e) => this.deleteRow(id, e)>Delete Row</button>
<button onClick=this.deleteRow.bind(this, id)>Delete Row</button>

Class 和 Style

class:

<div className="before" title="stuff" />

classNames:

style:

<div style=color: 'red', fontWeight: 'bold' />

表单处理

参考文档:https://reactjs.org/docs/forms.html

组件

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。

组件规则注意事项

  • 组件类的第一个首字母必须大写
  • 组件类必须有 render 方法
  • 组件类必须有且只有一个根节点
  • 组件属性可以在组件的 props 获取
    • 函数需要声明参数:props
    • 类直接通过 this.props

函数式组件(无状态)

  • 名字不能用小写
    • React 在解析的时候,是以标签的首字母来区分的
    • 如果首字母是小写则当作 HTML 来解析
    • 如果首字母是大小则当作组件来解析
    • 结论:组件首字母必须大写

类方式组件(有状态)

class ShoppingList extends React.Component 
  render() 
    return (
      <div className="shopping-list">
        <h1>Shopping List for this.props.name</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  


// Example usage: <ShoppingList name="Mark" />

本质:

return React.createElement('div', className: 'shopping-list',
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);

组件传值 Props

EcmaScript 5 构造函数:

function Welcome(props) 
  return <h1>Hello, props.name</h1>;

EcmaScript 6 Class:

class Welcome extends React.Component 
  render() 
    return <h1>Hello, this.props.name</h1>;
  

this.props.children

参考文档:https://reactjs.org/docs/react-api.html#reactchildren

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。

它表示组件的所有子节点。

this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object

组件状态 State

参考文档:https://reactjs.org/docs/state-and-lifecycle.html

组件生命周期

参考文档:https://reactjs.org/docs/state-and-lifecycle.html

完整生命周期 API:https://reactjs.org/docs/react-component.html#the-component-lifecycle

PropTypes 类型校验

参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html

组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。

示例:

import PropTypes from 'prop-types';

class Greeting extends React.Component 
  render() 
    return (
      <h1>Hello, this.props.name</h1>
    );
  


Greeting.propTypes = 
  name: PropTypes.string
;

Default Prop Values

参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html#default-prop-values

示例:

class Greeting extends React.Component 
  render() 
    return (
      <h1>Hello, this.props.name</h1>
    );
  


// Specifies the default values for props:
Greeting.defaultProps = 
  name: 'Stranger'
;

// Renders "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);

或者:

class Greeting extends React.Component 
  static defaultProps = 
    name: 'stranger'
  

  render() 
    return (
      <div>Hello, this.props.name</div>
    )
  

和服务端交互

组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI 。

获取真实 DOM 节点

参考文档:https://reactjs.org/docs/refs-and-the-dom.html

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性。

示例:

class CustomTextInput extends React.Component 
  constructor(props) 
    super(props);
    this.focusTextInput = this.focusTextInput.bind(this);
  

  focusTextInput() 
    // Explicitly focus the text input using the raw DOM API
    this.textInput.focus();
  

  render() 
    // Use the `ref` callback to store a reference to the text input DOM
    // element in an instance field (for example, this.textInput).
    return (
      <div>
        <input
          type="text"
          ref=(input) =>  this.textInput = input;  />
        <input
          type="button"
          value="Focus the text input"
          onClick=this.focusTextInput
        />
      </div>
    );
  

TodoMVC

开始

下载模板:

git clong https://github.com/tastejs/todomvc-app-template.git --depth=1 todomvc-react

安装依赖:

cd todomvc-react
npm install

安装 react 开发环境依赖:

npm install --save babel-standalone react react-dom

React 其它

React DevTools

https://github.com/facebook/react-devtools

create-react-app

以上是关于React:JSX环境配置和基础语法,列表等操作的主要内容,如果未能解决你的问题,请参考以下文章

React基础-JSX语法列表渲染详解

2017.11.30 React基础语法之一JSX

React 语法基础之表达式和jsx

React教程:JSX语法基础

React:JSX

React 6/100 React原理 | setState | JSX语法转换 | 组件更新机制