freeCodeCamp 旅途14 - React

React:创建一个简单的 JSX 元素

React 是由 Facebook 创建和维护的开源视图库。它是渲染当代 Web 应用程序用户界面(UI)的绝佳工具。

React 使用名为 JSX 的 JavaScript 语法扩展,允许你直接在 JavaScript 中编写 HTML。这有几个好处。它允许你在 HTML 中使用 JavaScript 的完整程序功能,并有助于保持代码的可读性。

但是,由于浏览器不能解析 JSX,因此必须将 JSX 代码编译为 JavaScript。比如 转换器 Babel 。

ReactDOM.render(JSX, document.getElementById('root'))这个函数调用是将你的 JSX 置于 React 自己的轻量级 DOM 中。然后,React 使用自己的 DOM 快照来优化更新实际 DOM 的特定部分。

React:创建一个复杂的 JSX 元素

// 几个作为兄弟元素而编写的JSX元素没有父元素包裹将不会被转换
// 有效的 JSX:
<div>
  <p>Paragraph One</p>
  <p>Paragraph Two</p>
  <p>Paragraph Three</p>
</div>

const JSX = (
<div>
  <h1>Heading.</h1>
  <p>Paragraph</p>
 <ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
</div>
); 

React:在 JSX 中添加注释

要将注释放在 JSX 中,可以使用{/* */}语法来包裹注释文本。

React:渲染 HTML 元素为 DOM 树

在 React 中,我们可以使用它的的渲染 API(ReactDOM)将此 JSX 直接渲染到 HTML DOM。

ReactDOM 提供了一个简单的方法来将 React 元素呈现给 DOM,如下所示:ReactDOM.render(componentToRender, targetNode),其中第一个参数是要渲染的 React 元素或组件,第二个参数是要将组件渲染到的 DOM 节点。

React:在 JSX 中定义一个 HTML Class

JSX 的一个关键区别是你不能再使用class这个单词来定义 HTML 的 class 名。这是因为class是 JavaScript 中的关键字。JSX 使用className代替。

事实上,JSX 中所有 HTML 属性和事件引用的命名约定都变成了驼峰式

React:了解自动闭合的 JSX 标记

JSX 不同于 HTML 的另一个重要方面是自闭合标签。

任何 JSX 元素都可以使用自闭合标签编写,并且每个元素都必须关闭。例如,换行标签必须始终编写为<br />。另一方面<div>可以写成<div />或者<div></div>

const JSX = (
  <div>
    <h2>Welcome to React!</h2> <br />
    <p>Be sure to close all tags!</p>
    <hr />
  </div>
);

React:创建一个无状态的函数组件

组件是 React 的核心。

有两种方法可以创建 React 组件。第一种方法是使用 JavaScript 函数。以这种方式定义组件会创建无状态功能组件。目前,可以将无状态组件视为可以接收数据并对其进行渲染的组件,但是它不管理或跟踪对数据的更改。

要用函数创建组件,只需编写一个返回 JSX 或null的 JavaScript 函数。需要注意的一点是,React 要求你的函数名以大写字母开头。

const DemoComponent = function() {
  return (
    <div className='customClass' />
  );
};

React:创建一个 React 组件

定义 React 组件的另一种方法是使用 ES6 的class语法。

class Kitten extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <h1>Hi</h1>
    );
  }
}

React:用组合的方式创建一个 React 组件

const ChildComponent = () => {
  return (
    <div>
      <p>I am the child</p>
    </div>
  );
};
class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>I am the parent</h1>
        <ChildComponent />
      </div>
    );
  }
};

React:使用 React 渲染嵌套组件

const TypesOfFruit = () => {
  return (
    <div>
      <h2>Fruits:</h2>
      <ul>
        <li>Apples</li>
        <li>Blueberries</li>
        <li>Strawberries</li>
        <li>Bananas</li>
      </ul>
    </div>
  );
};
const Fruits = () => {
  return (
    <div>
        <TypesOfFruit />
    </div>
  );
};
class TypesOfFood extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>Types of Food:</h1>
          <Fruits />
      </div>
    );
  }
};

React:组合 React 组件

