一、组件

  1. //Tips:每一个页面级的组件第一行必须加
  2. import React from 'react'

二、无状态组件

  1. //就是一个函数,无状态组件中不能写事件,不能对数据进行直接的改变

App.js

  1. import React from 'react';
  2. import './App.css'
  3. import Header from '../Header'
  4. function App() {
  5. return (
  6. <div className="App">
  7. hello world
  8. {/* <p>haha</p> */}
  9. <Header/>
  10. </div>
  11. );
  12. }
  13. export default App;

Header.js

  1. import React from 'react';
  2. function Header(){
  3. return (<div>头部</div>)
  4. }
  5. export default Header

2-1 传参

2-1-1 直接传参

父组件:
image.png
子组件:
image.png

2-1-2 传state里的参数

父组件:
image.png
子组件:
image.png

三、有状态组件

Tip:rcc快捷键

  1. import React from 'react';
  2. class App extends React.Component{
  3. //数据放在构造函数的state属性
  4. constructor(props){
  5. super(props);
  6. this.state = {
  7. msg:"hello world"
  8. }
  9. }
  10. render(){
  11. return (
  12. //使用数据 {this.state.msg}
  13. <div>{this.state.msg}</div>
  14. )
  15. }
  16. }
  17. // jsx
  18. export default App;
  1. this.setState(
  2. { data: newData },
  3. () => {
  4. //这里打印的是最新的state值
  5. console.log(that.state.data);
  6. }
  7. );

3-1 事件

3-1-1 第一种

  1. //1.改变事件内部this指向的问题 bind(this)
  2. render(){
  3. return (
  4. //bind(this)改变this关键字的指向
  5. <div onClick={this.handleClick.bind(this)}>{this.state.msg}</div>
  6. )
  7. }
  8. handleClick(){
  9. this.setState({
  10. msg:"change"
  11. })
  12. }

3-1-2 第二种

  1. //2.使用箭头函数 改变this指向
  2. render(){
  3. return (
  4. <div onClick={this.handleClick}>{this.state.msg}</div>
  5. )
  6. }
  7. handleClick=()=>{
  8. this.setState({
  9. msg:"change"
  10. })
  11. }

3-2 事件参数

  1. //Tips:传递参数一定加bind bind(this,params)
  2. render(){
  3. return (
  4. <div onClick={this.handleClick.bind(this,"10001")}>{this.state.msg}</div>
  5. )
  6. }
  7. handleClick=(id)=>{
  8. console.log(id)
  9. this.setState({
  10. msg:"change"
  11. })
  12. }

四、组件传参

4-1 父组件向子组件传参

父组件

  1. import React from 'react';
  2. import Title from '../components/Title'
  3. class App extends React.Component{
  4. constructor(props){
  5. super(props);
  6. this.state={
  7. msg:'hello world',
  8. }
  9. }
  10. render(){
  11. return (
  12. <div>
  13. <Title msg={this.state.msg}></Title>
  14. </div>
  15. )
  16. }
  17. }
  18. export default App;

子组件

  1. import React from 'react';
  2. class Title extends React.Component{
  3. constructor(props){
  4. super(props)
  5. }
  6. render(){
  7. return(
  8. <h1>{this.props.msg}</h1>
  9. )
  10. }
  11. }
  12. export default Title

4-2 子组件向父组件传参

父组件自定义方法给子组件

  1. import React from 'react';
  2. import Title from '../components/Title'
  3. class App extends React.Component{
  4. constructor(props){
  5. super(props);
  6. this.state={
  7. msg:'hello world',
  8. }
  9. }
  10. render(){
  11. return (
  12. <div>
  13. <Title
  14. deleteItem = {this.handleDelete.bind(this)}
  15. msg={this.state.msg}></Title>
  16. </div>
  17. )
  18. }
  19. handleDelete(id){
  20. console.log(id)
  21. var index = this.state.musics.findIndex(item=>{
  22. if(item.id==id){
  23. return true
  24. }
  25. })
  26. var musics = this.state.musics
  27. musics.splice(index,1)
  28. this.setState({
  29. musics
  30. })
  31. }
  32. }
  33. export default App;

