react笔记

1、JSX

1.1、JSX中使用js表达式
  • 1)、语法

    • {js表达式}

    • const name = 'zll'
      
      function App() {
        return (
          <div className="App">
            react-{name}
          </div>
        );
      }
      
      export default App;
      
      // 效果: <div class="App">react-zll</div>
      
      
  • 2)、可以使用的表达式

    • 字符串、数值、布尔值、null、undefined、object( [] / {} )
    • 1 + 2、‘abc’.split(‘’)、[‘a’, ‘b’].join(‘-’)
    • fn()
  • 3)、特别注意

    • if 语句/ switch-case 语句/ 变量声明语句,这些叫做语句,不是表达式,不能出现在 {} 中!!
1.2、JSX列表渲染
  • 1)、语法

    • 使用map方法

    • const songs = [
        { id: 1, name: '痴心绝对' },
        { id: 2, name: '像我这样的人' },
        { id: 3, name: '南山南' }
      ]
      
      function App() {
        return (
          <div className="App">
            { songs.map(i => <div key={i.id}>{i.name}</div>) }
          </div>
        );
      }
      
      //   效果 <div class="App">
      //					<div>痴心绝对</div>
      //					<div>像我这样的人</div>
      //					<div>南山南</div>
      //				</div>
      
    • 注意:需要为遍历项添加 key 属性

1.3、JSX条件渲染
  • 1)、语法

    • 使用 三元表达式逻辑运算符

    • const flag = false
      
      function App() {
        return (
          <div className="App">
            <h5>三元</h5>
            {flag?<div>zll</div>:<div>cjy</div>}
            <h5>&&</h5>
            {flag && <div>zll</div>}
            <h5>||</h5>
            {flag || <div>cjy</div>}
          </div>
        );
      }
      
      // 效果
      // <div class="App">
      //   <h5>三元</h5>
      //   <div>cjy</div>
      //   <h5>&amp;&amp;</h5>
      //   <h5>||</h5>
      //   <div>cjy</div>
      // </div>
      
1.4、JSX样式处理
  • 1)、语法

    • 行内样式

    • const styleObj = {
        color:'red',
        fontSize:'32px'
      }
      
      function App() {
        return (
          <div className="App">
            <div style={ styleObj }>cjy</div>
          </div>
        );
      }
      
    • 类名

    • <div style={ styleObj } className='cjy_div'>cjy</div>
      
    • <div style={ styleObj } className={ getClassName() }>cjy</div>
      
1.5、JSX注意事项
  • JSX必须有一个根节点,如果没有根节点,可以使用<></>(幽灵节点)替代

  • 所有标签必须形成闭合,成对闭合或者自闭合都可以

  • JSX中的语法更加贴近JS语法,属性名采用驼峰命名法 class -> className for -> htmlFor

  • JSX支持多行(换行),如果需要换行,需使用() 包裹,防止bug出现

2、react组件基础

2.1、函数组件
  • 使用 JS 的函数(或箭头函数)创建的组件,就叫做函数组件
2.1.1、语法demo
// 定义函数组件
function HelloFn () {
  return <div>这是我的第一个函数组件!</div>
}

// 定义类组件
function App () {
  return (
    <div className="App">
      {/* 渲染函数组件 */}
      <HelloFn />
      <HelloFn></HelloFn>
    </div>
  )
}
export default App
  • 约定说明
    • 组件的名称必须首字母大写,react内部会根据这个来判断是组件还是普通的HTML标签
    • 函数组件必须有返回值,表示该组件的 UI 结构;如果不需要渲染任何内容,则返回 null
    • 组件就像 HTML 标签一样可以被渲染到页面中。组件表示的是一段结构内容,对于函数组件来说,渲染的内容是函数的返回值就是对应的内容
    • 使用函数名称作为组件标签名称,可以成对出现也可以自闭合
2.1.2、事件绑定
  • 1)、 如何绑定事件

    • on + 事件名称 = { 事件处理程序 } ,比如:<div onClick={ onClick }></div>

    • 注意点:react事件采用驼峰命名法,比如:onMouseEnter、onFocus

    • demo

      // 函数组件
      const HelloFn = () => {
        const sayHello = (e,str) => {
          console.log('hello',str)
          console.log('事件对象', e)
        }
        return (
          <button onClick={(e)=>sayHello(e, 'cjy')}>say hello</button>
        )
      }
      
      function App() {
        return (
          <div className="App">
            <HelloFn></HelloFn>
          </div>
        );
      }
      
      export default App;
      
