To learn React, check out the React documentation.

元素是构成 React 应用的最小单位,JSX 就是用来声明 React 当中的元素。

与浏览器的DOM元素不同,React当中的元素实际是普通的对象
React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
要将 React 元素渲染到根 DOM 节点中,我们通过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上:
ps:由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。

在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。以下实例中如果变量 i 等于 1 浏览器将输出 true, 如果修改 i 的值,则会输出 false.

  1. ReactDOM.render(
  2. <div>
  3. <h1>{i == 1 ? 'True!' : 'False'}</h1>
  4. </div>
  5. ,
  6. document.getElementById('example')
  7. );

样式

React 推荐使用内联样式。我们可以使用 camelCase 语法来设置内联样式. React 会在指定元素数字后自动添加 px 。以下实例演示了为 h1 元素添加 myStyle 内联样式:

var myStyle = {
    fontSize: 100,
    color: '#FF0000'
};
ReactDOM.render(
    <h1 style = {myStyle}>菜鸟教程</h1>,
    document.getElementById('example')
);

数组

JSX 允许在模板中插入数组,数组会自动遍历展开所有成员:
var arr = [
  <h1>菜鸟教程</h1>,
  <h2>学的不仅是技术,更是梦想!</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);

创建组件

1.我们可以使用函数定义了一个组件:
function HelloMessage(props) {
    return <h1>Hello World!</h1>;
}
----
2.也可以使用 ES6 class 来定义一个组件:

class Welcome extends React.Component {
  render() {
    return <h1>Hello World!</h1>;
  }
}

注意,原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。

向组件传递参数,可以使用 this.props 对象,实例如下:

使用React.Component 的 ES6 类,该类封装了要展示的元素,需要注意的是在 render() 方法中,需要使用 this.props 替换 props:来获取值



function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>现在是 {props.date.toLocaleTimeString()}.</h2> //props.value
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('example')
  );
}

setInterval(tick, 1000);

----- 

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>现在是 {this.props.date.toLocaleTimeString()}.</h2> //this.props.value
      </div>
    );
  }
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('example')
  );
}

setInterval(tick, 1000);

()=>this.tick() 是 ES6 中声明函数的一种方式,叫做箭头函数表达式,引入箭头函数有两个方面的作用:更简短的函数并且不绑定 this。

var f = ([参数]) => 表达式(单一)
// 等价于以下写法
var f = function([参数]){
   return 表达式;
}

React Props

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

State 和 Props
以下实例演示了如何在应用中组合使用 state 和 props 。我们可以在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据。

class WebSite extends React.Component {
  constructor() {
      super();

      this.state = {
        name: "xxx",
        site: "https://www.xxx.com"
      }
    }
  render() {
    return (
      <div>
        <Name name={this.state.name} />
        <Link site={this.state.site} />
      </div>
    );
  }
}



class Name extends React.Component {
  render() {
    return (
      <h1>{this.props.name}</h1>
    );
  }
}

class Link extends React.Component {
  render() {
    return (
      <a href={this.props.site}>
        {this.props.site}
      </a>
    );
  }
}

ReactDOM.render(
  <WebSite />,
  document.getElementById('example')
);

默认 Props

你可以通过组件类的 defaultProps 属性为 props 设置默认值,实例如下:

class HelloMessage extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1> //编译后:Hello, Runoob
    );
  }
}

HelloMessage.defaultProps = {
  name: 'Runoob'
};

const element = <HelloMessage/>;

ReactDOM.render(
 element,
 document.getElementById('example')
)

React 事件处理

在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为, 你必须明确的使用 preventDefault。

一般:
<a href="#" onclick="console.log('点击链接'); return false">
  点我
</a>

react中:
function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('链接被点击');
  }

  return (
    <a href="#" onClick={handleClick}>
      点我
    </a>
  );
}

阻止组件渲染

在极少数情况下,你可能希望隐藏组件,即使它被其他组件渲染。让 render 方法返回 null 而不是它的渲染结果即可实现。

在下面的例子中, 根据属性 warn 的值条件渲染。如果 warn 的值是 false,则组件不会渲染:

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

  return (
    <div className="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 ? '隐藏' : '显示'}
        </button>
      </div>
    );
  }
}

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

