React学习笔记

React学习笔记

1.React快速入门

主要分为3个步骤:
0.引入相关js文件
1.准备一个容器
2.创建虚拟DOM
3.将虚拟DOM渲染到容器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello_react</title>
</head>
<body>
    <!-- 准备好“容器” -->
    <div id="test"></div>
    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../react.development.js"></script>
    <!-- 引入react-DOM,用于支持react操作DOM -->
    <script type="text/javascript" src="../react-DOM.development.js"></script>
    <!-- 引入babel,将jsx转为js -->
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        //1.创建虚拟DOM
        const VDOM = <h1>Hello,React</h1>
        //2.渲染虚拟DOM到页面
        ReactDOM.render(VDOM,document.getElementById('test'))
    </script>
</body>
</html>

2.用jsx和js写虚拟DOM的区别

const JSXVDOM = <h1 id="title"><span>Hello,React</span></h1> 
const JSVDOM = React.createElement('h1',{id:'title'},React.createElement('span',{},'Hello,React'))

当出现标签嵌套的情况时,js的写法变得复杂起来,而jsx则是像写页面一样,故开发时选用jsx

3.虚拟DOM和真实DOM的区别

虚拟DOM的属性比真实DOM要少,在运行时更“轻便”。

4.jsx的语法规则

  1. 定义虚拟DOM时,不要写引号。
  2. 标签中混入js表达式时要用{}。
  3. 样式的类名指定不要用class,要用className。
  4. 内联样式,要用style={{key:value}}的形式写。
  5. 只有一个根标签。
  6. 标签必须闭合。
  7. 标签首字母
    (1)若小写字母开头,则将该标签转为html中同名元素,若html中无对应的同名元素,则报错。
    (2)若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。

一定注意区分【js语句(代码)】与【js表达式】

  1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
    下面这些都是表达式:
    (1)a
    (2)a+b
    (3)demo(1)
    (4)arr.map()
    (5)function test () {}
  2. 语句(代码):
    下面这些都是语句(代码):
    (1)if () {}
    (2)for () {}
    (3)switch () {case:xxxx}

5.React中定义组件

5.1函数式组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>函数式组件</title>
</head>
<body>
    <!-- 准备好“容器” -->
    <div id="test"></div>
    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作DOM -->
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转成js -->
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        //1.创建函数式组件
        function Demo(){
            console.log(this)
            return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
        }
        //2.渲染组件到页面
        ReactDOM.render(<Demo/>,document.getElementById('test'))
        
    </script>
</body>
</html>

函数式组件的返回值就是要渲染的内容。
函数式组件中的this为undefined,这是因为babel在翻译jsx时开启了严格模式,禁止自定义函数中的this指向window。

5.2类式组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2_类式组件</title>
</head>
<body>
    <!-- 准备好“容器” -->
    <div id="test"></div>
    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作DOM -->
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转成js -->
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        //1.创建函数式组件
        class MyComponent extends React.Component{
            render(){
                console.log('render中的this:',this)
                return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
            }
        }
        //2.渲染组件到页面
        ReactDOM.render(<MyComponent/>,document.getElementById('test'))
        
    </script>
</body>
</html>

定义类式组件需要继承React中的Component类,
并重写render()方法,React在渲染类式组件时会调用其中的render方法,其返回值就是渲染的内容。
render()和constructor()函数中的this就是实例对象,而其他的自定义函数中的this是undefine。
这是因为render()和constructor()函数是通过实例来调用,而其他自定义方法是直接调用,故取到的是window对象,而又因为babel翻译时开启了严格模式,取不到window,只能变成undefined。
解决方法是写成箭头函数,就能使用this取到实例对象。

6.组件实例的三大属性之state

标准写法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>state</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        class   Weather extends React.Component{
            constructor(props){
                super(props)
                this.state = {isHot:false}
                this.changeWeather = this.changeWeather.bind(this)
            }

            render(){
                const {isHot} = this.state
                return <h1 onClick={this.changeWeather}>今天天气很{isHot?'炎热':'凉快'}</h1>
            }

            changeWeather(){
                const isHot = this.state.isHot
                this.setState({isHot:!isHot})
            }
        }

        ReactDOM.render(<Weather/>,document.getElementById('test'))
    </script>
</body>
</html>

state的特殊之处在于在React的Component对象中有setState对象可以用来更新state中属性的值。

简化写法:
简化的地方在于state可以直接属性赋值,而调用setState的方法可以通过箭头函数来触发

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2_state的简写方式</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        class   Weather 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(<Weather/>,document.getElementById('test'))
    </script>