2.2、类组件
  • 使用 ES6 的 class 创建的组件,叫做类(class)组件
2.2.1、语法demo
// 引入React
import React from 'react'

// 定义类组件
class HelloC extends React.Component {
  render () {
    return <div>这是我的第一个类组件!</div>
  }
}

function App () {
  return (
    <div className="App">
      {/* 渲染类组件 */}
      <HelloC />
      <HelloC></HelloC>
    </div>
  )
}
export default App
  • 约定说明

    • 类名称也必须以大写字母开头
    • 类组件应该继承 React.Component 父类,从而使用父类中提供的方法或属性
    • 类组件必须提供 render 方法render 方法必须有返回值,表示该组件的 UI 结构
2.2.2、事件绑定
  • 函数组件绑定方式一致

  • demo

    // 类组件
    class HiFn extends React.Component {
      sayHi = (e,str) => {
        console.log('hi',str)
        console.log('事件对象', e)
      }
      render(){
        return (
          <button onClick={(e)=>this.sayHi(e,'cjy')}>say hi</button>
        )
      }
    }
    function App() {
      return (
        <div className="App">
          <HiFn/>
        </div>
      );
    }
    
    export default App;
    
    
  • 类组件中,访问this为undefined

    class HiFn extends React.Component {
      hClick(){
        console.log('hClick',this) // undefined
      }
      render(){
        return (
          <>
            <button onClick={this.hClick}>this</button>
          </>
        )
      }
    }
    function App() {
      return (
        <div className="App">
          <HiFn/>
        </div>
      );
    }
    
    export default App;
    
    • 为啥是undefined?
      • 1、this隐式丢失,使用默认绑定(全局对象)
      • 2、严格模式,禁止this关键字指向全局对象。会用undefined代替。
    • this修正方案
      • 方案一:显示绑定
      • 方案二:剪头函数(this指向创建时的上下文)
    • 更多关于this

3、组件状态

在React hook出来之前,函数式组件是没有自己的状态的。

3.1、读取状态
  • 通过class的实例属性state来初始化

  • state的值是一个对象结构,表示一个组件可以有多个数据状态

  • 通过this.state来获取状态

    // 引入React
    import React from 'react'
    
    class InitState extends React.Component {
      state = {
        count: 0
      }
      render(){
        return <div>01、组件状态 {this.state.count} </div>
      }
    }
    export default InitState
    
3.2、修改状态
  • 语法
    this.setState({ 要修改的部分数据 })
  • setState方法作用
    1. 修改state中的数据状态
    2. 更新UI
  • 注意事项
    不要直接修改state中的值,必须通过setState方法进行修改

    // 引入React
    import React from 'react'
    const styleObj = {
      marginLeft:'20px'
    }
    class ChangeState extends React.Component {
      state = {
        count: 0,
        name:'cjy'
      }
      change = () => {
        this.setState({
          count: this.state.count + 1
        })
      }
      render(){
        return <div>
            02、组件状态 {this.state.count} {this.state.name}
            <button style={styleObj}  onClick={this.change}>修改状态</button>
          </div>
      }
    }
    export default ChangeState
    
3.3、状态不可变

不要直接修改状态,而时使用setState方法修改状态

直接修改,虽然有时会生效,但是许多情况会直接报错,而且严格的状态管理会避免很多莫名其妙的bug。

3.4、表单处理

受控组件和非受控组件

3.4.1、受控组件

什么是受控组件? input框自己的状态被React组件状态控制

