React学习

📑前言

本文主要是【React】——React基础的文章,如果有什么需要改进的地方还请大佬指出⛺️

🎬作者简介:大家好,我是听风与他🥇
☁️博客首页:CSDN主页听风与他
🌄每日一句:狠狠沉淀,顶峰相见

React学习

1.react特点

  • 1.采用组件化的模式,声明式编程,提高开发效率及组件复用率
  • 2.使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互

1.1 ReactDOM

  • ReactDOM将组件或JSX元素渲染到DOM中。render(),负责在浏览器中渲染应用程序。
  • render方法只会覆盖,不会追加。

1.2 jsx的基本语法

  • 1.定义虚拟DOM,不能使用""

  • 2.标签中混入JS表达式时使用{}

    id = {myId.toUpperCase()}
    
  • 3.样式的类名指定不能使用class,使用className

  • 4.内敛样式要使用{{}}包裹

    style={{color:'skyblue',fontSize:'24px'}}
    

1.3 js遍历数组

objArr.map((item, index) => {
                return item.name
            })

1.4 组件的使用

当应用是以多组件的方式实现,这个应用技术一个组件化的应用

  • 1.组件名必须是首字母大写
  • 虚拟DOM元素只能有一个根元素
  • 3.虚拟DOM元素必须有结束标签</>

渲染类组件标签的基本流程

  • 1.React内部会创建组件实例对象
  • 调用render()得到虚拟DOM,并解析为真实DOM
  • 插入到指定的页面元素内部

1.5 类式组件

weather

class MyComponent extends React.Component {
    state = {isHot:false}
    render() {
        const {isHot} = this.state
        return <h1 onClick={this.changeWeather}>今天天气很{isHot?'炎热':'凉爽'}</h1>
    }
    changeWeather = ()=>{
        const isHot = this.state.isHot
        this.setState({isHot:!isHot})
    }
}
ReactDOM.render(<MyComponent/>,document.querySelector('.test'))

this的指向真的需要好好学习

  1. 组件中的 render 方法中的 this 为组件实例对象
  2. 组件自定义方法中由于开启了严格模式,this 指向undefined如何解决
    1. 通过 bind 改变 this 指向
    2. 推荐采用箭头函数,箭头函数的 this 指向
  3. state 数据不能直接修改或者更新

2.组件实例三大属性

1.state

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。

简单的说就是组件的状态,也就是该组件所存储的数据

