初识React

  1. react是一个js库,更加关注视图的构建。
  2. 在原生h5应用中,js操作dom代价是非常昂贵的,react是以最小代价(最少次数)去操作dom, 但不一定比原生js操作dom快。

与原生js做比较

  1. // html
  2. <div id="app"></div>
  3. // js
  4. <script>
  5. document.getElementById('app').innerHTML = '<h1>hello, world pure</h1>'
  6. </script>
  7. // react
  8. <script src="../lib/react.js"></script>
  9. <script src="../lib/react-dom.js"></script>
  10. <script src="../lib/babel.min.js"></script>
  11. <script type="text/babel">
  12. ReactDOM.render(
  13. <h1>hello, world</h1>,
  14. document.getElementById('app')
  15. );
  16. </script>

元素(Element)

  1. 元素是构成React应用的最小单元
  2. 元素是你在屏幕上能够看到的东西
  3. 可以简单理解为,用标签包裹起来的就是元素
  1. // 元素
  2. const element = <div>huang</div>;

JSX

在React中,jsx是用来声明React元素的

  1. // 原生js中
  2. var element = '<h1>hello-world, dada</h1>';
  3. // jsx中
  4. const element = <h1>hello-world, dada</h1>;
  5. ReactDOM.render(
  6. element,
  7. document.getElementById('app')
  8. );

1. 嵌入表达式

通过一个大括号

  1. const element = <h1>{ 1 + 2 }</h1>; // 3

2. JSX属性

  1. // 传递属性为字符串要加上引号
  2. const element = <div name="logo">my logo</div>; // my logo
  3. // 传递属性为变量要加上{}
  4. const data = 'dada'
  5. const element = <div data={data}>huang</div> // huang

JSX的属性采用驼峰命名: 注意一些特殊标签的命名, class要写成className, tabindex要写成tabIndex

3. 自闭标签

  1. // 没有内容的标签,可以选择自闭
  2. const element = <img src="https://fe.imdada.cn/myosotis/assets/src/home/images/next.png" />

4. JSX实质

  1. // 以下两段代码是等价的
  2. const element = (
  3. <h1 className="greeting">Hello, world!</h1>
  4. );
  5. // 编译成对象
  6. const element = React.createElement(
  7. 'h1', // 标签名
  8. {className: 'greeting'}, // 属性值
  9. 'Hello, world!' // 内容值
  10. );

组件及props(重要)

组件可以将UI切分成一些的独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件。

用函数定义组件

纯展示组件,所有数据都通过外部传入

  1. function Welcome(props) {
  2. return <h1>Hello</h1>;
  3. }

用class定义组件

  1. 带状态的组件,组件内部允许有组件自己维护的数据
  2. 可以使用生命周期函数
  1. class Welcome extends React.Component {
  2. state = {
  3. // 组件内部有自己维护的数据,不供外部使用,它是局部的
  4. data: 'Hello'
  5. }
  6. render() {
  7. return <h1>{ this.state.name }</h1>;
  8. }
  9. }

组件抽离

  1. 可以组件复用
  2. 可维护性高
  3. 一个逻辑复杂的组件尽量只做一件事
  1. function Comment(props) {
  2. return (
  3. <div className="Comment">
  4. <div className="UserInfo">
  5. <img className="Avatar"
  6. src={props.author.avatarUrl}
  7. alt={props.author.name}
  8. />
  9. <div className="UserInfo-name">
  10. {props.author.name}
  11. </div>
  12. </div>
  13. <div className="Comment-text">
  14. {props.text}
  15. </div>
  16. <div className="Comment-date">
  17. {formatDate(props.date)}
  18. </div>
  19. </div>
  20. );
  21. }
  22. // 抽离userInfo
  23. function UserInfo(props) {
  24. return (
  25. <div className="UserInfo">
  26. <img className="Avatar"
  27. src={props.author.avatarUrl}
  28. alt={props.author.name}
  29. />
  30. <div className="UserInfo-name">
  31. {props.user.name}
  32. </div>
  33. </div>
  34. );
  35. }
  36. // 变成
  37. function Comment(props) {
  38. return (
  39. <div className="Comment">
  40. <UserInfo user={props.author} />
  41. <div className="Comment-text">
  42. {props.text}
  43. </div>
  44. <div className="Comment-date">
  45. {formatDate(props.date)}
  46. </div>
  47. </div>
  48. );
  49. }

props

  1. 顾名思义是指组件的属性
  2. props是只读的,一定不能(直接)更改props的值
  1. const Welcome = props => {
  2. return <h1>Hi, { props.name }</h1>
  3. }
  4. // name为组件属性
  5. const element = <Welcome name="NewDada" />
  6. ReactDOM.render(
  7. element,
  8. document.getElementById('app')
  9. );
  10. // 输出 Hi, NewDada

state及生命周期

  1. 一个组件需要有自己的状态,需要用到state
  2. state是私有的,完全受控于当前组件。
  3. 要使用state, 你需要将函数声明的组件转化为class声明的组件

看一个例子: Clock.js

注意:

  1. 不要直接更新state, 只能使用this.setState函数进行更新。
  2. 如果你有些内部数据不在render函数中使用,请不要放在state中。

生命周期

第一次渲染时相关生命周期函数

  1. constructor() {}
  2. componentWillMount() {} // 组件将要挂载
  3. render() {} // 渲染
  4. componentDidMount() {} // 组件已经挂载
  5. // 组件将要卸载时调用
  6. componentWillUnmount() {}

组件更新时

  1. componentWillReceiveProps() {}
  2. shouldComponentUpdate() {}
  3. componentWillUpdate() {}
  4. componentDidUpdate() {}