react全家桶

react全家桶

体验 React

React 从诞生之初就是可被逐步采用的,因而你可以按需引入或多或少的 React 特性。不管你是想体验下 React,用它给简单的 HTML 页面增加一点交互,还是要开始一个完全由 React 驱动的复杂应用,该章节内容里的链接都能帮你快速开始。

在线体验

如果你对体验 React 感兴趣,可以尝试在线代码编辑器。从 CodePen,CodeSandbox,Glitch, 或者 Stackblitz 开始一个 React 版本的 Hello World 模版。

如果你喜欢使用自己的文本编辑器,也可以下载这个 HTML 文件,然后编辑文件内容,最后再用浏览器从本地文件系统打开文件,预览页面效果。注意:这个文件中包含一个低效率的运行时代码转换脚本,所以我们推荐仅在简单的演示项目中使用。

在网站中添加 React

你可以立即在 HTML 文件中添加 React,然后选择逐渐拓展它的应用范围,或只在一些动态小部件中使用它。

创建新的 React 应用

当你刚开始一个 React 应用时,通过 HTML 的 script 标签引入 React 依然是最好的选项,因为这能让你的项目立即启动。

但随着应用越来越大,你可能会需要更加集成化的安装方式。我们推荐了一些 JavaScript 工具链,它们适合大型应用。它们只需很少甚至零配置,就能让你充分利用丰富的 React 生态。立即尝试。

JSX语法糖

官方提示: React 不强制要求使用 JSX,但是大多数人发现,在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用。它还可以使 React 显示更多有用的错误和警告消息。

  1. 使用js表达式需要加括号{}: 表达式是一个值

    const name = 'Josh Perez';
    const element = 

    Hello, {name}

    ; ReactDOM.render( element, document.getElementById('root') ); //等效的两种写法 const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' ); const element = (

    Hello, world!

    ); //React.createElement() 会预先执行一些检查,以帮助你编写无错代码,但实际上它创建了一个这样的对象: // 注意:这是简化过的结构 const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world!' } };
  2. 属性使用

    内联样式使用style={{key:value}}形式,如果原生css属性中有-,则属性第二个字符大写如font-size需要改为fontSize

//class <-> className
//style=“color:red;front-size:20px” <-> style={{color:‘red’ fontSize:‘20px’}}


3. jsx中渲染: 最外层只有一个根标签