类式组件中的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Weather1 extends React.Component{
            constructor(props){
                super(props)
            }
            state = {
                weather:'炎热'
            }
            render(){
                return <h1>今天的天气很{this.state.weather}</h1>
            }
        }
        ReactDOM.render(<Weather1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

2.pros

state不同,state是组件自身的状态,而props则是外部传入的数据

类式组件使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <div id="zz"></div>
    <script type="text/babel">
        class Person extends React.Component{
            render(){
                return (
                    <ul>
                        {/* 接受数据并显示*/} 
                        <li>{this.props.name}</li>
                        <li>{this.props.age}</li>
                        <li>{this.props.sex}</li>
                        </ul>
                )
            }
        }
        ReactDOM.render(<Person name="zzl" age="19" sex="男" />,document.getElementById('zz'))
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <div id="zz"></div>
    <script type="text/babel">
        class Person extends React.Component{
            render(){
                const {name,age,sex} = this.props
                return (
                    <ul>
                        {/* 接受数据并显示*/} 
                        <li>{this.props.name}</li>
                        <li>{this.props.age}</li>
                        <li>{this.props.sex}</li>
                        </ul>
                )
            }
            
        }
        const p = {name:"zzl",age:"18",sex:'男'}
        ReactDOM.render(<Person {...p} />,document.getElementById('zz'))
    </script>
</body>
</html>

函数式组件中的使用

函数在使用props的时候,是作为参数进行使用的(props)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        const p = {name:"zzl",age:"18",sex:'男'}
        function Person(props){
            const {name,age,sex} = props
            return (
                    <ul>
                        <li>{name}</li>
                        <li>{age}</li>
                        <li>{sex}</li>
                        </ul>
                )
        }
        ReactDOM.render(<Person {...p} />,document.getElementById('zzl'))
    </script>
</body>
</html>

函数组件的 props定义:

  1. 在组件标签中传递 props的值
  2. 组件函数的参数为 props
  3. props的限制和默认值同样设置在原型对象上

3.refs

Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。

在我们正常的操作节点时,需要采用DOM API 来查找元素,但是这样违背了 React 的理念,因此有了refs

字符串形式

在react,Vue中,均可以使用ref来操作DOM

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Demo1 extends React.Component{
             show1=()=> {
              const  {input1}=this.refs
              alert(input1.value)
            }
            show2 = () =>{
                const {input2}=this.refs
                alert(input2.value)
            }
            render(){
                return (
                    <div>
                        <input ref="input1" type="text" placeholder="点击按钮提示数据"  />
                        <button onClick={this.show1}>点击按键</button>
                        <input onBlur={this.show2} ref="input2" type="text" placeholder="失去焦点提示数据" />
                        </div>
                )
            }
        }
        ReactDOM.render(<Demo1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

createRef创建ref容器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Demo1 extends React.Component{
            // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是专人专用的
            myRef = React.createRef()
             show1=()=> {
            alert(this.myRef.current.value);
            }
            show2 = () =>{
                const {input2}=this.refs
                alert(input2.value)
            }
            render(){
                return (
                    <div>
                        <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"  />
                        <button onClick={this.show1}>点击按键</button>
                        <input onBlur={this.show2} ref="input2" type="text" placeholder="失去焦点提示数据" />
                        </div>
                )
            }
        }
        ReactDOM.render(<Demo1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

ref回调形式

ref={c=> this.username = c}

3.react中收集表单数据

1.非受控组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        //创建组件
        class Login extends React.Component{
            handleSubmit = (event) =>{
                event.preventDefault() //阻止表单提交
                const {username,password}=this
                alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
            }
            render(){
                return (
                    //登录按钮被点击时,该事件会被触发
                    <form  onSubmit={this.handleSubmit}>
                        用户名:<input ref={c=> this.username = c} name="username" type="text"/>
                        密码:<input ref={c=> this.password = c}  name="password" type="password"/>
                        <button>登录</button>
                        </form>
                )
            }
        }
        //渲染组件
        ReactDOM.render(<Login/>,document.getElementById('zzl'))
    </script>
</body>
</html>

2.受控组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Login1 extends React.Component{
            handleSubmit = (event) =>{
                event.preventDefault()
                const {username,password} = this.state
                alert(`用户名为${username},密码为${password}`)
            }
            //初始化状态
            state = {
                username:'',
                password:''
            }
            //保持用户名
            saveUsername = (event)=>{
                this.setState({username:event.target.value})
            }
            savePassword = (event)=>{
                this.setState({password:event.target.value})
            }
            render(){
                return (
                    <form onSubmit={this.handleSubmit}>
                        用户名:<input onChange={this.saveUsername} type="text" name="username"  />
                        密码:<input onChange={this.savePassword} type="password" name="password"/>
                        <button>登录</button>
                        </form>
                )
            }
        }
        ReactDOM.render(<Login1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

4.react的生命周期

mount 挂载

unmount 卸载

记住,const声明的变量不能再改了

opacity可设置透明度,通过设置透明度可以实现由浅入深,由深入浅的效果。

组件挂载完毕

componentDidMount()

组件将要卸载

componentWillUnmount()

设置一个定时器

this.timer = setInterval(()=>{

},200);

卸载组件

ReactDOM.unmountComponentAtNode()

初始化渲染、状态更新之后

render()

1.Demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Life1 extends React.Component{
            state={
                opacity:1
            }
            death = () =>{
                ReactDOM.unmountComponentAtNode(document.getElementById('zzl'))
            }
            //挂载时
        componentDidMount(){ 
            this.timer = setInterval(()=>{
                //获取原状态
                let {opacity} = this.state
                opacity-=0.1
                if(opacity<=0) opacity=1
                this.setState({opacity})
            },200);
        }
        //组件将要卸载时
        componentWillUnmount(){
            clearInterval(this.timer)
        }
        render(){
            return (
                <div>
                    <h2 style={{opacity:this.state.opacity}}>学习react</h2>
                    <button onClick={this.death}>消失</button>
                    </div>
            )
        }
        }

        ReactDOM.render(<Life1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

效果
在这里插入图片描述

初始化阶段总结

执行顺序 constructor -> getDerivedStateFromProps 或者 componentWillMount -> render -> componentDidMount

更新阶段

在这里插入图片描述

2.DOM的diffing算法

以按秒记时的时间为例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        class Time1 extends React.Component{
            state = {date:new Date()}
            componentDidMount(){
                setInterval(()=>{
                    this.setState({date:new Date()})
                },1000)
            }
            render(){
                return (
                    <div>
                        <input type="text"/>
                        <span>时间是{this.state.date.toTimeString()}</span>
                        </div>
                )
            }
        }
        ReactDOM.render(<Time1/>,document.getElementById('zzl'))
    </script>
</body>
</html>

3.经典面试题

  1. react/vue中的key有什么作用?(key的内部原理是什么?)

  2. 为什么遍历列表时,key最好不要用index?

    • 1.简单来说,key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。

    • 在状态中的数据发生变化,react会根据新数据生成新的虚拟DOM,随后React进行新虚拟DOM旧虚拟DOM的diff比较

      比较规则:

      ​ a.旧虚拟DOM中找到了与新虚拟DOM相同的key:

      ​ 1.若虚拟DOM中内容没变,直接使用之前的真实DOM

      ​ 2.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

      b.旧虚拟DOM中未找到与新虚拟DOM相同的key,则会根据数据创建新的真实DOM,随后渲染到页面

      1. 1.若对数据进行:逆序添加、逆序删除等破坏顺序操作。

        ​ 会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。

        2.如果结构中还包含输入类的DOM:

        ​ 会产生错误DOM更新 ==> 界面有问题。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react</title>
</head>
<body>
    <script type="text/javascript" src="/js/react.development.js"></script>
    <script type="text/javascript" src="/js/react-dom.development.js"></script>
    <script type="text/javascript" src="/js/babel.min.js"></script>
    <script type="text/javascript" src="/js/prop-types.js"></script>
    <div id="zzl"></div>
    <script type="text/babel">
        /*
        慢动作回放----使用index索引值做为key

        初始数据:
                {id:1,name:'小张',age:18}
                {id:2,name:'小李',age:18}
        初始的虚拟DOM:
                <li key=0>小张---18</li>
                <li key=1>小李---19</li>
        更新后的数据:
                {id:3,name:'小王',age:18}
                {id:1,name:'小张',age:18}
                {id:2,name:'小李',age:18}

        更新数据后的虚拟DOM:
                <li key=0>小王---20</li>
                <li key=1>小张---20</li>
                <li key=2>小李---20</li>
--------------------------------------------------------
        慢动作回放----使用id索引值做为key

        初始数据:
                {id:1,name:'小张',age:18}
                {id:2,name:'小李',age:18}
        初始的虚拟DOM:
                <li key=1>小张---18</li>
                <li key=2>小李---19</li>
        更新后的数据:
                {id:3,name:'小王',age:18}
                {id:1,name:'小张',age:18}
                {id:2,name:'小张',age:18}

        更新数据后的虚拟DOM:
                <li key=3>小王---20</li>
                <li key=1>小张---20</li>
                <li key=2>小李---20</li>

                */
        class Person extends React.Component{
            state = {
                persons:[
                    {id:1,name:'小张',age:18},
                    {id:2,name:'小李',age:19}
                ]
            }

            add = () =>{
                const {persons} = this.state
                const p = {id:persons.length+1,name:'小王',age:20}
                this.setState({persons:[...persons,p]})
            }

            render(){
                return (
                    <div>
                        <h2>展示人员信息</h2>
                        <button onClick={this.add}>添加一个小王</button>
                        <ul>
                            {
                                this.state.persons.map((personObj,index)=>{
                                return <li key={index}>{personObj.name}---{personObj.age}</li>
                                })
                            }
                            </ul>
                            <hr/>
                            <ul>
                            {
                                this.state.persons.map((personObj)=>{
                                return <li key={personObj.id}>{personObj.name}---{personObj.age}</li>
                                })
                            }
                            </ul>
                        </div>
                )
            }
        }
        ReactDOM.render(<Person/>,document.getElementById('zzl'))
    </script>
</body>
</html>

📑文章末尾

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

听风与他

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

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

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

打赏作者

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

抵扣说明:

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

余额充值