class Fruits extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h2>Fruits:</h2>
        <NonCitrus />
        <Citrus />
      </div>
    );
  }
};
class TypesOfFood extends React.Component {
  constructor(props) {
     super(props);
  }
  render() {
    return (
      <div>
        <h1>Types of Food:</h1>
        <Fruits />
        <Vegetables />
      </div>
    );
  }
};

React:渲染 class 组件为 Dom 树

React 组件传递到ReactDOM.render()与 JSX 元素略有不同。对于 JSX 元素,你传入的是要渲染的元素的名称。但是,对于 React 组件,你需要使用与渲染嵌套组件相同的语法,例如ReactDOM.render(<ComponentToRender />, targetNode)

class TypesOfFood extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>Types of Food:</h1>
        <Fruits />
        <Vegetables />
      </div>
    );
  }
};
ReactDOM.render(<TypesOfFood />, document.getElementById("challenge-node"));

React:从零开始写一个 React 组件

class MyComponent extends React.Component {
  constructor(props){
    super(props)
  }
  render(){
    return (
      <div>
       <h1>My First React Component!</h1>
      </div>
    )
  }
}
ReactDOM.render(<MyComponent />, document.getElementById("challenge-node"))

React:将 Props 传递给无状态函数组件

假设你有一个App组件,该组件渲染了一个名为Welcome的子组件,它是一个无状态函数组件。你可以通过以下方式给Welcome传递一个user属性:

<App>
  <Welcome user='Mark' />
</App>

使用自定义 HTML 属性,React 支持将属性user传递给组件Welcome。由于Welcome是一个无状态函数组件,它可以像这样访问该值:

const Welcome = (props) => <h1>Hello, {props.user}!</h1>

自定义属性中使用 javascript 需要使用花括号,并且不需要引号。

const CurrentDate = (props) => {
  return (
    <div>
      <p>The current date is: { props.date } </p>
    </div>
  );
};
class Calendar extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h3>What date is it?</h3>
        <CurrentDate date={Date()} />
      </div>
    );
  }
};

React:传递一个数组作为 Props

要将数组传递给 JSX 元素,必须将其视为 JavaScript 并用花括号括起来。

<ParentComponent>
  <ChildComponent colors={["green", "blue", "red"]} />
</ParentComponent>

const ChildComponent = (props) => <p>{props.colors.join(', ')}</p>

React:使用默认的 Props

React 还有一个设置默认 props 的选项。如果你声明MyComponent.defaultProps = { location: 'San Francisco' },即定义一个 location 属性,并且其值在没有另行制定的情况下被设置为字符串San Francisco。如果 props 未定义,则 React 会分配默认 props,但如果你将null作为 prop 的值,它将保持null

const ShoppingCart = (props) => {
  return (
    <div>
      <h1>Shopping Cart Component</h1>
    </div>
  )
};
ShoppingCart.defaultProps = {
  items: 0
};

React:覆盖默认的 Props

在 React 中,设置默认的 props 是一个很有用的特性,显式设置组件的 prop 值即可覆盖默认 props。

const Items = (props) => {
  return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
}
Items.defaultProps = {
  quantity: 0
}
class ShoppingCart extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <Items quantity={10} />
  }
};

React:使用 PropTypes 来定义你期望的 Props

React 提供了有用的类型检查特性,以验证组件是否接收了正确类型的 props。例如,你的应用程序调用 API 来检索你希望在数组中的数据,然后将数据作为 prop 传递给组件。你可以在组件上设置propTypes,以要求数据的类型为array。当数据是任何其他类型时,都会抛出警告。

// 在 7 种 JavaScript 基本类型中,function和boolean(写为bool)是仅有的使用异常拼写的两种类型
MyComponent.propTypes = { handleClick: PropTypes.func.isRequired }

// 在 React v15.5.0 版本中, PropTypes可以从 React 中单独引入
import React, { PropTypes } from 'react';

const Items = (props) => {
  return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
};
Items.propTypes = {
  quantity: PropTypes.number.isRequired
};
Items.defaultProps = {
  quantity: 0
};
class ShoppingCart extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <Items />
  }
};

React:使用 this.props 访问 Props

