react-3.19->3.27

React

3.19React全家桶

1.React所涉及到的技术有哪些?

  • React基础
  • React-Router:专门做路由的
  • PubSub:消息管理库
  • Redux:集中式状态管理库
  • AntDesign:UI组件库

2.React是什么?

  • 用于构建用户界面的javascript库(操作DOM呈现页面
  • React是一个将数据渲染为HTML视图的开源js库

3.组件化与模块化?

  • 组件化:html、css、js放到同一个文件中,整个文件就是一个独立的组件
  • 模块化:将函数挑出来封装到js文件中,只在需要的时候调用这个js文件即可,这就是模块化

4.React的特点?

  1. 采用组件化,声明式编码(自动化:(命令式)电风扇跟(声明式)空调)
  2. 在React Native中可以使用React语法进行移动端开发(用js编写安卓和IOS)
  3. 使用虚拟DOM+优秀的Diffing算法,减少真实DOM的交互

5.react需要的三个js文件?

  • react.development.js(必须在第二个之前)=>生成React对象
  • react.dom.development.js=>生成ReactDOM对象(render方法在这上面)
  • babel.min.js
  • react使用的是jsx语法

6.jsx的写法?

jsx的写法
<script type="text/babel">//一定要写babel
 //此处写的不是js语句,而是react语句了
    //1.创建虚拟DOM
    const VDOM=<h1>HELLO,React</h1>
	//2.渲染虚拟DOM到页面
	ReactDOM.render(VDOM,document.getElementById("xxx"))
</script>
  • jsx里面的标签能够跟js语句混着写

  • 将jsx中的标签渲染到页面中,需要用react内置的方法React.render(VDOM,原生js方法获取元素)

注意点:

  1. text/babel区域内的标签代码,千万不要写引号

3.20

3.20虚拟DOM两种创建方式

1.使用jsx:const VDOM=hello

2.原生js:React.createElement(标签名,标签属性,标签内容)

例子:React.createElement(“h1”,{name=“haha”,age=22},“hello”)

JSX

如果想在第一个标签内部创建一个子标签,则直接以标签的形式实现:

const vdom=<h1><span>hello world</span></h1>

原生js(一般不用)

如果想在第一个标签内部创建一个子标签,则需要嵌套的方式实现:

  • React.createElement("h1",{name="haha",age=22},React.createElement(...))

总结:jsx就是原生js创建虚拟DOM的一种语法糖

  1. 关于虚拟DOM,本质是Object类型的对象(一般对象)
  2. 虚拟DOM比较轻,真实DOM比较重,因为虚拟DOM是React内部再用,无需太多属性
  3. 虚拟DOM会被React转化为真实DOM,呈现在页面上

3.20 jsx特点

  • jsx的全称:javascript+ XML
  • React定义的一种js扩展语法
  • 本质上是创建React.createElement(component,props,...children)的一种语法糖

jsx中调用变量

//jsx中调用变量,需要加{}调用

//1.创建变量
	const mid=1;
	const name="sjh"
//2.渲染虚拟DOM到页面
    ReactDOM.render(
     
     <div id={mid}>{name}</div>
    )
  • 标签内想混入js表达式,需要用花括号的形式
  • 定义虚拟DOM时,不要写引号

jsx中给标签定义类名

在js中定义类名用class

在jsx中定义类名用className

    ReactDOM.render(
     <div id={mid} className="mytest ">{name}</div>
    )

jsx中的style内联样式

  • js中的内联样式:<h1 style="color:red"></h1>
  • jsx中的内联样式:<h1 style={{color:red}}></h1>
    • 最外层{}表示要写js表达式了,内层{}表示写的是对象
    • 内联样式中的键值对,

jsx中虚拟DOM不能有多个根节点

jsx内虚拟DOM的标签必须闭合

jsx中默认标签为小写,组件标签开头应大写

  • 标签首字母
    • 若为小写字母,则将标签改为html同名元素.若HTML中无该标签对应的同名元素,则报错。
    • 若为大写字母,则去找对应组件

3.20jsx中数组的遍历

  • jsx中的虚拟DOM标签中,可以通过{}花括号引入表达式,但绝对不能直接引入语句

  • 
    const data=["angular","vue"]
    
    //引入语句(错误)
    //创建虚拟DOM
    const VDOM=(
    	<h1>前端框架</h1>
    	<ul>
            {
            for(let i=0;i<data.length;i++){
            	<li>data[i]</li>
            }
            }
    	</ul>
    )
    
    //引入语句(正确)
    const VDOM2=(
        <ul>
           {
                data.map((item,index)=>{
                    return <li key={index}>{item}</li>
                })
            }
        </ul>
    )
    

何为语句和表达式

  • 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
    • let a=null;a+b;arr.map()都是表达式
  • 语句:代码,控制代码走向,没有返回值
    • if(){}
    • for(){}
    • switch(){case:xxxx}

3.20模块与组件、模块化与组件化

  • 模块:一个js文件相当于一个模块

    • 复用js简化js的编写,提高js运行效率
  • 组件:将一份js/css/html组合在一起,形成一个全功能性组件,叫做组件

  • 模块化:当应用的js都以模块来编写,这个应用就是一个模块化的应用

  • 组件化:当应用是以多组件的方式实现,这个应用就是一个组件化的应用

3.20函数式组件和类式组件

执行ReactDom.render(,document.getElementById())之后发生了什么?

  • 第一步:React解析组件标签,找到了MyComponent组件
  • 第二步:发现组件是用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,呈现在页面中

函数式组件

  • 函数式组件适用于简单组件的定义

  • //定义函数式组件
    function Demo(){
     return <h2>我是函数式组件</h2>
    }
    //使用函数式组件
    ReactDom.render(<Demo/>,document.getElementById('test'))
    
  • 以上为函数式组件

  • 注意点

    • 因为babel自动开启了严格模式,所以函数式组件中的this是undefined

类式组件

类相关知识:

  • 类的constructor构造器不是必须要写的,只有给实例添加一些私有的属性时才需要写
  • 如果A类继承了B类,且A类写了构造器,那么A类的构造器中必须调用super()

类式组件:

  • 想要创建类式组件,就必须要先继承另外一个类React.Component

  • 类式组件中必须要写render()方法

  • 类式组件中的render必须有返回值,且返回内容

  • 创建组件时的render与渲染组件的render没有任何关系

  • render中的this是谁?->MyComponent中的实例对象,因为render是在new构造出实例后,通过实例调用的

  • 除render函数之外,其他函数中的this都需要看情况而定,因为其他函数不是通过实例调用的

  • 组件实例对象中的三大属性(state,refs,props)都是继承自React.Component类的构造器创建的

  • 类中所有定义的方法,都局部开启了严格模式

  • //1.创建类式组件:继承React的组件类
    	class MyCompnent extends React.Component{
    		render(){
                return <h1>react</h1>
            }
    	}
    //2.渲染组件到页面上
    	ReactDOM.render(<MyComponent/>,document.getElementById("test"))
    
  • 执行上面一段代码之后会经历什么?

    • 第一步:React解析组件标签,找到MyComponent组件
    • 第二步:发现组件是类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
    • 第三步:将render返回的虚拟DOM转为真实DOM,随后呈现在页面上

如何修改state中的值,驱动页面更新内容?

  • 如果我们想通过某个行为修改state中值,不能直接通过赋值修改state中的值,这样是错误的

3.20组件的三大属性

函数式组件中只能玩:props,如果想规定props的属性类型,只能通过原始写法来定义propTypesdefaultProps

类式组件中三大组件都能玩:state、props、refs

state(状态)

组件实例的三大属性之一

  • 人: 状态 影响 行为
  • 组件:状态 驱动 页面

state注意点:

  • state在constructor中定义,如果没有构造器,则可以直接在类中定义state

  • state应该是一个对象,可以定义多个属性({key:value}

  • class MyComponent extends React.Component{
        //方式一
        constructor(props){
            super(props)
            //初始化状态
            this.state={
                ishot:true
            }
        }
        //方式二
        state={isHot=true}
        
    }
    render(){
        //读取状态
        let isHot=this.state
    }
    
  • 组件被称为状态机,通过更新组件的state来更新对应的页面显示(重新渲染组件)

  • 不能直接修改state中的值:需要用Apithis.setState({ishot:false})

重点、重点、重点

  • 组件中render方法中的this为组件实例对象
  • 组件自定义的方法中this为undefined,解决方法:
    • 1、强制绑定:bind
    • 2、箭头函数
  • 状态数据,不能直接修改或更新
state的简写方式
  • state应该是放在实例上的属性,所以在构造器中就是this.state,作为实例的状态值

  • 但是在类中,实例的属性不仅可以在构造器中用this构造,直接在类中构造的属性,也会称为实例的私有属性

    • 注意:类中不用定义属性,可以直接写赋值语句

    • //给Car的实例添加一个a和一个state私有属性
      class Weather extends React.Component{
      	//初始化状态
      	state={name:11}
      	//获取最终需要渲染的信息    
          render(){
              return <h1></h1>
          }
          //自定义的方法:这样写能够保证方法中的this是实例本身
          chageWeather=()=>{
              this.setState({isHot:!isHot})
          }
      }
      
    • 自定义要用赋值语句+箭头函数的方式定义

props(属性)

  • 给组件传的标签属性就能在类中的props属性中找到

  • props中的内容是只读的

    •  class Person extends React.Component{
       	
       	render(){
       		return (
                  <ul>
                      //这里就能够通过实例的props属性找到实例标签中的name,age,sex
                      <li>{this.props.name}</li>
                      <li>{this.props.age}</li>
                      <li>{this.props.sex}</li>
                  </ul>
       		)
       	}
       }
        
      //渲染组件到页面
       ReactDom.render(<Person  name="sjh"  age=12  sex="male"/>,doument.getElementById("d1"))
      
props的语法糖(批量传递标签属性)
  • babel和react允许你在标签属性传递的过程中,用展开运算符去展开一个对象

    • //原始写法
       ReactDom.render(<Person  name="sjh"  age=12  sex="male"/>,doument.getElementById("d1"))
      //语法糖写法
      let p1={ name:"sjh",age:12,sex:"male"}
       ReactDom.render(<Person {...p1}/>,doument.getElementById("d1"))
      
    • 注意点:传递的对象内的属性名,必须与需要的属性名匹配

规定props中的属性类型
  • 给类添加事先定义好的规定属性类型属性Person.propTypes,就可以定义prop中的属性类型了

  • //对标签属性进行类型、必要性限制
    Person.propTypes={
    	name:PropTypes.string//规定props中的name属性必须是字符串类型
        age:PropTypes.number.isRequired //规定props中的age属性必须是数字且是必填的
        speak:PropTypes.func//注意注意,如果想要规定函数类型,不能写小写的function,因为与默认的函数数据类型冲突了,需要写func
         
    }
    //指定默认标签属性值
    Person.defaultProps={
        sex:"不男不女",//如果实例没有给传sex属性的值,则sex为不男不女
        age:18
    }
    
    • Person.propTypes:组件限制属性类型的默认属性

    • PropTypes:定义属性类型的专门的类,想用它首先要引入prop-types.js

    • Person.defaultProps:设置props属性中默认属性的值

    • 注意注意,如果想要规定函数类型,不能写小写的function,因为与默认的函数数据类型冲突了,需要写func

    • props是只读的(单向数据流)

props的简写方式
  • 将propTypes和defaultProps放到class类中,用static

  • class Person extends React.Component{
    	render(){
            return ...
        }
         state={...}
         props={...}
        //将下面两个属性放在Person类中作为静态属性,而不是实例的私有或公有属性
        static propTypes={...}
        static defaultProps={...}
        //自定义方法
        func1=()=>{
            ...
        }
    }
    
构造器中的props
  • 构造器是否接收props,是否传递props,取决于是否需要在构造器中通过this访问props
函数式组件使用props
  • 函数中所有传递的标签属性,都会传给函数的第一个参数对象props中

  • //props是一个对象类型的参数,接收所有给组件定义的属性
    function Person(props){
    	return (
            <ul>
                <li>姓名:{props.name}</li>
                <li>性别:{props.age}</li>
            </ul>
    	)
    }
    
    ReactDOM.render(<Person name="sjh" age=11/>,document.getElementById("p1"))
    

refs(引用)

  • 原生js中获取真实DOM的方式:let box=document.getElementById('box')

  • refs的作用是获取组件中标签的真实DOM,然后通过真实DOM实现事件或动作的交互

    • ref属性值应该唯一,就像Id一样
    • 每个实例都有一个refs私有属性,是对象类型,它会存放所有添加了ref标签的DOM元素
  • //第一步:在render渲染的标签中加上ref属性
    class Demo extends React.Component{
        render(){
            return(
                <div>
                    //在这里为input标签定义了ref属性
                    <input ref="inp">
                    <button  onClick={this.show}>点击</button>
                </div>
            )
        }
        //第二步:通过refs属性就能获取到已经添加了ref属性的标签:inp
        show=()=>{
           console.log(this.refs.inp)//能够获取	
        }
    }
    
     
    
ref的定义方式
  • 方式一(字符串类型): <input ref="inp">

    • 目前已经不推荐用了,因为字符串类型的ref存在效率问题
  • 方式二(回调函数形式):

    • <input ref={c=>{this.inp1=c}}>

    • 这种写法是利用了ref绑定的回调函数中能够接收到当前标签的节点,最后绑定到实例上作为实例的私有属性

    • 如果回调函数是以内联形式定义的,在更新过程中会调用两次,第一次获取的参数是null,第二次获取的参数是当前节点,如果不想调用两次,可以用类中定义函数的形式

      • //类中定义回调函数方式
        class Person extends React.Compnent{
            getInput=()=>{
                console.log(111)
            }
        	render{
        		return(
        			<input ref={this.getInput}/>
        		)
        	}
        }
        
        
  • **方式三(createRef API)😗*生成一个容器,之后ref标签就可以直接放到这个容器中

    • 该容器是专人专用的,每个容器中只能放一个标签

    • //类中定义回调函数方式
      class Person extends React.Compnent{
          //myRef就是一个容器
          myRef=React.creatRef()
          myRef2=React.creatRef()
      
      	render{
      		return(
                  //将这个输入标签放到myRef容器中
      			<input ref={this.myRef}/>
                  <input ref={this.myRef2}/>
      		)
      	}
      }
      
总结:
  • 尽量避免使用字符串的ref定义方式,内联目前看来是最舒服的

3.21

3.21react中标签的事件绑定

  • react中所有的原生html事件都被重写为驼峰命名的写法,比如:

    • onclick->onClick
  • //原生js
    <button οnclick="demo()">按钮</button>
    //react:注意react中绑定事件的函数不能加括号,加括号会绑定成函数的回调函数
    <button onClick={demo}>按钮</button>
    
    class Weather extends React.Component{
        render(){
            return <h1 onClick={this.changeWeather}></h1>
        }
        changeWeather(){
            
        }
    }
    
  • 当组件标签绑定事件时,一定要指明是哪里的函数this.changeWeather

3.27

3.27React中的事件处理

  • 通过onXxx属性指定事件处理函数(需要注意大小写)
    • 1、React使用的是自定义(合成)事件,而不是使用原生DOM事件->为了更好的兼容性
    • 2、React中的事件是通过事件委托的方式处理的(委托给组件最外层的元素)->为了高效
  • 通过event.target得到发生事件的DOM元素对象->不要过度的使用ref

3.27React中收集表单中的数据

  • 非受控组件:页面中所有输入类DOM(现用现取),它的内容不被state收录,这就是非受控组件(需要通过ref拿值)

  • 受控组件:页面中的输入类DOM,他们的值被收录到state中,这就是受控组件,(不需要通过ref拿值)

3.27react中的柯里化函数

  • 函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的方式就称为柯里化函数

  • 对象中想读取一个变量,必须用[]括起来

  • class Person extends React.Component{
        setFormData(dataType){
            return (event)=>{
                //注意:这里的dataType是在对象中设置,想要调用外部的dataType,必须加上中括号
                this.setState({[dataType]:event.target.value})
            }
            
        }
        render(){
            return(
            <input onChange={{this.setFormData("username")}}>
                    <input onChange={{this.setFormData("password")}}>
            )
        }
    }
    ReactDOM.render(<Person/>,document.getElementById("p1"))
    

高阶函数

  • 如果一个函数符合下面两个规范中的任何一个,它就是高阶函数:

    • 若A函数,接收的参数是一个函数,那么他就是高阶函数
    • 若A函数,return的值仍然是一个函数,那么它就是高阶函数
  • 常见的高阶函数:

    • Promise、setTimeOut、arr.map等

3.27组件的生命周期

**生命周期的作用:**在关键的点,调用某些函数,执行一些事情

生命周期回调函数<=>生命周期钩子函数<=>生命周期函数<=>生命周期钩子

生命周期图(旧):

image-20220327213313399
  • 挂载过程中生命周期函数的执行过程:constructor->componentWillMount->render->componentDidMount->componentWillUnmount

  • 更新状态过程中生命周期函数的执行过程setState()->shouldComponentUpdate->

componentWillMount(组件将要挂载)

  • 组件将要挂载的时候触发的方法(在render之前触发)

render(渲染组件)

  • render是组件实例化后,组件的实例调用的第一个默认函数
  • **调用时机:**初始化渲染、状态更新时

componentDidMount(组件挂载后)

  • componentDidMount是组件挂载到页面之后调用的函数

componentWillUnmount(组件卸载之前)

  • componentWillUnmount是组件将要卸载时调用的函数

shouldComponentUpdate(判断组件是否需要更新)

  • 控制组件更新的阀门

  • 当修改了信息之后,会调用shouldComponentUpdate来判断是否需要更新组件,如果该函数返回的是true则继续往下走,如果返回的是false则停止前进

  • 如果不调用该函数,则会有一个默认的返回值,但是如果调用了该函数,则返回的值必须是布尔值,否则会报错

componentWillUpdate(组件将要更新时调用)

  • 判断需要更新组件后调用的函数

componentDidUpdate(组件更新之后调用)

componentWillReceiveProps(组件将要接收props)

  • 父组件触发了render时,子组件就会触发这个函数
  • 父组件第一次render时不会调用,只有第二次触发render时才会调用

例子:

class Compon extends React.Component{
    //组件实例化之后第一个调用的函数
    constructor(){...}
    //组件将要挂载的时候调用
    componentWillMount(){...}
  	//组件渲染和更新的时候调用
    render(){...}
    //组件挂载到页面之后触发的函数
    componentDidMount(){...}
	//触发修改方式一:更改状态值数据
    this.setState()
    //修改方式二:强制更新组件
    this.forceUpdate()
    
    //用来判断组件是否需要更新时调用
    shouldComponentUpdate(){ return false}
    //组件更新之前调用
    componentWillUpdate(){...}
    //组件更新之后调用
    componentDidUpdate(){...}
     //组件将要被卸载时触发的函数
    componentWillUnmount(){...}
     
}

3.27react组件中的父子关系

  • react中组件存在父子关系:在A的render方法中调用B组件标签,则组件A就是组件B的父

  • class A extends React.Component{
    	render(){
    	   return(
               <div>
               		<B/>
               </div>
    	   )
    	}
    }
    class B extends React.Component{
    	render(){
    	   return(
               <div>
               		B
               </div>
    	   )
    	}
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值