子组件的属性接收父组件传递过来的方法

  1. import React from 'react';
  2. class Title extends React.Component{
  3. constructor(props){
  4. super(props)
  5. }
  6. render(){
  7. return(
  8. <h1 onClick={this.handleClick.bind(this,"1355")}>{this.props.msg}</h1>
  9. )
  10. }
  11. handleClick=(id)=>{
  12. console.log(id)
  13. this.props.deleteItem(id)
  14. }
  15. }
  16. export default Title

4-3 父组件跨级传参

1553135231745.png

  1. // 最外层的父组件
  2. import PropTypes from 'prop-types';
  3. export default class Com1 extends React.Component {
  4. constructor(props) {
  5. super(props)
  6. this.state = {
  7. color: 'red'
  8. }
  9. }
  10. // 1. 在父组件中定义一个function叫做getChildContext ,方法内部返回的对象就是要共享给所有子孙组件的数据
  11. getChildContext() {
  12. return {
  13. color: this.state.color
  14. }
  15. }
  16. // 2. 使用属性校验规定一下传递给子组件的数据类型,需要是静态方法
  17. static childContextTypes = {
  18. color: PropTypes.string
  19. }
  20. render() {
  21. return <div>
  22. <h1>这是 父组件 </h1>
  23. <Com2></Com2>
  24. </div>
  25. }
  26. }
  27. // 中间的子组件
  28. class Com2 extends React.Component {
  29. render() {
  30. return <div>
  31. <h3>这是 子组件 </h3>
  32. <Com3></Com3>
  33. </div>
  34. }
  35. }
  36. // 内部的孙子组件
  37. import PropTypes from 'prop-types';
  38. class Com3 extends React.Component {
  39. // 3. 子组件在使用父组件context数据的时候首先需要对父组件传递过来的数据做类型校验
  40. static contextTypes = {
  41. color: PropTypes.string
  42. }
  43. render() {
  44. return <div>
  45. <h5 style={{ color: this.context.color }}>这是 孙子组件 --- {this.context.color} </h5>
  46. </div>
  47. }
  48. }

4-3-1 关于prop-types的使用

  1. import PropTypes from 'prop-types';
  2. MyComponent.propTypes = {
  3. // 你可以声明一个 prop 是一个特定的 JS 原始类型。 默认情况下,这些都是可选的。
  4. optionalArray: PropTypes.array,
  5. optionalBool: PropTypes.bool,
  6. optionalFunc: PropTypes.func,
  7. optionalNumber: PropTypes.number,
  8. optionalObject: PropTypes.object,
  9. optionalString: PropTypes.string,
  10. optionalSymbol: PropTypes.symbol,
  11. // 任何东西都可以被渲染:numbers, strings, elements,数组或者是包含这些类型的片段。
  12. optionalNode: PropTypes.node,
  13. // 一个 React 元素 例如 <MyComponent />
  14. optionalElement: PropTypes.element,
  15. // 你也可以声明一个 prop 是类的一个实例。
  16. // 使用 JS 的 instanceof 运算符。
  17. optionalMessage: PropTypes.instanceOf(Message),
  18. // 你可以声明 prop 是特定的值,类似于枚举
  19. optionalEnum: PropTypes.oneOf(['News', 'Photos']),
  20. // 一个对象可以是多种类型其中之一
  21. optionalUnion: PropTypes.oneOfType([
  22. PropTypes.string,
  23. PropTypes.number,
  24. PropTypes.instanceOf(Message)
  25. ]),
  26. // 一个某种类型的数组
  27. optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
  28. // 属性值为某种类型的对象
  29. optionalObjectOf: PropTypes.objectOf(PropTypes.number),
  30. // 一个特定形式的对象
  31. optionalObjectWithShape: PropTypes.shape({
  32. color: PropTypes.string,
  33. fontSize: PropTypes.number
  34. }),
  35. // 你可以使用 `isRequired' 链接上述任何一个,以确保在没有提供 prop 的情况下显示警告。
  36. requiredFunc: PropTypes.func.isRequired,
  37. // 任何数据类型的值
  38. requiredAny: PropTypes.any.isRequired,
  39. }