key的正确使用方式:当你在 map() 方法的内部调用元素时,你最好随时记得为每一个元素加上一个独一无二的 key。

function ListItem(props) {
  // 对啦!这里不需要指定key:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 对啦!key应该在数组的上下文中被指定
    <ListItem key={number.toString()}
              value={number} />

  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('example')
);

key 会作为给 React 的提示,但不会传递给你的组件。如果您的组件中需要使用和 key 相同的值,请将其作为属性传递:

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);

setState更新是同步还是异步(8课时)

1.setState会引起视图的重绘
2.在可控的情况下是可以异步的。非可控的情况下是同步(通过async,await,promise)
3.不能在组件内部通过this.state修改状态,因为该状态会在调用setState()后被替换。

4.setState()并不会立即改变this.state,而是创建一个即将处理的state。setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染。

5.setState()总是会触发一次组件重绘,除非在shouldComponentUpdate()中实现了一些条件渲染逻辑。
6.构造函数是唯一能够初始化 this.state 的地方。(不要直接更新状态,应当使用 setState()==== this.setState({comment: ‘Hello’});)
7.状态更新可能是异步的:React 可以将多个 setState() 调用合并成一个调用来提高性能。

因为 this.props 和 this.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

class Counter extends React.Component{
  constructor(props) {
      super(props);
      this.state = {clickCount: 0};
      this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(function(state) {
      return {clickCount: state.clickCount + 1};
    });
  }
  render () {
    return (<h2 onClick={this.handleClick}>点我!点击次数为: {this.state.clickCount}</h2>);
  }
}
ReactDOM.render(
  <Counter />,
  document.getElementById('example')
);

强制更新:forceUpdate()

callback,可选参数,回调函数。该函数会在组件render()方法调用后调用。
forceUpdate()方法会使组件调用自身的render()方法重新渲染组件,组件的子组件也会调用自己的render()。但是,组件重新渲染时,依然会读取this.props和this.state,如果状态没有改变,那么React只会更新DOM。

forceUpdate()方法适用于this.props和this.state之外的组件重绘(如:修改了this.state后),通过该方法通知React需要调用render()

一般来说,应该尽量避免使用forceUpdate(),而仅从this.props和this.state中读取状态并由React触发render()调用。

生命周期

render() 初始以及更新,都会触发一遍,所以setState发生重绘。。
初始状态:count:0
Component WILL MOUNT!
Component DID MOUNT!
数据更新:count:1,触发3个生命周期
Component WILL RECEIVE PROPS!
Inline Babel script:37 Component WILL UPDATE!
Inline Babel script:40 Component DID UPDATE!

条件渲染-{xxx ? :}; 列表渲染-数组遍历{this.xxx.map(()=>{return() })}

表单

1.受控组件—内部state管理—表单适用
2.非受控组件—dom管理,Ref管理
使用场景:
管理焦点,文本选择,或媒体播放
触发强制动画
集成第三方dom库

使用方法:
    ref=“id”或者 
    input框比较多时,每个input绑定一个事件时,推荐使用非受控组件
    首先: this.id=React.createRef()
    <input ref={this.id} value=“”></input>
    获取当前dom时的值:this.id.current.value

Select 下拉菜单

在 React 中,不使用 selected 属性,而在根 select 标签上用 value 属性来表示选中项。

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('Your favorite flavor is: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          选择您最喜欢的网站
          <select value={this.state.value} onChange={this.handleChange}>
            <option value="gg">Google</option>
            <option value="rn">Runoob</option>
            <option value="tb">Taobao</option>
            <option value="fb">Facebook</option>
          </select>
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}

ReactDOM.render(
  <FlavorForm />,
  document.getElementById('example')
);

状态提升(父子通信)

组件之间的数据交互

组件组合和继承—类似vue插槽

this.props.children

antd按需加载(用到哪个css,引入哪个css)

1手动引入
2webpack配置: 使用babel-plugin-import

fecth基于promise: get请求 post请求 VS

react 项目中使用了typescript,是否还需要使用prop-types来进行格式验证。????