react简单入门介绍

以下是一个最简单的 demo,将一个最简单的组件渲染到页面上。

import React from 'react'
import { render } from 'react-dom'

// 定义组件
class Hello extends React.Component {
  render() {
    // return 里面写jsx语法
    return <p>hello world</p>
  }
}

// 渲染组件到页面
render(<Hello />, document.getElementById('root'))

**深入一下,这里`import React from 'react'`引用的是什么?**

这里的`'react'`对应的就是`./package.json`文件中`dependencies`中的`'react'`,即在

该目录下用`npm install`安装的 react 。npm 安装的 react 的物理文件是存放在

`./node_modules/react`中的,因此引用的东西肯定就在这个文件夹里面。

打开`./node_modules/react/package.json`找到`"main": "react.js",`,这里的`main`即

指定了入口文件,即`./node_modules/react/react.js`这个文件。那么,问题的答案自然

扫描二维码关注公众号,回复: 2429607 查看本文章

就出来了。

jsx 中不能一次性返回零散的多个节点,如果有多个请包涵在一个节点中。例如,

return (
  <div>
    <p>段落1</p>
    <p>段落2</p>
    <p>段落3</p>
  </div>
)
```

再例如:

```jsx
// { } 中返回的两个 <p> 也要用 <div> 包裹
return (
  <div>
    <p>段落1</p>
    {true ? (
      <p>true</p>
    ) : (
      <div>
        <p>false 1</p>
        <p>false 2</p>
      </div>
    )}
  </div>
)
```

### 注释

jsx 中用`{/* */}`的注释形式

```jsx
return (
  // jsx 外面的注释
  <div>
    {/* jsx 里面的注释 */}
    <p>hello world</p>
  </div>
)

对应 html 的两种形式,jsx 的样式可以这样写: css 样式:`<p

className="class1">hello world</p>`,注意这里是`className`,而 html 中是`class`

内联样式:`<p style={{display: 'block', fontSize: '20px'}}>hello world</p>`,注

意这里的`{{...}}`,还有`fontSize`的驼峰式写法

拿 click 事件为例,要在标签上绑定 click 事件,可以这样写

class Hello extends React.Component {
  render() {
    return <p onClick={this.clickHandler.bind(this)}>hello world</p>
  }

  clickHandler(e) {
    // e 即js中的事件对象,例如 e.preventDefault()
    // 函数执行时 this 即组件本身,因为上面的 .bind(this)
    console.log(Date.now())
  }
}

注意,`onClick`是驼峰式写法,以及`.bind(this)`的作用

在 jsx 中使用循环,一般会用到`Array.prototype.map`(来自 ES5 标准)

class Hello extends React.Component {
  render() {
    const arr = ['a', 'b', 'c']
    return (
      <div>
        {arr.map((item, index) => {
          return <p key={index}>this is {item}</p>
        })}
      </div>
    )
  }
}

注意,`arr.map`是包裹在`{}`中的,`key={index}`有助于 React 的渲染优化,jsx 中

的`{}`可放一个可执行的 js 程序或者变量

jsx 中使用判断一般会用到三元表达式(表达式也是放在`{}`中的),例如:

return (
  <div>
    <p>段落1</p>
    {
      true
      ? <p>true</p>
      : <p>false</p>
      </div>
    }
  </div>
)

也可以这样使用:

<p style={{display: true ? 'block' ? 'none'}}>hello world</p>

代码分离:

之前的 demo 代码都是在一个文件中,实际开发中不可能是这样子的,因此这里就先把组件

的代码给拆分开。我们将使用 es6 的模块管理规范。

### page 层

创建`./app/containers/Hello/index.jsx`文件,将之前创建组件代码复制进去

```jsx
import React from 'react'

class Hello extends React.Component {
  render() {
    return <p>hello world</p>
  }
}

export default Hello
```

然后`./app/index.jsx`中代码就可以这样写。

```jsx
import Hello from './containers/Hello'

render(<Hello />, document.getElementById('root'))
```