</body>
</html>

7.组件实例的三大属性之props

7.1props的基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1_props基本使用</title>
</head>
<body>
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>

    <script type="text/babel">
        class Person extends React.Component{
            render(){
                const {name,age,sex} = this.props
                return (
                    <ul>
                        <li>姓名:{name}</li>    
                        <li>性别:{sex}</li>    
                        <li>年龄:{age}</li>    
                    </ul>
                )
            }
        }

        ReactDOM.render(<Person name="小明" sex="男" age="20"/>,document.getElementById('test1'))
        ReactDOM.render(<Person name="小红" sex="女" age="17"/>,document.getElementById('test2'))
        ReactDOM.render(<Person name="小强" sex="男" age="18"/>,document.getElementById('test3'))


    </script>
</body>
</html>

props属性的特殊之处在于:在React渲染虚拟DOM时,通过组件标签传入的属性,能够被props接收。

7.2对props属性进行限制

需要引入一个prop-types.js文件,因为比较大所以没有放入核心库,在需要的时候再引入。
使用类名调用propTypes方法,传入属性类型的限制规则
使用类名调用defaultProps方法,传入属性默认值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2_对props进行限制</title>
</head>
<body>
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Person extends React.Component{
            render(){
                const {name,age,sex} = this.props
                return (
                    <ul>
                        <li>姓名:{name}</li>    
                        <li>性别:{sex}</li>    
                        <li>年龄:{age+1}</li>    
                    </ul>
                )
            }
        }

        Person.propTypes = {
            name:PropTypes.string.isRequired,//字符串类型,必要的属性(分别对应string,isRequired)
            age:PropTypes.number,//数字类型
            sex:PropTypes.string,
            speak:PropTypes.func//函数类型
        }
        Person.defaultProps = {
            sex:'男',
            age:18
        }

        ReactDOM.render(<Person name="小明"  speak={speak()} />,document.getElementById('test1'))
        ReactDOM.render(<Person name="小红" sex="女" age={17}/>,document.getElementById('test2'))
        ReactDOM.render(<Person name="小强" sex="男" age={18}/>,document.getElementById('test3'))

        function speak(){
            console.log('我说了一句话')
        }


    </script>
</body>
</html>

7.3props的简写方式

简化的地方在于:
将限制规则写在类中,将规则定义为类的属性,需要在propTypes、defaultProps 前面加static关键字,将其定义到类本身。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3_对props的简写方式</title>
</head>
<body>
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Person extends React.Component{
            static propTypes = {
                name:PropTypes.string.isRequired,
                age:PropTypes.number,
                sex:PropTypes.string,
                speak:PropTypes.func
            }
            static defaultProps = {
                sex:'男',
                age:18
            }
            render(){
                const {name,age,sex} = this.props
                return (
                    <ul>
                        <li>姓名:{name}</li>    
                        <li>性别:{sex}</li>    
                        <li>年龄:{age+1}</li>    
                    </ul>
                )
            }
        }
        ReactDOM.render(<Person name="小明"  speak={speak()} />,document.getElementById('test1'))
        ReactDOM.render(<Person name="小红" sex="女" age={17}/>,document.getElementById('test2'))
        ReactDOM.render(<Person name="小强" sex="男" age={18}/>,document.getElementById('test3'))

        function speak(){
            console.log('我说了一句话')
        }


    </script>
</body>
</html>

7.4函数式组件使用props

函数式组件由于没有实例对象无法使用三大对象的state、refs,但可以通过传参的方式得到props。
而设置props规则只能使用组件名.propTypes (defaultProps )的方式实现。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>4_函数式组件使用props</title>
</head>
<body>
    <div id="test1"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        function Person (props){
            const {name,age,sex} = props
            return (
                    <ul>
                        <li>姓名:{name}</li>    
                        <li>性别:{sex}</li>    
                        <li>年龄:{age+1}</li>    
                    </ul>
                ) 
        }
        Person.propTypes = {
            name:PropTypes.string.isRequired,
            age:PropTypes.number,
            sex:PropTypes.string,
        }
        Person.defaultProps = {
            sex:'男',
            age:18
        }
        ReactDOM.render(<Person name="小明" />,document.getElementById('test1'))
    </script>
</body>
</html>

8组件实例的三大属性之refs