React组件的状态的地方是在state中,input表单元素也有自己的状态是在value中,React将state与表单元素的值(value)绑定到一起,由state的值来控制表单元素的值,从而保证单一数据源特性

  • 实现步骤

    以获取文本框的值为例,受控组件的使用步骤如下:

    1. 在组件的state中声明一个组件的状态数据
    2. 将状态数据设置为input标签元素的value属性的值
    3. 为input添加change事件,在事件处理程序中,通过事件对象e获取到当前文本框的值(即用户当前输入的值
    4. 调用setState方法,将文本框的值作为state状态的最新值
  • 代码

    // 引入React
    import React from 'react'
    const styleObj = {
      marginLeft:'20px'
    }
    class ControlledComponent extends React.Component {
      state = {
        name:'cjy'
      }
      change = (e) => {
        this.setState({
          name: e.target.value
        })
      }
      render(){
        return (<div>
                  03、受控组件 
                  <input style={styleObj} value={this.state.name} onChange={this.change} />
                  <span  style={styleObj} >{this.state.name}</span>
                </div>)
      }
    }
    export default ControlledComponent
    
3.4.2、非受控组件

什么是非受控组件?

非受控组件就是通过手动操作dom的方式获取文本框的值,文本框的状态不受react组件的state中的状态控制,直接通过原生dom获取输入框的值

  • 实现步骤

    1. 导入createRef 函数
    2. 调用createRef函数,创建一个ref对象,存储到名为iptRef的实例属性中
    3. 为input添加ref属性,值为iptRef
    4. 在按钮的事件处理程序中,通过iptRef.current即可拿到input对应的dom元素,而其中iptRef.current.value拿到的就是文本框的值的值
  • 代码

    // 引入React
    import React, { createRef } from 'react'
    const styleObj = {
      marginLeft:'20px'
    }
    class UnControlledComponent extends React.Component {
      iptRef = createRef()
      state = {
        iptv:''
      }
      change = () => {
        this.setState({
          iptv: this.iptRef.current.value
        })
      }
      render(){
        return (<div>
                  04、非受控组件 
                  <span  style={styleObj} >{this.state.iptv}</span>
                  <input style={styleObj} ref={this.iptRef} />
                  <button  style={styleObj} onClick={this.change}>click</button>
                </div>)
      }
    }
    export default UnControlledComponent
    

4、组件通信

4.1、父传子
  • 实现步骤

    1. 给子组件标签添加属性值为 state中的数据
    2. 子组件中通过 props 接收父组件中传过来的数据
      1. 类组件使用this.props获取props对象
      2. 函数式组件直接通过参数获取props对象
  • props注意

    1. props是只读对象(readonly)

    根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改

    2. props可以传递任意数据

    数字、字符串、布尔值、数组、对象、函数、JSX

  • 代码

    import React from 'react'
    
    const faStyle = {
      background:'#f00'
    }
    const sonStyle = {
      background:'#0f0',
      flex:'1'
    }
    const fSonStyle = {
      background:'#00f',
      flex:'1'
    }
    const flexStyle = {
      display:'flex'
    }
    
    // 类组件使用this.props获取props对象
    class CSon extends React.Component {
      render(){
        return (
          <div style={sonStyle}>
            <p>I m CSon</p>
            <p>{this.props.msg}</p>
          </div>
        )
      }
    }
    
    // 函数式组件直接通过参数获取props对象
    const FSon = (props) => {
      return (
        <div style={fSonStyle}>
          <p>I m FSon</p>
            <p>{props.msg}</p>
        </div>
      )
    }
    
    class FatherSon extends React.Component {
      render(){
        return (
          <>
          <p>01、父传子</p>
          <div style={faStyle}>
            <p>I m father</p>
            <div style={flexStyle}>
              <CSon msg="hello!"></CSon>
              <FSon msg={"hi!"}></FSon>
            </div>
          </div>
          </>
        )
      }
    }
    
    export default FatherSon
    
4.2、子传父
  • 实现步骤

    • 父组件提供一个回调函数 - 用于接收数据
    • 将函数作为属性的值,传给子组件
    • 子组件通过props调用 回调函数
    • 将子组件中的数据作为参数传递给回调函数
  • 代码

    import React from 'react'
    
    const faStyle = {
      background:'#f00'
    }
    const sonStyle = {
      background:'#0f0',
      flex:'1'
    }
    const fSonStyle = {
      background:'#00f',
      flex:'1'
    }
    const flexStyle = {
      display:'flex'
    }
    
    // 类组件使用this.props获取props对象
    class CSon extends React.Component {
      say = ()=>{
        this.props.cb('hello,FSon!')
      }
      render(){
        return (
          <div style={sonStyle}>
            <p>I m CSon</p>
            <button onClick={this.say}>say</button>
          </div>
        )
      }
    }
    
    // 函数式组件直接通过参数获取props对象
    const FSon = (props) => {
      console.log(props)
      const say = () => {
        props.cb('hi,CSon!')
      }
      return (
        <div style={fSonStyle}>
          <p>I m FSon</p>
          <button onClick={say}>say</button>
        </div>
      )
    }
    
    class FatherSon extends React.Component {
      state = {
        msg:"hello world!"
      }
      cb = (msg) => {
        this.setState({
          msg
        })
      }
      render(){
        return (
          <>
            <p>02、子传父</p>
            <div style={faStyle}>
              <p>I m father</p>
              <p>{this.state.msg}</p>
              <div style={flexStyle}>
                <CSon cb={this.cb}></CSon>
                <FSon cb={this.cb}></FSon>
              </div>
            </div>
          </>
        )
      }
    }
    
    export default FatherSon
    
4.3、兄弟组件通信
  • 实现过程

    • 子传父
    • 父传子
  • 代码

    import React from 'react'
    
    const faStyle = {
      background:'#f00'
    }
    const sonStyle = {
      background:'#0f0',
      flex:'1'
    }
    const fSonStyle = {
      background:'#00f',
      flex:'1'
    }
    const flexStyle = {
      display:'flex'
    }
    
    // 类组件使用this.props获取props对象
    class CSon extends React.Component {
      say = ()=>{
        this.props.cb('CSon')
      }
      render(){
        return (
          <div style={sonStyle}>
            <p>I m CSon</p>
            <button onClick={this.say}>say</button>
          </div>
        )
      }
    }
    
    // 函数式组件直接通过参数获取props对象
    const FSon = (props) => {
      return (
        <div style={fSonStyle}>
          <p>I m FSon</p>
          <p>hello {props.name}</p>
        </div>
      )
    }
    
    class FatherSon extends React.Component {
      state = {
        name:"father"
      }
      cb = (name) => {
        this.setState({
          name
        })
      }
      render(){
        return (
          <>
            <p>03、兄弟通信</p>
            <div style={faStyle}>
              <p>I m father</p>
              <p>{this.state.msg}</p>
              <div style={flexStyle}>
                <CSon cb={this.cb}></CSon>
                <FSon name={this.state.name}></FSon>
              </div>
            </div>
          </>
        )
      }
    }
    
    export default FatherSon
    
4.4、跨级通信
  • 实现过程,使用 context

  • 代码

    • 04-grandfater-grandson.jsx

      import React from 'react'
      import CGrandSon from './04-cGrandSon'
      import FGrandSon from './04-fGrandSon'
      export const CContext = React.createContext('cConsumer666')
      export const FContext = React.createContext('fConsumer666')
      const flexStyle = {
        display:'flex',
        background:'#f00'
      }
      const Father = () => {
        return (
          <div style={flexStyle}>
            <CGrandSon />
            <FGrandSon />
          </div>
        )
      }
      
      export default class GrandFatherGrandSon extends React.Component {
        render(){
          return (
            <>
              <p>04、跨级通信</p>
              {/* <CContext.Provider value={'cConsumer'}> */}
                <FContext.Provider value={'cConsumer'} >
                    <Father></Father>
                </FContext.Provider>
              {/* </CContext.Provider> */}
            </>
          )
        }
      }
      
    • 04-cGrandSon.jsx

      import React from 'react'
      import { CContext } from './04-grandfater-grandson'
      const style = {
        background:'#0f0',
        flex:'1'
      }
      export default class CGrandSon extends React.Component {
        render(){
          return (
            <CContext.Consumer>
              {value => (
                <div style={style}>I am {value}</div>
              )}
            </CContext.Consumer>
          )
        }
      }
      
    • 04-fGrandSon.jsx

      import { FContext } from './04-grandfater-grandson'
      const style = {
        background:'#00f',
        flex:'1'
      }
      const FGrandSon = () => {
        return (
          <FContext.Consumer>
            {value => (
              <div style={style}>I am {value}</div>
            )}
          </FContext.Consumer>
        )
      }
      
      export default FGrandSon
      

5、组件进阶

5.1、children属性
  • children属性是什么
    • 每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容。
  • children属性可以是什么
    • 普通文本
    • 普通标签元素
    • 函数 / 对象
    • JSX
5.1.1、children的使用
  • 代码

    • 01-children.jsx
    const style = {
      width:'400px',
      height:'400px',
      backgroundColor:'#ccc'
    }
    const headrStyle = {
      width:'100%',
      height:'100px',
      backgroundColor:'#cc0'
    }
    const contentStyle = {
      width:'100%',
      height:'200px',
    }
    const footerStyle = {
      width:'100%',
      height:'100px',
      backgroundColor:'#0cc'
    }
    export default function UseChildren (props) {
      return (
        <div style={style}>
          <div style={headrStyle}>
            {props.children.header?.() || '标题内容'}
          </div>
          <div  style={contentStyle} >
            {props.children.default?.({name:'default-content'}) || '正文内容'}
          </div>
          <div  style={footerStyle} >
            {props.children.footer?.() || '底部内容'}
          </div>
        </div>
      )
    }
    
    • App.js
     	<h3>children属性</h3>
      <UseChildren>
        {{
          // header(){
          //   return '我是标题内容'
          // },
          default(scope){
            return (
              <>
                <p>我是默认内容</p>
                <p>{scope.name}</p>
              </>
            )
          },
          footer(){
            return '我是底部内容'
          },
        }}
      </UseChildren>
    
  • 和vue中插槽效果一样样的。vue中jsx插槽语法差不多就这样。

5.2 、props校验
  • 语法

    • 安装依赖 prop-types
    • import PropTypes from 'prop-types'
    • 使用 组件名.propTypes = {} 给组件添加校验规则
  • 校验规则

    • https://reactjs.org/docs/typechecking-with-proptypes.html
  • 代码 01-propTypes.jsx

    import React, { useState } from 'react';
    import PropTypes from 'prop-types'
    
    // 类组件
    class Ccomponent extends React.Component {
      render(){
        return (
          <>
            类组件-{this.props.name}
          </>
        )
      }
    }
    Ccomponent.propTypes = {
      name: PropTypes.string
    };
    
    // 函数组件
    const Fcomponents = (props) => {
      return (
        <>
          函数组件-{props.name}
        </>
      )
    }
    Fcomponents.propTypes = {
      name: PropTypes.string.isRequired
    };
    
    const UsePropTypes = () => {
      const [name, setName] = useState('cjy');
      const [name1, setName1] = useState('');
      const set = (e) => {
        setName(666)
        setName1(777)
      }
      return (
        <>
          <p>01、props校验</p>
          <div>
            <button onClick={(e)=>set(e)}>change</button>
          </div>
          <Ccomponent name={name}></Ccomponent>
          <Fcomponents name={name1}></Fcomponents>
        </>
      )
    }
    
    export default UsePropTypes
    
5.3、props默认值
  • 语法 https://reactjs.org/docs/typechecking-with-proptypes.html

  • 代码 02-propDefaultValue.jsx

    import React, { useState } from 'react';
    import PropTypes from 'prop-types'
    
    // 类组件
    class Ccomponent extends React.Component {
      static defaultProps = {
        name: 'cjy'
      }
      render(){
        return (
          <>
            类组件-{this.props.name}
          </>
        )
      }
    }
    Ccomponent.propTypes = {
      name: PropTypes.string
    };
    
    // 函数组件
    const Fcomponents = ({name = 'cjy'}) => {
      return (
        <>
          函数组件-{name}
        </>
      )
    }
    Fcomponents.propTypes = {
      name: PropTypes.string
    };
    
    const UsePropDefaultValue = () => {
      const [name, setName] = useState('');
      const [name1, setName1] = useState('');
      const set = (e) => {
        setName('666')
        setName1('777')
      }
      return (
        <>
          <p>02、props默认值</p>
          <div>
            <button onClick={(e)=>set(e)}>change</button>
          </div>
          <Ccomponent ></Ccomponent>
          <Fcomponents ></Fcomponents>
        </>
      )
    }
    
    export default UsePropDefaultValue
    

6、生命周期

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

参考链接:https://www.yuque.com/fechaichai/qeamqf/xbai87#80c6b3c5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值