五、关于props和state

5-1 定义

  • Props 是组件的输入。它们是单个值或包含一组值的对象,由于React是单向数据流,所以props基本上也就是从父级组件向子组件传递的数据。
  • State是组件的状态,用于组件保存、控制以及修改自己的状态。状态State是私有的,完全由组件控制,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。

    5-2 区别

  1. state是组件自己管理数据,控制自己的状态,在组件内部可变;
  2. props是外部传入的数据参数,在组件内部不可变,如果要修改,需要在父组件中修改


六、条件渲染

6-1 通过if进行条件渲染

  1. function Greeting(props) {
  2. const isLoggedIn = props.isLoggedIn;
  3. if (isLoggedIn) {
  4. return <UserGreeting />;
  5. }
  6. return <GuestGreeting />;
  7. }
  8. ReactDOM.render(
  9. // Try changing to isLoggedIn={true}:
  10. <Greeting isLoggedIn={false} />,
  11. document.getElementById('root')
  12. );

6-2 三元运算符渲染

  1. render() {
  2. const isLoggedIn = this.state.isLoggedIn;
  3. return (
  4. <div>
  5. {isLoggedIn ? (
  6. <LogoutButton onClick={this.handleLogoutClick} />
  7. ) : (
  8. <LoginButton onClick={this.handleLoginClick} />
  9. )}
  10. </div>
  11. );
  12. }

6-3 通过&&进行条件渲染

  1. function Mailbox(props) {
  2. const unreadMessages = props.unreadMessages;
  3. return (
  4. <div>
  5. <h1>Hello!</h1>
  6. {unreadMessages.length > 0 &&
  7. <h2>
  8. You have {unreadMessages.length} unread messages.
  9. </h2>
  10. }
  11. </div>
  12. );
  13. }
  14. const messages = ['React', 'Re: React', 'Re:Re: React'];
  15. ReactDOM.render(
  16. <Mailbox unreadMessages={messages} />,
  17. document.getElementById('root')
  18. );

6-4 阻止渲染

在极少数情况下,你可能希望能隐藏组件,即使它已经被其他组件渲染。若要完成此操作,你可以让 render 方法直接返回 null,而不进行任何渲染。

  1. render() {
  2. const isLoggedIn = this.state.isLoggedIn;
  3. if (!isLoggedIn) {
  4. return null;
  5. }
  6. return (
  7. <div>
  8. <LoginButton onClick={this.handleLoginClick} />
  9. </div>
  10. );
  11. }

七、列表渲染

实例详见Http请求

  1. function NumberList(props) {
  2. const numbers = props.numbers;
  3. const listItems = numbers.map((number) =>
  4. <li key={number.toString()}>
  5. {number}
  6. </li>
  7. );
  8. return (
  9. <ul>{listItems}</ul>
  10. );
  11. }
  12. const numbers = [1, 2, 3, 4, 5];
  13. ReactDOM.render(
  14. <NumberList numbers={numbers} />,
  15. document.getElementById('root')
  16. );
  17. //key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
  18. //一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据 id 来作为元素的 key。key在兄弟节点之间必须唯一
  19. //当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key:
  20. const todoItems = todos.map((todo, index) =>
  21. // Only do this if items have no stable IDs
  22. <li key={index}>
  23. {todo.text}
  24. </li>
  25. );

八、Fragment