class ReturnTempPassword extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
        <div>
            <p>Your temporary password is: <strong>{this.props.tempPassword}</strong></p>
        </div>
    );
  }
};
class ResetPassword extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
        <div>
          <h2>Reset Password</h2>
          <h3>We've generated a new temporary password for you.</h3>
          <h3>Please reset this password from your account settings ASAP.</h3>
          <ReturnTempPassword tempPassword='qweasdzxc' />
        </div>
    );
  }
};

React:复习如何使用 Props 和无状态函数组件

无状态函数组件是一个函数,它接收 props 作为输入并返回 JSX。另一方面,无状态组件是一个类,它扩展了React.Component,但是不使用内部状态。最后,状态组件是指维护其自身内部状态的组件,它简称组件或 React 组件。

class CampSite extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <Camper name='Hello React!' />
      </div>
    );
  }
};
const Camper = props => (<p>{props.name}</p>);
Camper.defaultProps = {
  name: 'CamperBot'
};
Camper.propTypes = {
  name: PropTypes.string.isRequired
};

React:创建一个有状态的组件

React中最重要的主题之一是state。 state 包含应用程序需要了解的任何数据,这些数据可能会随时间而变化。

你可以通过在constructor中的组件类上声明state属性来在 React 组件中创建 state,它在创建时使用state初始化组件。state属性必须设置为 JavaScript对象。声明如下:

class StatefulComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'HJSD'
    };
  }
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};

你可以在组件的整个生命周期内访问state对象,你可以更新它、在 UI 中渲染它,也可以将其作为 props 传递给子组件。

React:在用户界面中渲染状态

如果你想在 render 方法的return中访问 state 值,你必须把这个值用花括号括起来。

React 使用所谓的虚拟 DOM 来跟踪幕后的变化。当 state 数据更新时,它会使用该数据触发组件的重新渲染--包括接收 prop 数据的子组件。React 只在必要的时候更新实际的DOM,这意味着你不必担心 DOM 的变更,只需声明 UI 的外观即可。

注意,如果组件有状态,则没有其他组件知道它的state。它的state是完全封装的,或者是局限于组件本身的,除非你将 state 数据作为props传递给子组件。
封装state的概念非常重要,因为它允许你编写特定的逻辑,然后将该逻辑包含并隔离在代码中的某个位置。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'freeCodeCamp'
    }
  }
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};

React:以另一种方式在用户界面中渲染状态

render()方法中,在return语句之前,你可以直接编写 JavaScript。例如,你可以声明函数、从stateprops访问数据、对此数据执行计算等。然后,你可以将任何数据赋值给你在return语句中可以访问的变量。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'freeCodeCamp'
    }
  }
  render() {
    const name = this.state.name;
    return (
      <div>
        <h1>{name}</h1>
      </div>
    );
  }
};

React:用 this.setState 设置状态

React 提供了setState方法来更新组件的state。在组件类中调用setState方法如下所示:this.setState(),传入键值对的对象,其中键是 state 属性,值是更新后的 state 数据。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Initial State'
    };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      name: 'React Rocks!'
    });
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me</button>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};

React 希望你永远不要直接修改state,而是在 state 发生改变时始终使用this.setState()。此外,React 可以批量处理多个 state 更新以提高性能。这意味着通过setState方法进行的 state 更新可以是异步的setState方法有一种替代语法可以解决异步问题,虽然这很少用到,但是最好还是记住它!React 文档

React:将 this 绑定到 Class 方法

有几种方法可以让你的类方法访问this

一种常见的方法是在构造函数中显式地绑定this,这样当组件初始化时,this就会绑定到类方法。this.handleClick = this.handleClick.bind(this)用于其在构造函数中的handleClick方法。然后,当你在类方法中调用像this.setState()这样的函数时,this指的是这个类,而不是undefined

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      itemCount: 0
    };
    this.addItem = this.addItem.bind(this);
  }
  addItem() {
    this.setState({
      itemCount: this.state.itemCount + 1
    });
  }
  render() {
    return (
      <div>
        <button onClick={this.addItem}>Click Me</button>
        <h1>Current Item Count: {this.state.itemCount}</h1>
      </div>
    );
  }
};

