react的超详细讲解

create-react-app
项目目录
在HTML中使用react
1
2
3基础
React的注意事项
模拟的React 和 render
React组件
函数组件
类组件
React 的数据源(props(外部传入,不可修改) ,state(内部自带,可修改))
React 生命周期(钩子函数)
React Event 中的this问题
prop-types
受控与非受控组件
React 是单向数据流
4 超详细讲解
React高性能的体现:虚拟DOM
React Fiber
编写第一个react应用程序
函数组件
es6 class组件其实就是一个构造器,每次使用组件都相当于在实例化组件,像这样:
在16以前的版本还支持这样创建组件, 但现在的项目基本上不用
组件的组合、嵌套
React.createElement
create-react-app
脚手架工具create-react-app
基于webpack的一个工具,帮助我们快速创建一个项目 webpack gulp

npm install create-react-app -g yarn create-react-app -V 查看脚手架工具的版本 create-react-app 项目名字 创建项目 npm run start 开发环境运行 npm run build 打包 npm run eject 解开大礼包 在git仓库做一个commit操作

项目目录
config(vue.config.js) 默认不存在 解开大礼包才会出现 对项目做一些配置 代理 public 资源路径根vue中的public一样 scripts 文件 项目启动文件项目打包文件 src 源码文件 index.js === main.js 入口文件

create-react-app官方的一个生成react项目,安装时后面跟一个项目名称 需要在一个空的文件夹下安装 create-react-app 安装的时候会自动帮我们下载react(需要的react),react-dom(主要是渲染),react-script(可以认为继承了webpack的脚手架) 加-g是全局安装 npm install create-react-app myApp //mac 安装需要加 sudo sudo npm install create-react-app myApp

启动服务 npm start 开启本地服务 npm build 打包 npm test jest进行单元测试 npm eject 可以把webpack命令打包出来,方便我们修改webpack文件,但此操作不能回退

cmd
“–exact” “react” "react-dom"dom 渲染 "react-scripts"继承了webpack的脚手架 “cra-template” “–cwd”

react-scripts > jest > jest-cli > jest-config > jest-environment-jsdom > jsdom > left-pad
react-scripts > workbox-webpack-plugin > workbox-build > strip-comments > babel-plugin-transform-object-rest-spread > babel-runtime > [email protected]: core-js@❤️
“react-scripts > [email protected]” has incorrect peer dependency “[email protected]”.
warning “react-scripts > @typescript-eslint/eslint-plugin > [email protected]” has unmet peer dependency “typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta”.
在HTML中使用react

// 创建组件
/*
1.通过React crateClass 方法创建组件
2. 配置项里固定有一个render函数
3. render函数里要求return页面模板
4. 组件也是一个虚拟dom
*/

/*
React.createElement(‘div’,{id:‘test’},[
React.creatElement(‘h1’,{class:‘red’,text:‘jsx语法(vue中的模板)’},[])
React.createElenent(‘p’,{text:123},[
React.craeteElement(‘span’,{text:1})
])
])
语法 糖 class 简化代码少写点
jsx javascript xhtml
可以让我们在js里写html标签
1.标签必须闭合
2.必须有一个根元素
正常的js代码不能直接写标签 jsx 也不行
想使用需要将jsx的语法进行解析
type=‘text/babel’ 是告诉浏览器该标签的内部需要解析jsx
*/

// 注释方式 {/要注释的内容/}
// 控制一个元素的渲染 ||
// 2个元素切换 三元表达式
// 渲染的东西比较多 用函数

/*
react 不允许直接将对象绑定在页面
react 绑定数组到页面回将数组的每一项拆分
*/

/*
事件绑定 原生事件用驼峰命名法 注意传参不能能加() bind

方法一直接调用处理函数
react 中的事件和原生类似 将原生事件使用变成驼峰命名法 onclick->onClick
默认参数是事件对象
传递参数不能写() 所以通过bind 进行传参 默认参数放到最后
方法二
在事件的函数里 调用目标处理函数
注意 需要手动传递事件对象
*/