```react
const element = (
  

Hello!

Good to see you here.

);
  1. 标签

    //标签必须关闭否则报错
    
    //不要使用自定义标签,除非你想使用组件,且组件名首字母需要大写
    //react识别标签如果是小写字母开头则将其转为html标签如果没有与之对应的标签则报错
    
    //首字母大写则是组件,如果没有该组件则报错
    
    
  2. 循环

    const element = (
      
      { //item中需要有id属性赋予key唯一值 data.map(item,index)=>{ return
    • {item}
    • } }
    );

react开发工具

官方调试工具: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi

组件

函数组件

//安装react插件React-Native/React/Redux snippets for es6/es7  代码片段 在vscode里快捷创建函数组件输入 rfc回车
function Demo () {
    this;//babel编译会开启严格模式this指向undefined,在js中指向的是Window
    return 

demo

} ReactDOM.render(,document.getElementById('demo'))

类式组件

//代码片段 在vscode里快捷创建类式组件 rcc回车
//必须继承react内置类 类名大写
class Person extends React.Component{
    name
	age
    //需要初始化
	constructor(name,age){
        //this指向实例对象
        this.name = name
        this.age=age
    }
    render(){
        //必须有render方法,且必须有返回值
        return 

honshen

} } //调用了new Person得到实例对象,且调用render方法,方法中的this指向其实例对象 ReactDOM.render(,document.getElementById('demo'))

组件三大属性

state

constructor (prpos){
    this.state = {} //初始化state
    this.setState() //更新状态
    this.state.name //读取name
}

props



class B extends Components{
    //读取属性
    this.props
}

ref

//ref类似于getElementById
class B extends Components{
    func = () => {
      const  {scanIn} = this.refs
      scanIn.value //输入框的值
       this.input.value //获取输入的值
    }
    render(
    
    {this.input = input}} /> //推荐
    )
}

高阶函数–柯里化函数

//不使用柯里化函数
function func(event,data) {
    //函数体
}
{this.func(event,data)}}
 //柯里化函数
 function func (data){
    return (event)=>{
        //函数体
    }
}

React脚手架

//全局安装
npm i -g create-react-app
//创建应用
create-react-app my-app

webpack配置文件都已隐藏通过: yaen eject暴露webpack.config.js

脚手架配置代理

//建议使用axios请求库
//使用json-server配合调试 axios github地址: https://github.com/typicode/json-server
npm i -g json-server
//在项目文件夹下创建db.json
//在db.json目录监视监视json
json-server --watch db.json
//axios github地址: https://github.com/axios/axios
npm i axios --save
//get请求
axios({
	//请求类型 GET POST PUT DELETE
	method: "GET",
	//请求地址
	url: ""
	//请求体
	data:{
	
	}
}).then((res)=>{
	//回调
})
//方法1: 在package.json中配置
  "proxy": "http://localhost:5000"
//方法二: 新建setupProxy.js文件
const proxy = require('http-proxy-middleware');
module.exports = function(app){
app.use(
proxy('请求路径',{
	target: '目标地址',
	changeOrigin: true, //修改请求源host
	pathRewrite: {'^请求路径':''}
})
),
proxy('请求路径',{
	target: '目标地址',
	changeOrigin: true, //修改请求源host
	pathRewrite: {'^请求路径':''}
})
)
}

组件通信

父子组件通信

//父组件直接传递数据给子组件

//子组件接收数据
const {data} = this.props

状态提升

//子组件将state提升到父组件里
//子组件修改父组件的数据
change(){}

消息订阅与发布

订阅消息:

1. 消息名
2. 消息发布
//使用库 PubSubJs
npm i pubsub-js --save
//在componentDidMount(){}中订阅消息
PubSub.subscribe('消息名',(_,data)=>{
    //处理
})

Redux状态管理js

集中管理组件中多个共享的状态

谷歌浏览器插件: redux-dev-tools

npm i redux-devtools-extension --save
//修改store.js
import {composeWithDevTools} from 'redux-devtools-extension'
import {createStore,combineReducers,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
const allReducer = combineReducers({
    //对象
})
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KX7REb6I-1619771333081)(https://images-1300732204.cos.ap-chengdu.myqcloud.com/MarkDown/Snipaste_2021-04-01_21-04-56.png.png)]

三个原则:
1.单一数据源

​ 2.State 是只读的

​ 3.使用纯函数来执行修改

// 1.如何得到此对象?
import {createStore} from 'redux"; 
import reducer from './reducers'
const store = createStore(reducer)
// 2.此对象的功能?”
getState() //得到state
dispatch(action) // 分发action,触发reducer调用,产生新的 state
subscribe(listener) //注册监听,当产生了新的state时,自动调用

redux使用引用类型进行的是浅比较例如数组返回不能这样reture arr.unshift(data)这样返回的是arr的地址和原来的值一样redux不会更新状态,可以使用return [data,...arr]

redux必须使用纯函数:同一个输入只有同一个输出

组件通信 Context

适用于组组件与后代组件通信

//在组组件中创建上下文对象Con是一个容器对象
const Con = React.createContext()
const {Provider} = Con
const {Consumer} = Con
//子组件被上下文包裹

       //在son的内部组价都能收到data但必须声明使用,通过后代组件的this.context


//在son组件内部想要使用context的组件需要声明使用=类式组件
static contextType = Con
this.context; //获取context对象

//也可以使用这样的方式在需要使用数据的地方--函数组件

    {
        value => {
            //函数
            //返回一个组件
        }
    }

SPA和React路由

SPA: 单页面应用,点击页面不会刷新只会做局部更新

react路由

import 'react-router-dom';




	//默认是push,点击后向栈顶加入,当使用 时不能回退历史记录


{//注册路由,模糊匹配}

{//严格匹配,不能随便开}

    

{//路由组件会默认收到一些props, this.props查看一下
//如果多个路由的path一致则同时展示两个组件,但这种不好,建议合并两个为一个组件
//路由较多时使用
/*react样式丢失问题: 当在多级路由路径下刷新时,index.html中引入的css样式会请求相应css但路由所在路径刷新导致请求失败react会返回index.html的内容所以css请求返回的是index.html
    解决方法: 1. 引入css使用根路径
    		2. 使用%PUBLIC_URL%作为样式的路径,推荐
    		3. 使用HashRouter
*/}
 //当模糊匹配失败时

    

react嵌套路由

//例如请求 /home/me 先匹配/home 当/home/me是Home组件

//组件1中

    
     //匹配成功
     //写在所有路由的最下方


//app中

    
     //匹配成功
     //写在所有路由的最下方

路由传参

//1. 路径传参params 路由占位符 :
 //传参
 //在注册路由时声明接收参数this.props.match.params中能够拿到id和info

//2. 传递search参数
 //传参
 //无需申明接收参数,this.props.location.search中得到?id=12&info=12需要对search参数编码
//需要引入库 querystring
import qs from 'querystring'
qs.stringify(obj); //将对象转换为字符串
qs.parse(str); //将字符串转换为对象 qs.parse(this.props.location.search.slice(1))去除?号

//3. 传递state参数,这里的state不是组件的state,而是路由的参数,前两种参数传递会在地址栏显示但state传参不会

 //无需申明接收参数在组件的this.props.location.state中,此种情况下state的参数由BrowserRouter维护,刷新页面不会丢失值,当清空浏览器的历史记录时会丢失

编程式路由导航

//路由组件中的导航函数
replace () {
 this.props.history.replace('/idnex')  //不能返回
 //携带state参数
 this.props.history.replace('/index',{id: 2,title: 1})
 //前进
    this.props.history.goForward(); //前进
    this.props.history.goBack(); //后退
}
push (){
 this.props.history.push('/idnex')  //可返回 
}

//一般组件导航
import {withRouter} from 'react-router-dom
class Header extends Component {
    
}
export default withRouter(Header) //withRouter是一个函数返回值是一个新组件,加工了Header组件使之可以使用路由组件的一些函数

HashRouter与BrowserRouter区别

1.底层原理
	BrowserRouter使用的是H5的history API不兼容IE9及以下版本。HashRouter使用的是URL的哈希值。
2.ur1表现形式不一样
	BrowserRouter的路径中没有#
     例如: localhost: 3000/demo/testHashRouter的路径包含#,例如: localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
	(1).BrowserRouter没有任何影响,因为state保存在history对象中。
	(2).HashRouter刷新后会导致路由state参数的丢失。
4.备注: HashRouter可以用于解决一些路径错误相关的问题。

Ant-design 蚂蚁设计

按钮及icon

//按钮
import 'antd/dist/antd.css';
import { Button } from 'antd';

主题

https://3x.ant.design/docs/react/use-with-create-react-app-cn
https://3x.ant.design/docs/react/customize-theme-cn

项目构建

npm run build
# 使用第三方库快速搭建服务 seve会以当前文件夹作为服务器根目录
npm i serve -g #-g要写在最后

serve # 启动服务器

serve demo # 以当前文件夹下的demo文件夹作为根目录

如果报错检查一下系统环境变量PATH中是否添加了npm的bin路径

扩展

setState的两种写法

react的状态更新是异步的

state = {
    //对象
}

//法1
func = () => {
    this.setState({
        //对象
    })
    //此处同步获取不到更新状态
}
//法2 对象式的setState
func = () => {
    //setState是异步更新,callback回调里的状态是更新后的
    //新状态不依赖原状态
    this.setState({/*对象更新*/},callback())
}
//法3 函数式的setState
func1 = ()=>{
    //state 就是this.state值 props是this.props
    //这里也可以有回调函数
    //新状态依赖原状态
    this.setState(func2(state,props))
}
func2 = (state,props) = > return {/*对象*/};

懒加载 Lazy_load

import {lazy, Suspense} from 'react
//对路由组件使用
const Index = lazy(()=>{import('./Index')})
//用的时候会引入index组件,当请求Index组件在请求中时会显示Suspense组件

      
        
        
      

钩子 Hooks

让函数式组件使用类式组件的state等具有生命周期

//state Hook 状态
function Index () {
    const [状态,更新状态的方法] = React.useState(状态初始化值)
    return (/*组件*/)
}

//effect Hook 生命周期
function Index () {
    //第一个参数是生命周期函数,第二个是[]表示不检测其他改变,为空表示检测所有改变
    //当[]中写入变量时表示检测变量的改变componentDidUpdate
    React.useEffect(()=>{
        //生命周期函数componentDidMount
        return //该函数返回一个函数,这个函数是componentWillUnmount
    },[])
    return (/*组件*/)
}

//ref Hook
function Index () {
    const ref = React.useRef()
    
    return ()
}

多级嵌套解决 Fragment

import {Fragment} from 'react'

//react解析会丢弃 Fragment组件,该组件只能拥有key属性用于遍历
render(){
    return (
    
            
) } //类似于,但空标签不能写任何属性 render(){ return ( <>
) }

组件优化 PureComponent

组件问题: 当子组件不使用父组件的状态时,父组件更新render也会触发子组件的render,只要执行setState即使不改变状态也会触发render

//使用PureComponent组件重写shouldComponentUpdata
/*
shouldComponentUpdata(nextProps,nextState){
    //参数为下一个即将改变的props或state
    return true;//更改组件状态
    return false;//不会更改组件状态
}
*/

import {PureComponent} from 'react'
//修改继承
class Index extends PureComponent {
  func = ()=>{
      //别这样做,PureComponent是浅比较会导致状态不能更新
      const obj = this.setState;
      obj.name = "honshen";
      this.setState(obj);
  }  
}

插槽技术 renderProps

//自定义组件中B在A的标签体内不会在页面展示被收集在A的this.props.children中

     //想要展示B可以将A组件中加入B组件或 在A组价中添加 {this.props.children}


//当B想要使用A的state时,解决上述问题
{}} /> //很灵活
 
class A { 
   render(){
        const name = ''
         return (
                 {this.props.children(name)})   
        }
    }

错误边界 ErrorBoundary

在生产环境有效

//在容易发送错误的子组件的父组件中使用
class Father extends Components{
    state = {
        hsaError: ''; //准备一个状态,用于标识子组件是否出错
    }
 static getDerivedStateFromError (error) {
     //子组件报错时会触发该函数
     
     //返回一个错误对象
     return {hasError: error}
 }   
  componentDidCatch(error, errorInfo) {
    // 你同样可以将错误日志上报给服务器
    logErrorToMyService(error, errorInfo);
  }
render(
	{this.state.hasError?"Error":}
)
}
//componentDidCatch(){在这个地方统计出错反馈给服务器} //子组件渲染出错时调用类似getDerivedStateFromError

name}/>}} /> //很灵活

class A {
render(){
const name = ‘’
return (
{this.props.children(name)})
}
}


## 错误边界 ErrorBoundary

**在生产环境有效**

```react
//在容易发送错误的子组件的父组件中使用
class Father extends Components{
    state = {
        hsaError: ''; //准备一个状态,用于标识子组件是否出错
    }
 static getDerivedStateFromError (error) {
     //子组件报错时会触发该函数
     
     //返回一个错误对象
     return {hasError: error}
 }   
  componentDidCatch(error, errorInfo) {
    // 你同样可以将错误日志上报给服务器
    logErrorToMyService(error, errorInfo);
  }
render(
	{this.state.hasError?"Error":}
)
}
//componentDidCatch(){在这个地方统计出错反馈给服务器} //子组件渲染出错时调用类似getDerivedStateFromError

你可能感兴趣的:(react)