React:使用 State 切换元素

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visibility: false
    };
    this.toggleVisibility = this.toggleVisibility.bind(this);
  }
  toggleVisibility(){
    this.state.visibility = !this.state.visibility;
  }
  render() {
    if (this.state.visibility) {
      return (
        <div>
          <button onClick={this.toggleVisibility}>Click Me</button>
          <h1>Now you see me!</h1>
        </div>
      );
    } else {
      return (
        <div>
          <button onClick={this.toggleVisibility}>Click Me</button>
        </div>
      );
    }
  }
};

React:写一个简单的计数器

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
    this.reset = this.reset.bind(this);
  }
  increment(){
    this.setState({  count: this.state.count + 1 });
  }
  decrement(){
    this.setState({   count: this.state.count - 1 });
  }
  reset(){
    this.setState({   count: 0 });
  }
  render() {
    return (
      <div>
        <button className='inc' onClick={this.increment}>Increment!</button>
        <button className='dec' onClick={this.decrement}>Decrement!</button>
        <button className='reset' onClick={this.reset}>Reset</button>
        <h1>Current Count: {this.state.count}</h1>
      </div>
    );
  }
};

React:创建一个可以控制的输入框

class ControlledInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event){
    this.setState({
      input: event.target.value
    })
  }
  render() {
    return (
      <div>
        <input type="text" value={this.state.input} onChange={this.handleChange} />
        <h4>Controlled Input:</h4>
        <p>{this.state.input}</p>
      </div>
    );
  }
};

React:创建一个可以控制的表单

class MyForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      submit: ''
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleChange(event) {
    this.setState({
      input: event.target.value,
      submit: ''
    });
  }
  handleSubmit(event) {
    event.preventDefault();
    this.setState({
      input: '',
      submit: this.state.input
    });
  }
  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input value={this.state.input} onChange={this.handleChange}/>
          <button type='submit' onSubmit={this.handleSubmit}>Submit!</button>
        </form>
       <h1>{this.state.submit}</h1>
      </div>
    );
  }
};

React:将 State 作为 Props 传递给子组件

props 是从哪里来的。一个常见的模式是:有状态组件中包含对应用程序很重要的state,然后用它渲染子组件。你希望这些组件能够访问该state的某些部分,就把这些部分作为 props 传入。

例如,也许你有一个App组件可以渲染Navbar以及其他组件。在你的App中,你的state中包含大量用户信息,但是Navbar只需要访问用户的用户名就可以显示出来,这时你将该state作为一个 prop 传递给Navbar组件即可。

这个模式说明了 React 中的一些重要范例。第一个是单向数据流,state 沿着应用程序组件树的一个方向流动,从有状态父组件到子组件,子组件只接收它们需要的 state 数据。第二,复杂的有状态应用程序可以分解成几个,或者可能是一个单一的有状态组件。其余组件只是从父组件简单的接收 state 作为 props,并从该 state 渲染 UI。

它开始创建一种分离,在这种分离中,state 管理在代码的一部分中处理,而 UI 渲染在另一部分中处理。将 state 逻辑与 UI 逻辑分离是 React 的关键原则之一。当它被正确使用时,它使得复杂的、有状态的应用程序的设计变得更容易管理。

class MyApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'CamperBot'
    }
  }
  render() {
    return (
       <div>
         <Navbar name={this.state.name} />
       </div>
    );
  }
};
class Navbar extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
    <div>
      <h1>Hello, my name is: {this.props.name} </h1>
    </div>
    );
  }
};

React:传递回调作为 Props

class MyApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: ''
    }
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({
      inputValue: event.target.value
    });
  }
  render() {
    return (
       <div>
        <GetInput input={this.state.inputValue} handleChange={this.handleChange} />
        <RenderInput input={this.state.inputValue} />
       </div>
    );
  }
};

class GetInput extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h3>Get Input:</h3>
        <input
          value={this.props.input}
          onChange={this.props.handleChange}/>
      </div>
    );
  }
};
class RenderInput extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h3>Input Render:</h3>
        <p>{this.props.input}</p>
      </div>
    );
  }
};

React:使用生命周期方法:componentWillMount

React 组件有几种特殊方法,可以在组件生命周期的特定点执行操作。这些称为生命周期方法或生命周期钩子,允许你在特定时间点捕获组件。这可以在渲染之前、更新之前、接收 props 之前、卸载之前等等。以下是一些主要生命周期方法的列表:

componentWillMount()
componentDidMount()
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
componentWillUnmount()