注意,代码`import Hello from './containers/Hello';`这里可以写
成`./containers/Hello/index.jsx`也可以写成`./containers/Hello/index`

### subpage 层

如果`Hello`组件再稍微复杂一点,那么把代码都放一块也会变得复杂,接下来我们再拆分
。

创建`./app/containers/Hello/subpage`目录,然后在其下创建三个文件`Carousel.jsx`
`Recommend.jsx` `List.jsx`,分别写入相应的代码(看代码文件即可),然
后`./app/containers/Hello/index.js`中即可这样写

```jsx
import Carousel from './subpage/Carousel'
import Recommend from './subpage/Recommend'
import List from './subpage/List'

class Hello extends React.Component {
  render() {
    return (
      <div>
        <p>hello world</p>
        <hr />
        <Carousel />
        <Recommend />
        <List />
      </div>
    )
  }
}
```

注意,这里`import`时`.jsx`后缀省略了。

数据传递 & 数据变化

### props

接着刚才 Header 的话题往下说,每个页面都会使用 Header ,但是 Header 上显示的标题

每个页面肯定是不一样的。我们需要这样解决:页面中引用 Header 时,这样写 `<Header

title="Hello 页面 "/>`,即给 Header 组件设置一个 title 属性。而在 Header 组件中

可以这样取到

render() {
        return (
             <p>{this.props.title}</p>
        )
    }

在 React 中,父组件给子组件传递数据时,就是以上方式,通过给子组件设置 props 的方

式,子组件取得 props 中的值即可完成数据传递。被传递数据的格式可以是任何 js 可识

别的数据结构,上面 demo 是一个字符串。**React 中,props 一般只作为父组件给子组件

传递数据用,不要试图去修改自己的 props ,除非你想自找麻烦**

上面提到了 props 不能被自身修改,如果组件内部自身的属性发生变化,该怎么办?——

React 为我们提供给了 `state`,先看一个 demo:

class Hello extends React.Component {
  constructor(props, context) {
    super(props, context)
    this.state = {
      // 显示当前时间
      now: Date.now()
    }
  }
  render() {
    return (
      <div>
        <p>hello world {this.state.now}</p>
      </div>
    )
  }
}

还有一点非常重要,**React 会实时监听每个组件的 props 和 state 的值,一旦有变化,

会立刻更新组件,将结果重新渲染到页面上**,下面 demo 演示了`state`的变化

,`props`也是一样的

class Hello extends React.Component {
  constructor(props, context) {
    super(props, context)
    this.state = {
      // 显示当前时间
      now: Date.now()
    }
  }
  render() {
    return (
      <div>
        <p onClick={this.clickHandler.bind(this)}>
          hello world {this.state.now}
        </p>
      </div>
    )
  }
  clickHandler() {
    // 设置 state 的值的时候,一定要用 this.setState ,不能直接赋值修改
    this.setState({
      now: Date.now()
    })
  }
}

智能组件 & 木偶组件

这是用 React 做系统设计时的两个非常重要的概念。虽然在 React 中,所有的单位都叫做

“ 组件 ”,但是通过以上例子,我们还是将它们分别放在

了`./app/containers`和`./app/components`两个文件夹中。为何要分开呢?

* **智能组件** 在日常开发中,我们也简称**“ 页面 ”**。为何说它 “ 智能 ”,因为它只

会做一些很聪明的事儿,脏活累活都不干。它只对数据负责,只需要获取了数据、定义好

数据操作的相关函数,然后将这些数据、函数直接传递给具体实现的组件即可。

* **木偶组件** 这里 “ 木偶 ” 一词用的特别形象,它总是被人拿线牵着。它从智能组件

(或页面)那里接受到数据、函数,然后就开始做一些展示工作,它的工作就是把拿到的

数据展示给用户,函数操作开放给用户。至于数据内容是什么,函数操作是什么,它不关

心。

以上两个如果不是理解的很深刻,待把课程学完再回头看一下这两句话,相信会理解的。

猜你喜欢

转载自blog.csdn.net/lbpro0412/article/details/81172243