/*
setState 通知组件重新渲染一遍
setState 是一个异步的函数
参数1 表示要修改的数据 参数2是一个回调 当数据修改结束后执行
1-2-3-4-1
setState 同步中 修改数据不会直接更新页面 将同一个事件循环所有的setState 合并 更新一次页面
setState 如果在异步中 每一次都会触发页面刷新
*/

/*
使用方式2 通过ref 绑定组件
可以获取组件对象 获取绑定组件的相关方法
*/

/*
组件标签中写的内容不会被渲染
但是可以在组件内部通过 props.childer 获取使用
/
/

组件通信
父子 props 将父组件的数据传递给子组件 ref 获取子组件的方法 由父组件调用
子父 props 将父组件的方法传给子组件调用
兄弟 状态提升 上下文 全局状态管理 redux

父子通信 1 父组件控制子组件元素的渲染
将 控制div显示的state 放到子组件上
子组件有一个修改 state值的方法
通过ref 将父组件调用子组件的方法
/
/

父子通信 2 父组件控制子组件元素的渲染
直接传递数据
1.控制元素渲染的数据放在父组件上
2.修改的方法放在父组件上
3.通过props 将数据传递给子组件
4.父组件调用自己的方法修改
*/

/*
子父通信 子组件控制父组件
1数据在父组件上
2.修改数据的方法在父组件
3.将父组件的方法传给子组件调用
*/

/*
亲兄弟通信
1.子元素控制另一个子元素的div显示
2.控制变量放在父组件
3.控制变量的方法也在父组件上
4.结合父子和子父通信
*/
let Son = React.createClass({
sonfun(){
console.log(‘子组件的方法’)
},
toggle(num1,num2){
console.log(num1,num2)
this.setState({show:!this.state.show})
},
render(){
return(


子组件

子组件:{this.props.children}

<button onClick={()=>{
this.props.sonToggle(6,8)
}}>sonToggle

    {!this.props.show||<div className='red'></div>}

  </div>
  </div>
)

}
})
let Son2 = React.createClass({

render(){
return(


子组件2

<button onClick={()=>{
this.props.toggle()
}}>toggle

)
}
})