React:使用生命周期方法:componentDidMount

React 的最佳实践是在生命周期方法componentDidMount()中对服务器进行 API 调用或任何其他调用。将组件装载到 DOM 后会调用此方法。此处对setState()的任何调用都将触发组件的重新渲染。在此方法中调用 API 并使用 API​​ 返回的数据设置 state 时,一旦收到数据,它将自动触发更新。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      activeUsers: null
    };
  }
  componentDidMount() {
    setTimeout( () => {
      this.setState({
        activeUsers: 1273
      });
    }, 2500);
  }
  render() {
    return (
      <div>
        <h1>Active Users: { this.state.activeUsers }</h1>
      </div>
    );
  }
};

React:添加事件侦听器

componentDidMount()方法也是添加特定功能所需的任何事件监听器的最佳位置。

React 的合成事件系统非常适合用于你在 DOM 元素上管理的大多数交互。但是,如果要将事件处理程序附加到 document 或 window 对象,则必须直接执行此操作。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      message: ''
    };
    this.handleEnter = this.handleEnter.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
  }
  componentDidMount() {
    document.addEventListener('keydown', this.handleKeyPress)
  }
  componentWillUnmount() {
    document.removeEventListener('keydown', this.handleKeyPress)
  }
  handleEnter() {
    this.setState({
      message: this.state.message + 'You pressed the enter key! '
    });
  }
  handleKeyPress(event) {
    if (event.keyCode === 13) {
      this.handleEnter();
    }
  }
  render() {
    return (
      <div>
        <h1>{this.state.message}</h1>
      </div>
    );
  }
};

React:使用生命周期方法管理更新

另一个生命周期方法是componentWillReceiveProps(),只要组件将要接收新的 props 就会调用它。此方法接收新的 props(通常写为nextProps)作为参数。

还有一个方法是componentDidUpdate(),它在组件重新渲染后立即调用。请注意,渲染和装载在组件生命周期中是不同的。当页面第一次加载时,所有组件都被装载,这就是调用componentWillMount()componentDidMount()等方法的地方。此后,随着 state 的变化,组件会重新渲染自己。

class Dialog extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillUpdate() {
    console.log('Component is about to update...');
  }
  componentWillReceiveProps(nextProps){
    console.log("this.props: "+this.props)
    console.log('nextProps: '+nextProps);
  }
  componentDidUpdate(){
    console.log('componentDidUpdate');
  }
  render() {
    return <h1>{this.props.message}</h1>
  }
};

class Controller extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      message: 'First Message'
    };
    this.changeMessage = this.changeMessage.bind(this);
  }
  changeMessage() {
    this.setState({
      message: 'Second Message'
    });
  }
  render() {
    return (
      <div>
        <button onClick={this.changeMessage}>Update</button>
        <Dialog message={this.state.message}/>
      </div>
    );
  }
};

React:使用 shouldComponentUpdate 优化重新渲染

如果任何组件接收到新的state或新的props,它会重新渲染自己及其所有子组件。这通常是好的。但是 React 提供了一种生命周期方法,当子组件接收到新的stateprops时,你可以调用该方法,并特别声明组件是否应该更新。方法是shouldComponentUpdate(),它将nextPropsnextState作为参数。

这种方法是优化性能的有效方法。例如,默认行为是,当组件接收到新的props时,即使props没有改变,它也会重新渲染。你可以通过使用shouldComponentUpdate()比较props来防止这种情况。

该方法必须返回一个布尔值,该值告诉 React 是否更新组件。你可以比较当前的 props(this.props)和下一个 props(nextProps),以确定你是否需要更新,并相应地返回truefalse

class OnlyEvens extends React.Component {
  constructor(props) {
    super(props);
  }
  shouldComponentUpdate(nextProps, nextState) {
    console.log('Should I update?');
    return nextProps.value % 2 === 0;
  }
  componentWillReceiveProps(nextProps) {
    console.log('Receiving new props...');
  }
  componentDidUpdate() {
    console.log('Component re-rendered.');
  }
  render() {
    return <h1>{this.props.value}</h1>
  }
};
class Controller extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 0
    };
    this.addValue = this.addValue.bind(this);
  }
  addValue() {
    this.setState({
      value: this.state.value + 1
    });
  }
  render() {
    return (
      <div>
        <button onClick={this.addValue}>Add</button>
        <OnlyEvens value={this.state.value}/>
      </div>
    );
  }
};

