react基础、StyledComponents

85 阅读4分钟

react

CRA 搭建 React 开发环境

  • 切换镜像 【可选】
切换安装镜像源,提高npx下载速度
npm config set registry https://registry.npmmirror.com/
配置后可通过下面方式来验证是否成功
npm config get registry

不成功可以:npm i nrm -g open@8.4.2 --save
  • nrm
    • npm i nrm -g 全局安装 nrm
    • nrm ls 查看镜像列表
    • nrm use 镜像名称
  • 初始化 react 项目 create-react-app
    • npx create-react-app [项目名称]
    • npm run start 启动项目

类组件形式

组件名称首字母必须大写

基本结构

import React, { Component } from 'react'
class ClassDemo extends React.Component{
  constructor(){  //构造函数
    super()
  }
  render(){

  }
}

函数的定义

普通函数定义方式

  • 使用的是普通函数,必须在 constructor 中通过 bind 修正 this 指向后才能使用
handleNum(){
  let {num} = this.state
  // num += 1
  this.setState({  //唯一引发类组件数据响应式变化的方法
    num:++num
  })
}

箭头函数定义方式,不传参

handleNum = ()=>{
  let {num} = this.state
  this.setState({  //唯一引发类组件数据响应式变化的方法
    num:++num
  })
}
<button onClick={this.handleNum}>按钮</button>

调用方法函数并传参

handleNum = (n=1,ev)=>{
  console.log(ev);
  let {num} = this.state
  num += n
  this.setState({  //唯一引发类组件数据响应式变化的方法
    num
  })
}

传参时这样写()=>{this.xxx(n)} 不然会死循环

<button onClick={(ev)=>{this.handleNum(10,ev)}}>按钮</button>

列表渲染

{
  this.state.joblist.map((item,index)=>{
    return <JobItem jobname={item.jobname} salary={item.salary}/>
  })
}

条件渲染

{
  isShow
  ?
  <input ref={this.myInput} type="text" />
  :
  ''
}

setState 方法的回调

setState 方法是异步的

this.setState({
  isShow:true
})
this.myInput.current.focus()   //此处的DOM操作,会因为setState的异步特点,导致执行失败

//解决方案
this.setState({
  isShow:true
},()=>{  //此处的回调函数,会等到isShow引发的DOM更新完成后,再执行
  this.myInput.current.focus()
})

StyledComponents

css写在js中

使用

  • npm i yarn -g 全局安装yarn
  • yarn add styled-components 安装依赖

安装 vscode 插件 vscode-styled-components

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: #BF4F74;
`;

render(
    <Title>
      Hello World!
    </Title>
);

生命周期

  • 挂载阶段
    • constructor
    • render
    • componentDidMount
  • 更新阶段 (props、state 的变化都会触发更新)
    • shouldComponentUpdate
    • render
    • componentDidUpdate
  • 销毁阶段
    • componentWillUnmount
  • PureComponent (表现形式跟 Component 有差异)

组件通信方法汇总

父子、子父通信

  • 父子通信
    • 父级传数据
    • 子级接收并使用
  • 子父通信
    • 父级传递函数
    • 子级接收函数
    • 子级触发父级提供的函数
    • 父级函数中得到子级提供的数据

兄弟通信(状态提升)

为兄弟组件增加一个共同的父组件,进而实现通信

import React, { Component } from "react";
import CompA from "./ComA";
import CompB from "./CompB";

export default class UpperDemo extends Component {
  constructor() {
    super();
    this.state = {
      //状态提升
      num: 111,
    };
  }
  handleNum = () => {
    let num = this.state.num + 1;
    this.setState({
      num,
    });
  };
  render() {
    return (
      <div>
        <CompA num={this.state.num} />
        <CompB handleNum={this.handleNum} />
      </div>
    );
  }
}

事件总线

文档

  • 定义总线对象
 //事件总线,发布订阅模式【设计模式】
import { EventEmitter } from "events";

let bus = new EventEmitter();

// 进行通信信号的接收
export const $on = (callback) => {
  bus.on("hello", callback); //callback是给用户接收信号后去触发的方法函数
};

// 进行通信信号的发送
export const $emit = (arg) => {
  bus.emit("hello", arg); //arg是发射信号时携带的参数
};
  • 在 C 组件中调用总线的信号监听方法
componentDidMount() {
    $on((arg) => {
      console.log("接收到了信号", arg);
      this.setState({
        msg: arg.msg,
      });
    });
  }
  • 在 D 组件中调用总线的信号发射方法
<button
  onClick={() => {
    $emit({
      msg: "0707,收到请回答",
    });
  }}
>
  发射信号
</button>

Context

理解上下文、作用及其特点

  • Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
  • Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。
  • Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。

使用

  • 创建上下文对象
import React, { Component } from "react";
// 1.创建上下文对象
const MyContext = React.createContext();

//如果浏览器安装过 react 的开发者工具,打开之后发现上述代码,都显示为 `Context.Provider` 和 `Context.Consumer`,不好区分加入 上下文对象的 `displayName`
ColorContext.displayName = "ColorContext"
  • 传值
class App extends Component {
  render() {
    return (
      <div>
        {/* 在需要传值的地方,通过 上下文 对象 的 Provider 组件以及value属性配合传递数据 */}
        <MyContext.Provider value="传家宝">
          <First />
        </MyContext.Provider>
      </div>
    );
  }
}
  • 后代获取数据
// 1. 如果后代组件是类组件 可以通过 类的静态属性 static contextType = 上下文对象 获取祖先组件的值,然后在jsx中 通过 this.context 取值即可
// class Third extends Component {
//   static contextType = MyContext
//   render () {
//     return (
//       <div>
//         <h3>third!!</h3>
//         <div>{ this.context }</div>
//       </div>
//     )
//   }
// }
// 2. 如果不使用 静态属性,那么可以 通过 上下文对象.Consumer 来获取数据(在其内部图片通过函数返回jsx代码,函数的默认参数就是祖先组件传递的值)
class Third extends Component {
  render() {
    return (
      <div>
        <h3>third!!</h3>
        <div>
          <MyContext.Consumer>
            {(value) => {
              return <mark>{value}</mark>;
            }}
          </MyContext.Consumer>
        </div>
      </div>
    );
  }
}