let Component = React.createClass({
getInitialState(){
console.log(‘初始化state值’) //类似于vue中的data
return {
name:‘韩梅梅’,
hide:true,
num:1,
string:‘呵呵’,
arr:[“呢”,‘he’,‘sdf’],
obj:{us:123,ps:123},
null:null,
undef:undefined,
boolean:true,
tabs:[‘动作’,‘恐怖’,‘动漫’,‘喜剧’],
// tabs:[‘

  • 动作
  • ’,‘
  • 恐怖
  • ’,‘
  • 动漫
  • ’]
    // tabs:[
  • 动作
  • ,
  • 恐怖
  • ,
  • 动漫
  • ]
    color:false,

    }
    

    },
    renderDiv(){
    console.log(‘渲染div’)
    if(this.state.hide){

    }else{
    
    return (<img src='dsfsf'/>)
    }
    

    },
    test(num1,num2,event){
    console.log(‘点到我了’,num1,num2,event)
    },
    toggle(){
    // this.state.color=!this.state.color
    console.log(this.state.color)
    this.setState({color:!this.state.color})
    },
    render(){
    return (


    hehe


    hehe


    {this.props.hehe}
    {/* {this.state.show?
    div
    :

    p

    } /}
    {/
    { this.state.hide||
    div
    }*/}
    {this.renderDiv()}

    数据绑定


    {this.state.num}

    {this.state.string}

    {this.state.null?‘a’:‘b’}

    {this.state.undefined?‘c’:‘d’}

    {this.state.boolean?‘真’:‘假’}

    {this.state.obj.us}

    {this.state.arr}

        <ul>
           {this.state.tabs.map((item,index)=>{
             return (<li>{item}</li>)
           })}
          </ul>  
          
        {/*<button onClick={this.test.bind(this,1,2)} >add</button>*/}
           <button onClick={(e)=>{
             console.log(11)
             this.test(1,2,e)
           }}>add</button>  
           
        <div className={this.state.color?'red':'blue'}>
          </div>
          <button onClick={this.toggle}> toggle</button> 
          
        // this.setState({num:5},()=>{
            //   console.log('赋值结束',this.state.num)
            // })
            // console.log('bottom',this.state.num)
            setTimeout(()=>{
              this.setState({num:2})
              this.setState({num:3})
              this.setState({num:4})
              this.setState({num:5})
            },1000)
            
        <img ref='hehe' src="sfsf" alt=""/>
          <button onClick={()=>{
             console.log(this.refs.hehe)
          }}> toggle</button>  
          
        <button onClick={()=>{
             console.log(this)
             this.refs.son.sonfun()
          }}> toggle</button>
          <hr/>  
          <Son ref='son'>
                你买到票了没
          </Son>  
          
          <button onClick={()=>{
            this.refs.son.toggle(1,2)
          }}>toggle</button>
          <Son ref='son'></Son>
          
          <button onClick={()=>{
            this.setState({show:!this.state.show})
          }}>toggle</button>
          <Son toggle={this.state.show}></Son>
          
          toggle(num1,num2){
    console.log(num1,num2)
    this.setState({show:!this.state.show})
    

    },
    render() {
    return (


    这里是父组件


    {!this.state.show||
    }

          toggle(){
    this.setState({show:!this.state.show})
    

    },
    render() {
    return (


    这里是父组件

          <Son1 show={this.state.show}></Son1>
          <Son2 toggle={this.toggle}></Son2>
      </div>
    )
    

    }
    })

    // 将组件挂载到 app元素上 参数1 要挂载的组件 参数2 要挂载的元素
    // 组件名当成标签名使用 组件名必须大写
    ReactDOM.render(,document.getElementById(‘app’))
    // ReactDOM.render(,app)

    1 https://blog.csdn.net/qq_36824244/article/details/103003640

    用于构建用户界面的javascript库

    16之前采用diff算法,之后采用fiber算法,分成小块,异步渲染

    import React from “react”
    //只要使用jsx的语法都需要引入react,这是顶级api
    import ReactDOM from “react-dom”
    //render是react dom提供的一个方法,这个方法通常只会渲染一次
    import { render } from ‘react-dom’

    const app=

    Welconme


    //函数式组件
    //使用箭头函数,但名字要大写开始
    const createApp = (props) => {
    //在jsx里面写js语法需要加{},只有这一种语法
    return

    Welconme{props.title}


    }
    const app = createApp({
    title: ‘16.8’
    })
    //类组件
    class App extends React.Component {
    render () {
    return

    类组件!!!


    }
    }
    //new一个实例
    //类组件渲染的原理
    // 因为app不是一个element所以必须要调实例的render方法
    const app = new App({
    desc:‘类组件是继承React.Component的1’
    }).render()
    //表示一个虚拟dom树
    const appVDom = {
    tag: ‘div’,
    attrs: {
    className: ‘app’,
    id: ‘appRoot’
    },
    children: [
    {
    tag: ‘h3’,
    attrs: {
    className: ‘title’
    },
    children: [
    ‘类组件!!!’
    ]
    },{
    tag: ‘p’,
    attrs: null,
    children: [
    ‘类组件是继承React.Component的’
    ]
    }
    ]
    }
    //所以react在真正渲染的时候会把上面的代码成下面这个样子,这是合法的js代码
    class App extends Component {
    render () {
    return (
    // React.createElement是一个方法,用于创建元素,可以有很多参数,但前两个是固定的
    //第一个为标签名
    //第二个为标签的属性
    React.createElement(
    ‘div’,
    {
    className: ‘app’,
    id: ‘appRoot’
    }
    ),
    React.createElement(
    ‘h3’,
    {
    className: ‘title’,
    },
    ‘类组件’
    ),
    React.createElement(
    ‘p’,
    null,
    ‘类组件是继承React.Component的’
    )
    )
    }
    }
    //下载class包 npm i classnames --save

    ReactDOM.render(app,querySelector("#toot")

    //在react6以前使用的是这种方式来创建一个类组件
    React.createClass({
    render

    类组件!!!


    })
    2
    https://blog.csdn.net/halations/article/details/84389261

    3基础
    https://blog.csdn.net/qq_30523685/article/details/85621598

    React的注意事项
    一般采用import的方式引入React,React首字母规定大些,因为jsx会默认使用大写的React

    会根据尖括号(<)来判断是一个html,根据花括号({)来判断是一个js js中的保留字 关键字会进行转化 class=>className for=>htmlFor react相邻的jsx元素,react元素,必须被一个标签包裹 <></> style标签 必须是一个对象 style={ {}} //{}表示js里面的{}表示是一个对象 注释 要用{}包裹 dangerouslySetInnerHTML 危险的,解析html用innerHtml的方式把内容塞进元素中

    你好"}}>
    可以在页面中使用三元运算 事件方法 之前的οnclick=> onClick …

    模拟的React 和 render
    react渲染的流程

    react会把jsx语法渲染成React.createElement()格式 React.createElement() 会转为 vnode(虚拟节点) vnode 渲染到页面上

    let React = {
    createElement(type,props,…children){//可以组成一个对象,用来描述dom元素
    return {type,props,children};//虚拟dom
    }
    }
    let ele =

    哈哈

    ;
    console.log(ele);//返回一个对象
    let render=(obj,container)=>{
    if(typeof obj === “string”) return container.appenChild(document.createTextNode(obj));
    let {type,props,children} = obj;
    let ele = document.createElement(type);
    for(let key in props){
    ele.setAtteributte(key,props[key])
    }
    children.forEach(item=>{
    render(item,ele);//递归,渲染子节点
    })
    children.appendChild(ele);
    }
    React组件
    函数组件
    函数就是组件 组件名称规定首字母大写,小写认为是一个标签元素 组件在元素中应用<组件名/> or <组件名></组件名> 组件传递的属性或方法(<组件名 title={“222”}>)会把传入的属性包成一个对象({title:“222”})传给这个组件函数props,在组件内取值时就是,{props.title}

    函数组件会在内部添加一个render方法,把函数的返回结果作为render方法的返回结果
    函数组件的不足

    没有状态 新版本有增加 没有生命周期的钩子 新版本有增加 函数组件中没有this

    类组件
    类组件在渲染时会默认调用render方法 类组件内有状态和钩子函数 需要继承React.Component React.Component 是一个基类,有生命周期,更改状态的方法 继承React.Component 之后才算是一个React类。

    import React from “react”;
    import ReactDOM from “react-dom”;
    class Clcok extends React.Component{
    constructor(props){//会接受组件传入的属性or方法
    super(props);
    //this.state 是规定死的,表示给这个组件生命状态
    this.state={ }
    }
    //es7语法 简单粗暴 和上面的一样
    // state={}
    render(){
    return

    哈哈


    }
    }
    React 的数据源(props(外部传入,不可修改) ,state(内部自带,可修改))
    props 会把组件传入的属性or方法放在this上 ---- 取值时:this.props.name1 this.state 状态 ---- 取值时:this.state.name1 this.setState

    是父类提供的,用于修改状态,这种更新状态的方式,不会覆盖之前的,只会进行比较把更新的状态进行合并 this.setState 会刷新页面,如果不用this.setState。直接修改state 会改状态还是页面不会刷新 需要改属性的话只能把属性(props)变为状态(state) this.setState 可以执行多次么? 面试题

    React 生命周期(钩子函数)
    componentDidMount(){} 当前组件挂在完成,在render方法加载完之后执行 unmountComponentAtNode() 卸载组件 //用法 ReactDOM.unmountComponentAtNode(window.root) componentWillUnmount(){} 将要卸载,在此阶段中删掉所有的监听和卸载异步方法 componentDidMount(){ this.itemer = setInterval=()=>{ //this.setState 可以导致页面刷新 this.setState({time:new Date().toLocalString()}) } } componetWillUnmount(){ clearInterval(this.timer); }

    React Event 中的this问题
    this问题

    通常在元素中给事件绑定一个函数 (onClick = this.btnclick) this是undefined的 在es6 类中,如果把原型上的方法拿出来,这是一个错误的操作,this是undefined btnclick(){} 1 如果解决this指向问题

    在元素中绑定时加入bind(onClick = this.btnclick.bind(this)) 每次点击都产生一个新的函数 在constructor中设置一下,然后在元素中用(οnclick={this.btnclick}) 官网推荐 consttuctor(){ super(); this.btnclick = this.btnclick.bind(this); //这样每次点击的时候都是用的一个函数。 }

    采用箭头函数可以完美解决,只要是在原型中的方法采用箭头函数就可以 在元素中直接用(οnclick=this.btnclick) es7方式 btnclick=()=>{} //这里采用箭头函数方式

    prop-types
    React 内置了类型检测的功能,在组件中检测,可以赋值propTypes属性

    格式校验 需下载 propTypes 属性 .array 数组 .bool 布尔值 .func 函数 .number 数字 .object 对象 .string 字符串 .symbol 符号 .node 任何东西都可以被渲染:numbers, strings, elements,或者是包含这些类型的数组(或者是片段)。 .element React元素 .instanceOf(Message) 类的一个实例 .oneOf([‘News’, ‘Photos’]) 枚举值 .oneOfType([PropTypes.string,PropTypes.number,PropTypes.instanceOf(Message)]) 多种类型其中之一 .arrayOf(PropTypes.number) 某种类型的数组 .objectOf(PropTypes.number) 某种类型的对象 .shape({color: PropTypes.string,fontSize: PropTypes.number}) 特定形式的对象 .func.isRequired 可以使用 isRequired’ 链接上述任何一个,以确保在没有提供 prop 的情况下显示警告 .any.isRequired 任何数据类型的值 function(props, propName, componentName) { return new Error()} 自定义的验证器 .arrayOf(function(propValue, key, componentName, location, propFullName) {} import React from ‘react’; import ReactDOM from ‘react-dom’; import PropTypes from ‘prop-types’; class Person extends React.Component{ static defaultProps = { nam

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
React Refs 是 React 提供的一种访问 DOM 元素或组件实例的方法。通过 Refs,我们可以在组件中直接访问到被 Refs 引用的 DOM 元素或组件实例,从而进行一些特殊的操作。 下面,我来举一个 React Refs 的案例: 假设我们有一个 Input 组件,需要在组件加载完毕后自动获取焦点,我们可以通过 Refs 来实现这个功能。具体的实现步骤如下: 1. 在 Input 组件中定义 Refs: ```jsx class Input extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); // 创建 Refs } render() { return <input type="text" ref={this.inputRef} />; } } ``` 2. 在 componentDidMount 生命周期中,使用 Refs 获取到 input 元素,并调用 focus() 方法: ```jsx class Input extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); // 创建 Refs } componentDidMount() { this.inputRef.current.focus(); // 获取 input 元素并获取焦点 } render() { return <input type="text" ref={this.inputRef} />; } } ``` 这样,当 Input 组件加载完毕后,它的 input 元素就会自动获取焦点了。 注意,Refs 只能在类组件中使用,不能在函数式组件中使用。另外,Refs 的值可以是回调函数,而不仅仅是 React.createRef() 方法返回的对象。如果使用回调函数的方式,可以在回调函数中访问到组件实例或 DOM 元素,例如: ```jsx class Input extends React.Component { constructor(props) { super(props); this.inputRef = null; // 创建 Refs this.setInputRef = element => { this.inputRef = element; }; } componentDidMount() { this.inputRef.focus(); // 获取 input 元素并获取焦点 } render() { return <input type="text" ref={this.setInputRef} />; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶子 ✪ω✪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值