React17学习

命令

  • npx create-react-app my-app
  • npx create-react-app my-app --template typescript
  • npm start

jsx

React认为视图的本质就是渲染逻辑与UI视图表现的内在统一,React把HTML与渲染逻辑进行了耦合,形成了JSX。

JSX的特点

  • HTML代码可以与jsx兼容
  • 可以在jsx中镶如表达式
  • 使用jsx指定子元素
  • 小驼峰命名。class变成了className、tabindex变成tabIndex
  • jsx自定义属性,以 data- 开头

JSX 编译成对象

  • jsx会被编译成React.createElement() 对象
const element = (
    <h1 className="greeting">hello</h1>
);
const element = React.createElement(
    'h1',
    {className='greeting' },
    'hello'
);
// 这两种写法一样
// jsx 会被编译成React.createElement()对象
const element = { // 最后输出的对象
    type: 'h1',
    props: {
        className:'greeting',
        children:'hello'
    }
}

css in js

新建custom.d.ts 这种文件可以被ts直接识别。不被编译不备打包

// 声明 CSS 文件。讲过声明后才可以被TS识别
declare module "*.css" {
    const css: { [key: string]: string }
    export default css
}

import style from './index.css' <div className={style.app}></div>

npm install typescript-plugin-css-modules --save

加载媒体资源

新建assets文件夹。存储images、fonts、icons

class 组件

react组件必须继承React.Component ,这个组件接受一个泛型(Props,State,自定义数据)

class ShoppingCart extends React.Component<Props, State>{
   constructor(props: Props) { // 传递来的Props
   super(props); // 必须调用父类
   this.state = { // 初始化state
     isOpen: false,
    }
   }
   render() {
       return (
           // DOM 元素
       )
   }
}

行内样式

行内样式接受一个采用小驼峰命名属性的js对象,可以预防xss攻击

const divStyle = {
    color: 'blue'
}
// 在组件内使用时
return ( <div style={divStyle}></div> )

State和Props的区别

  • props是组件对外的接口,而state是组件对内部的接口
  • props用于组件间数据传递,而state用于组件内部的数据传递

用setState()修改State

this.setState({isOpen:false})

构建函数constructor是唯一可以初始化state的地方

constructor(props) {
    super(props)
    this.state = {
        count: 0
    }
}
  • 调用setState后,state不会立即改变,是异步操作
  • 不要依赖当前的state,计算下一个state
  • state处理一般发生在声明周期变化的时候。(生命周期不变,state就是开始那个值)
<button onClick = {
        this.setState((preState, preProps) => {
            return {count: this.preState.count++}
        }, ()=>{})
    }>
</button>

Props

本质上,props就是传入函数的参数,是从外部传入组件内部的数据。就是父组件传递到子组件的数据。

props是只读属性

事件处理

handleClick = (e) => {
    e.tatget // 描述的是时间发生的元素
    e.currentTarger // 描述的是时间处理绑定的元素
}

react中的icon

npm install react-icons

<FcAddressBook />组件方式使用

React生命周期

  • Mounting:创建虚拟DOM,渲染UI

  • Updating:更新虚拟DOM,重新渲染UI

  • Unmounting:删除虚拟DOM,移除UI

  shouldComponentUpdate(nextProps, nextState) {
     return (nextState.some! = this.state.some);
  }
  componentDidUpdate() {}
  componentWillUnmount() {}

hooks(钩子)

一类特殊的函数,为你的函数型式组件注入特殊功能
Hooks的目的就是为了给函数式组件加上状态

  • 消息处理的一种方法,用来监视指定程序
  • 函数组件中需要处理副作用,可以用钩子把外部代码“沟进来”
  • 常用钩子:useState、useEffect、useContext、useReducer
    Hooks代表了React结构的一次重大变革。我们不再需要类组件了,不会再有this、binding、甚至可能取代redux,简化了代码、减少了模板、降低了学习难度

常用钩子

副作用

纯函数(pure function):给一个函数同样的参数,那么这个函数永远返回同样的。React组件接受相同的参数(props),渲染的UI应该永远一样。

副作用与纯函数相反:指一个函数处理了与返回值无关的事情。

useState()

import React, { useState } from "react";
const App:React.FC = (props) => {
    const [count, setCount] = useState<number>(0)
    return (
        {count}
        <button onClick={ () => {setCount(count+1)} }></button>
    )
}

useEffect()

第二个参数不可为空,为空会死循环

import React, { useState, useEffect } from 'react'
const App: React.FC = (props) => {
    const [robotGallery, setRobotGallery] = useState<any>([])
    useEffect(() => {}) // 一直循环。
    useEffect(() => {}, []) // 空数组表示模拟componentDidMount() {}
    useEffect(() => {}, [count]) // 当count改变时触发函数
}

useEffect使用async

useEffect(() => {
    const fetchData = async () => {
        try {
        const response = await fetch("url")
        const data = await response.json()
        } catch (e) {
            error = e.message
        }
    }
    fetchData()
}, [])

**三元表达式 **

{ !loading ? (
    // 显示代码
) : (
    <h2>loading...加载中</h2>
)
}

二元表达式

{/* 错误处理 error不为空,为假就显示div*/}
{(!error || error !== '') && <div>{error}</div>}

全局数据传递 - AppState.tsx

  • Context
  • useContext()

在父组件index.tsx

const defaultContextValue = {
  username: "rain"
}
export const appContext = React.createContext(defaultContextValue)
ReactDOM.render(
  <React.StrictMode>
    <appContext.Provider value={defaultContextValue}>
      <App /> App是父组件
    </appContext.Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

子组件Robot.tsx(函数组件)

import React, { useContext } from 'react';
const value = useContext(appContext) // 使用useContext() 取值
<p>作者:{value.username}</p>

子组件Robot.tsx(类组件)

render() {
    return (
    <appContext.Consumer>
            {(value) => {
                return <div>{value.usename}</div>
            }}
    </appContext.Consumer>
    )
}

自定义高阶组件HOC

const hoc = higherOrde(wrappedComponent)

高阶组件(HOC)就是返回了组件的函数,通过组件嵌套的方法给子组件添加更多的功能。

  • 抽取重复代码,实现组件复用
  • 条件渲染,控制组件的渲染逻辑
  • 捕获/劫持被处理组件的生命周期
import React, { useContext } from 'react'
import { appSetStateContext } from '../AppState'
/**
 *  AddToCart.tsx 
 *  高阶组件HOC以 with开头 返回一个组件
 *  改造了 Robot.tsx RobotDiscount.tsx
 */
import { RobotProps } from './Robot'
export const withAddToCart = (ChildComponent: React.ComponentType<RobotProps>) => {
  // return class extends React.Component {}
  // return ()=>{}
  return (props) => {
    const setState = useContext(appSetStateContext)
    const addToCart = (id, name) => {
      if (setState) {
        setState((state) => {
          console.log(state)
          return {
            ...state,
            shoppingCart: {
              items: [...state.shoppingCart.items, { id, name }],
            },
          }
        })
      }
    }
    return <ChildComponent {...props} addToCart={addToCart} />
  }
}

自定义Hook

use 开头。是函数。并非React特性。内部可调用替他Hook

export const useAddToCart = () => {
  const setState = useContext(appSetStateContext)
  const addToCart = (id, name) => {
    if (setState) {
      setState((state) => {
        console.log(state)
        return {
          ...state,
          shoppingCart: {
            items: [...state.shoppingCart.items, { id, name }],
          },
        }
      })
    }
  }
  return addToCart
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值