React:介绍内联样式

如何对在 React 中创建的 JSX 元素进行风格化。如果从样式表导入样式,它就没有太大的不同。使用className属性将 class 应用于 JSX 元素,并将样式应用于样式表中的 class。另一种选择是使用内联样式,这在 ReactJS 开发中非常常见。

//  HTML 中内联样式
<div style="color: yellow; font-size: 16px">Mellow Yellow</div>

// JSX 元素使用style属性
<div style={{color: "yellow", fontSize: 16}}>Mellow Yellow</div>

class Colorful extends React.Component {
  render() {
    return (
      <div style={{fontSize:"72px",color:"red"}}>Big Red</div>
    );
  }
};

React:在 React 中添加内联样式

所有属性值是长度的(如heightwidthfontSize)其单位都假定为px。例如,如果要使用em,可以用引号将值和单位括起来,例如{fontSize: "4em"}。除了默认为px的长度值之外,所有其他属性值都应该用引号括起来。

const styles = {fontSize: 40, color: "purple", border:"2px solid purple"};
class Colorful extends React.Component {
  render() {
    return (
      <div style={styles}>Style Me!</div>
    );
  }
};

React:在 React Render 方法中使用 JavaScript

render方法中编写 JavaScript,你可以把 JavaScript 直接放在return语句之前,而不必将其插入大括号中。这是因为它还不在 JSX 代码中。当你稍后想在return语句中的 JSX 代码中使用变量时,可以将变量名放在大括号中。

render() {
    const possibleAnswers = [
      'It is certain',
      'It is decidedly so',
      'Without a doubt', 
      'Yes, definitely',
      'You may rely on it',
      'As I see it, yes',
      'Outlook good',
      'Yes',
      'Signs point to yes',
      'Reply hazy try again',
      'Ask again later',
      'Better not tell you now',
      'Cannot predict now',
      'Concentrate and ask again',
      'Don\'t count on it', 
      'My reply is no',
      'My sources say no',
      'Most likely',
      'Outlook not so good',
      'Very doubtful'
    ];
    const answer = possibleAnswers[this.state.randomIndex];
    return (...)
}

React:使用 If/Else 条件进行渲染

使用 JavaScript 控制渲染视图的另一个应用是将渲染的元素绑定到一个条件。当条件为真时,将呈现一个视图,反之,则呈现另一种视图。你可以在 React 组件的render()方法中使用的标准if/else语句来实现这一点。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      display: true
    }
    this.toggleDisplay = this.toggleDisplay.bind(this);
  }
  toggleDisplay() {
    this.setState({
      display: !this.state.display
    });
  }
  render() {
    if(this.state.display){
        return (
        <div>
          <button onClick={this.toggleDisplay}>Toggle Display</button>
          <h1>Displayed!</h1>
        </div>
      );
    }else {
      return (
        <div>
          <button onClick={this.toggleDisplay}>Toggle Display</button>
        </div>
      );
    }
  }
};

React:使用 && 获得更简洁的条件

if/else 语句在上一次挑战中是有效的,但是有一种更简洁的方法可以达到同样的结果。你可以使用&&逻辑运算符以更简洁的方式执行条件逻辑。

{condition && <p>markup</p>}

render() {
    return (
       <div>
         <button onClick={this.toggleDisplay}>Toggle Display</button>
         {this.state.display && <h1>Displayed!</h1>}
       </div>
    );
  }

React:使用三元表达式进行条件渲染

在继续使用动态渲染技术之前,还有最后一种方法可以渲染你想要的东西,它使用内置的 JavaScript 条件:三元运算符

const inputStyle = {
  width: 235,
  margin: 5
}
class CheckUserAge extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      userAge: ''
    };
    this.submit = this.submit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(e) {
    this.setState({
      input: e.target.value,
      userAge: ''
    });
  }
  submit() {
    this.setState({
      userAge: this.state.input
    });
  }
  render() {
    const buttonOne = <button onClick={this.submit}>Submit</button>;
    const buttonTwo = <button>You May Enter</button>;
    const buttonThree = <button>You Shall Not Pass</button>;
    return (
      <div>
        <h3>Enter Your Age to Continue</h3>
        <input
          style={inputStyle}
          type="number"
          value={this.state.input}
          onChange={this.handleChange} /><br />
        {
          this.state.userAge===''?buttonOne: (this.state.userAge < 18?buttonThree:buttonTwo)
        }
      </div>
    );
  }
};