8.1字符串形式的ref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1_字符串形式的ref</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Demo extends React.Component{
            render(){
                return (
                    <div>
                        <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
                        <input onClick={this.showData} type="button" value="点击显示左侧数据"/>
                        <input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点显示数据"/>
                    </div>
                )
            }
            
            showData = ()=>{
                const {input1} = this.refs
                // console.log(this)
                alert(input1.value)
            }

            showData2 = ()=>{
                const {input2} = this.refs
                alert(input2.value)
            }
        }

        ReactDOM.render(<Demo/>,document.getElementById('test'))
    </script>
</body>
</html>

refs的特殊之处在于:在render()函数中的标签可以设置一个ref属性,React在创建实例对象时会将有ref属性的标签会以{key:value}的方式存入对象上的refs属性上,其中key是ref属性名,value是标签本身。
举例:在上述代码中共设置了两个有ref属性的标签,他们在实例对象中大概是这样的:

demo实例对象{
			...其他属性
			refs{
				input1: <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
				input2: <input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点显示数据"/>
				}
			...其他属性
}

8.2回调函数形式的ref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2_回调函数形式的ref</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Demo extends React.Component{
            render(){
                return (
                    <div>
                        <input ref={(currentNode)=>{this.input1 = currentNode}} type="text" placeholder="点击按钮提示数据"/>
                        <input onClick={this.showData} type="button" value="点击显示左侧数据"/>
                        <input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点显示数据"/>
                    </div>
                )
            }

            showData = ()=>{
                const {input1} = this
                // console.log(this)
                alert(input1.value)
            }

            showData2 = ()=>{
                const {input2} = this
                alert(input2.value)
            }
        }

        ReactDOM.render(<Demo/>,document.getElementById('test'))
    </script>
</body>
</html>

回调函数(currentNode)=>{this.input1 = currentNode}中的currentNode是自定义的参数名,它的含义是
当前的标签本身。这段代码的含义是将当前节点直接挂载到实例对象上的input1属性。
举例:在上述代码中共设置了两个有ref属性的标签,他们在实例对象中大概是这样的:

demo实例对象{
			...其他属性
			input1: <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
			input2: <input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点显示数据"/>
			...其他属性
}

8.3回调ref中回调执行次数的问题

组件在创建时会执行一次回调ref,在更新组件时,会执行2次回调ref。其中第一次执行是清空当前节点,第二次是赋值。以下是测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3_回调ref中回调执行次数的问题</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Demo extends React.Component{
            render(){
                const {isHot} = this.state
                return (
                    <div>
                        <h1>今天天气真{isHot?'炎热':'凉快'}</h1>
                        <input ref={(currentNode)=>{this.input1 = currentNode,console.log('@',currentNode)}} type="text" placeholder="点击按钮提示数据"/>
                        <input onClick={this.showData} type="button" value="点击显示左侧数据"/><br/>
                        <input onClick={this.changeWeather} type="button" value="点击切换天气"/>
                    </div>
                )
            }
            state = {isHot:true}
            changeWeather = ()=>{
                const {isHot} = this.state
                this.setState({isHot:!isHot}) 
            }
            showData = ()=>{
                const {input1} = this
                alert(input1.value)
            }
        }

        ReactDOM.render(<Demo/>,document.getElementById('test'))
    </script>
</body>
</html>

8.4createref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>4_createRef</title>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript" src="../react.development.js"></script>
    <script type="text/javascript" src="../react-dom.development.js"></script>
    <script type="text/javascript" src="../babel.min.js"></script>
    <script type="text/javascript" src="../prop-types.js"></script>

    <script type="text/babel">
        class Demo extends React.Component{
            myRef = React.createRef()
            myRef2 = React.createRef()

            render(){
                return (
                    <div>
                        <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
                        <input onClick={this.showData} type="button" value="点击显示左侧数据"/>
                        <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦点显示数据"/>
                    </div>
                )
            }

            showData = ()=>{
                console.log(this.myRef)
                alert(this.myRef.current.value)
            }

            showData2 = ()=>{
                alert(this.myRef2.current.value)
            }
        }

        ReactDOM.render(<Demo/>,document.getElementById('test'))
    </script>
</body>
</html>

该方式是通过React.createRef()来创建一个容器,然后在标签中的ref属性来绑定该容器来使用。
该容器是专人专用,节点在容器中的current上。
举例:在上述代码中共设置了两个有ref属性的标签,他们在实例对象中大概是这样的:

demo实例对象{
			...其他属性
			myRef: {current: <input ref="input1" type="text" placeholder="点击按钮提示数据"/>}
			myRef2: {current: <input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点显示数据"/>}
			...其他属性
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值