官方文档

  1. import React, { Fragment } from 'react';
  2. //子组件
  3. function ListItem({ item }) {
  4. return (
  5. <Fragment>
  6. <dt>{item.term}</dt>
  7. <dd>{item.description}</dd>
  8. </Fragment>
  9. );
  10. }
  11. //父组件
  12. function Glossary(props) {
  13. return (
  14. <dl>
  15. {props.items.map(item => (
  16. <ListItem item={item} key={item.id} />
  17. ))}
  18. </dl>
  19. );
  20. }

8-1 实例:

  1. class Table extends React.Component {
  2. render() {
  3. return (
  4. <table>
  5. <tr>
  6. <Columns />
  7. </tr>
  8. </table>
  9. );
  10. }
  11. }

<Columns /> 需要返回多个 <td> 元素以使渲染的 HTML 有效。如果在 <Columns />render() 中使用了父 div,则生成的 HTML 将无效。

  1. class Columns extends React.Component {
  2. render() {
  3. return (
  4. <div>
  5. <td>Hello</td>
  6. <td>World</td>
  7. </div>
  8. );
  9. }
  10. }

得到一个 <Table /> 输出:

  1. <table>
  2. <tr>
  3. <div>
  4. <td>Hello</td>
  5. <td>World</td>
  6. </div>
  7. </tr>
  8. </table>

8-2 用法:

  1. class Columns extends React.Component {
  2. render() {
  3. return (
  4. <React.Fragment>
  5. <td>Hello</td>
  6. <td>World</td>
  7. </React.Fragment>
  8. );
  9. }
  10. }

短语法:

你可以像使用任何其他元素一样使用 <> </>,除了它不支持 key 或属性。

  1. class Columns extends React.Component {
  2. render() {
  3. return (
  4. <>
  5. <td>Hello</td>
  6. <td>World</td>
  7. </>
  8. );
  9. }
  10. }

带 key 的 Fragments:

使用显式 <React.Fragment> 语法声明的片段可能具有 key。一个使用场景是将一个集合映射到一个 Fragments 数组 - 举个例子,创建一个描述列表:

  1. function Glossary(props) {
  2. return (
  3. <dl>
  4. {props.items.map(item => (
  5. // 没有`key`,React 会发出一个关键警告
  6. <React.Fragment key={item.id}>
  7. <dt>{item.term}</dt>
  8. <dd>{item.description}</dd>
  9. </React.Fragment>
  10. ))}
  11. </dl>
  12. );
  13. }

九、React组合

参考文档 官方文档
react组合类似于Vue中的slot(插槽),子组件的内容由父组件来指定

  1. function FancyBorder(props) {
  2. return (
  3. <div className={'FancyBorder FancyBorder-' + props.color}>
  4. {/*子组件:占坑*/}
  5. {props.children}
  6. </div>
  7. );
  8. }
  9. function WelcomeDialog() {
  10. return (
  11. <FancyBorder color="blue">
  12. {/*父组件中填坑*/}
  13. <h1 className="Dialog-title">
  14. Welcome
  15. </h1>
  16. <p className="Dialog-message">
  17. Thank you for visiting our spacecraft!
  18. </p>
  19. </FancyBorder>
  20. );
  21. }

少数情况下,你可能需要在一个组件中预留出几个“洞”。这种情况下,我们可以不使用 children,而是自行约定:将所需内容传入 props,并使用相应的 prop。

  1. function SplitPane(props) {
  2. return (
  3. <div className="SplitPane">
  4. <div className="SplitPane-left">
  5. {props.left}
  6. </div>
  7. <div className="SplitPane-right">
  8. {props.right}
  9. </div>
  10. </div>
  11. );
  12. }
  13. function App() {
  14. return (
  15. <SplitPane
  16. left={
  17. <Contacts />
  18. }
  19. right={
  20. <Chat />
  21. } />
  22. );
  23. }