React:根据 Props 有条件地渲染

使用 props 有条件地渲染代码在 React 开发人员中很常见--也就是说:他们使用给定 prop 的值来自动决定渲染什么。

class Results extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <h1>
      {
        this.props.fiftyFifty
      }
      </h1>
    )
  };
};
class GameOfChance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 1
    }
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      counter: this.state.counter+1 
    });
  }
  render() {
    let expression = Math.random() > 0.5; 
    return (
      <div>
        <button onClick={this.handleClick}>Play Again</button>
        {(expression == 1)? <Results fiftyFifty="You win!"/> : <Results fiftyFifty="You lose!"/> }
        <p>{'Turn: ' + this.state.counter}</p>
      </div>
    );
  }
};

React:根据组件状态有条件地更改内联 CSS

根据 React 组件的 state 有条件地渲染 CSS。要执行此操作,请检查条件,如果满足该条件,则修改在 render 方法中分配给 JSX 元素的样式对象。

class GateKeeper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({ input: event.target.value })
  }
  render() {
    let inputStyle = {
      border: '1px solid black'
    };
    if(this.state.input.length > 15){
      inputStyle.border = '3px solid red';
    }
    return (
      <div>
        <h3>Don't Type Too Much:</h3>
        <input
          type="text"
          style={inputStyle}
          value={this.state.input}
          onChange={this.handleChange} />
      </div>
    );
  }
};

React:使用 Array.map() 动态渲染元素

const textAreaStyles = {
  width: 235,
  margin: 5
};
class MyToDoList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userInput: '',
      toDoList: []
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }
  handleSubmit() {
    const itemsArray = this.state.userInput.split(',');
    this.setState({
      toDoList: itemsArray
    });
  }
  handleChange(e) {
    this.setState({
      userInput: e.target.value
    });
  }
  render() {
    const items = this.state.toDoList.map(i => <li>{i}</li>);; 
    return (
      <div>
        <textarea
          onChange={this.handleChange}
          value={this.state.userInput}
          style={textAreaStyles}
          placeholder="Separate Items With Commas" /><br />
        <button onClick={this.handleSubmit}>Create List</button>
        <h1>My "To Do" List:</h1>
        <ul>
          {items}
        </ul>
      </div>
    );
  }
};

React:给同级元素一个唯一的键属性


const frontEndFrameworks = [
  'React',
  'Angular',
  'Ember',
  'Knockout',
  'Backbone',
  'Vue'
];

function Frameworks() {
  const renderFrameworks = frontEndFrameworks.map(x => <li key={x+1}>{x}</li>); 
  return (
    <div>
      <h1>Popular Front End JavaScript Frameworks</h1>
      <ul>
        {renderFrameworks}
      </ul>
    </div>
  );
};

使用 Array.Filter() 动态过滤数组

filter 它根据条件过滤数组的内容,然后返回一个新数组。例如,如果你有一个 users 数组,每个数组元素都有一个可以设置为truefalseonline属性,你可以只过滤那些在线的用户:let onlineUsers = users.filter(user => user.online);

const usersOnline = this.state.users.filter(i => i.online == true); 
const renderOnline = usersOnline.map((i) => <li key={i.username + 1}>{i.username}</li>);

React:用 renderToString 在服务器上渲染 React

由于 React 是一个 JavaScript 视图库,所以使用 Node 让 JavaScript 运行在服务器上是可行的。事实上,React 提供了一个可用于此目的的renderToString()方法。renderToString()方法由ReactDOMServer提供。

class App extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <div/>
  }
};
ReactDOMServer.renderToString(<App />);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 1、什么是react React.js 是一个帮助你构建页面 UI 的库。React.js 将帮助我们将界面分成了...
    谷子多阅读 2,554评论 1 13
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 1,001评论 0 1
  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,804评论 0 24
  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,414评论 1 33
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,039评论 2 35