React的基础知识(超详细)

React

React基础之ref的三种书写方式

1.字符串形式的ref(官方将要弃用)

<body>
    <div id="test"></div>
    <script type="text/babel">
        // 创建组件
        class Demo extends React.Component {
            showDate = () =>{
                let {input1} = this.refs
                alert(input1.value)
            }

            showDate2 = () =>{
                let {input2} = this.refs
                alert(input2.value)
            }

            render() {
                return(
                    <div>
                        <input ref="input1" type="text" placeholder="点击按钮提示信息"/>
                        <button onClick={this.showDate}>点我</button>
                        <input ref="input2" type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
                    </div>
                )
            }
        }
        // 渲染到页面上
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

2.回调形式的ref

<body>
    <div id="test"></div>

    <script type="text/babel">
        // 创建组件
        class Demo extends React.Component {
            showDate = () =>{
                let {input1} = this
                alert(input1.value)
            }

            showDate2 = () =>{
                let {input2} = this
                alert(input2.value)
            }

            render() {
                return(
                    <div>
                        <input ref={ c => this.input1 = c } type="text" placeholder="点击按钮提示信息"/>
                        <button onClick={this.showDate}>点我</button>
                        <input ref={ c => this.input2 = c } type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
                    </div>
                )
            }
        }
        // 渲染到页面上
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

3.createRef创建ref容器(官方最推荐的一种)

<body>
    <div id="test"></div>

    <script type="text/babel">
        // 创建组件
        class Demo extends React.Component {
            /*
                React.createRef调用后可以返回一个容器,容器可以存储被ref所标识的节点,该容器是“专人专用”的
                1.通过onXxx属性指定事件处理函数(注意大小写)
                    a.React使用的是自定义(合成)事件,而不是使用的原生DOM事件. 为了更好的兼容性
                    b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素), 为了的高效
                2.通过event.target得到发生事件的DOM元素对象,不要过度使用ref
            */
            myRef1 = React.createRef()
            myRef2 = React.createRef()

            showDate = () =>{
                alert(this.myRef1.current.value)
            }

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

            render() {
                return(
                    <div>
                        <input ref={ this.myRef1 } type="text" placeholder="点击按钮提示信息"/>
                        <button onClick={this.showDate}>点我</button>
                        <input ref={ this.myRef2 } type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
                    </div>
                )
            }
        }
        // 渲染到页面上
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

注意:因为ref很消耗内存, 所以不要过度使用ref! 不要过度使用ref! 不要过度使用ref!

React基础之dangerouslySetInnerHTML 和 Child

1.Child

  1. React.Children 是顶层API之一,为处理 this.props.children 这个封闭的数据结构提供了有用的工具。

  2. this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。

<body>
    <div id="test"></div>

    <script type="text/babel">
        /*
            React.Children 是顶层API之一,为处理 this.props.children 这个封闭的数据结构提供了有用的工具。
            this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。
        */

        class Child extends React.Component {
            render(){
                console.log(this)
                return <div></div>
            }
        }

        class Demo extends React.Component {

            render() {
                return(
                    <div>
                        <Child>
                            <h1>今天的天气阴了</h1>
                            <h1>明天的天气不知道</h1>
                        </Child>    
                    </div>
                )
            }
        }
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

效果:

React的基础知识(超详细)_第1张图片

2.dangerouslySetInnerHTML

<body>
    <div id="test"></div>

    <script type="text/babel">
        let message = `
            

夏天真好

又亮又白

` class Demo extends React.Component { render() { return( <div dangerouslySetInnerHTML={{ __html:message }}> </div> ) } } ReactDOM.render(<Demo/>, document.getElementById("test")) </script> </body>

效果:

React的基础知识(超详细)_第2张图片

React基础之PureComponent

Component的2个问题

  1. 只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低
  2. 只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据 ==> 效率低

效率高的做法

只有当组件的state或props数据发生改变时才重新render()

原因

Component中的shouldComponentUpdate()总是返回true

解决

办法1: 
	重写shouldComponentUpdate()方法
	比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
办法2:  
	使用PureComponent
	PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
	
项目中一般使用PureComponent来优化
注意:
1.只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
2.不要直接修改state数据, 而是要产生新数据

React基础之非受控组件和受控组件

1.非受控组件

<body>
    <div id="test"></div>

    <script type="text/babel">
        // 非受控组件性质, 现用现取, 什么时候用, 什么时候取

        // 创建组件
        class Demo extends React.Component {
            dain = (event) =>{
                event.preventDefault(); // 阻止表单提交
                let {username,password} = this
                alert(`你的用户名是:${username.value}, 你的密码是: ${password.value}`)
            }

            render() {
                return(
                    <form onSubmit={this.dain}>
                        用户名: <input ref={c => this.username = c} type="text" name="username"/>    
                        密码: <input ref={c => this.password = c} type="password" name="password"/>    
                        <button>登录</button>
                    </form>
                )
            }
        }
        // 渲染到页面上
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

2.受控组件, 类似于vue中的 v-model

<body>
    <div id="test"></div>
	// 类似于vue中的 v-model
    <script type="text/babel">
        // 创建组件
        class Demo extends React.Component {
            // 初始化状态
            state = {
                username:'',
                password:''
            }

            // 保存用户名到状态中
            username = (event) =>{
                this.setState({username:event.target.value})
            }

            // 保存密码到状态中
            password = (event) =>{
                this.setState({password:event.target.value})
            }

            dain = (event) =>{
                event.preventDefault(); // 阻止表单提交
                let {username,password} = this.state
                alert(`你的用户名是:${username}, 你的密码是: ${password}`)
            }

            render() {
                return(
                    <form onSubmit={this.dain}>
                        用户名: <input onChange={this.username} type="text" name="username"/>    
                        密码: <input onChange={this.password} type="text" name="password" name="password"/>    
                        <button>登录</button>
                    </form>
                )
            }
        }
        // 渲染到页面上
        ReactDOM.render(<Demo/>, document.getElementById("test"))
    </script>
</body>

React基础之Hooks

1.React Hook/Hooks是什么?

1)Hook是React 16.8.0版本增加的新特性/新语法

2)可以让你在函数组件中使用 state 以及其他的 React 特性

2.三个常用的Hook

1). State Hook: React.useState()

2). Effect Hook: React.useEffect()

3). Ref Hook: React.useRef()

3.State Hook

1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
2). 语法: const [xxx, setXxx] = React.useState(initValue)  
3). useState()说明:
        参数: 第一次初始化指定的值在内部作缓存
        返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
4). setXxx()2种写法:
        setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
        setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
案例:
import React,{Component} from 'react';

function Dome(){
    const [count,setCount] = React.useState(0)

    // 加的回调
    function add(){
        // setCount(count+1) // 第一种写法
        setCount(count => count+1)
    }

    return(
        <div>
            <h1>当前求和为: {count}</h1>
            <button onClick={add}>点我</button>
        </div>
    )
}

export default Dome

4.Effect Hook

1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
2). React中的副作用操作:
        发ajax请求数据获取
        设置订阅 / 启动定时器
        手动更改真实DOM
3). 语法和说明: 
        useEffect(() => { 
          // 在此可以执行任何带副作用操作
          return () => { // 在组件卸载前执行
            // 在此做一些收尾工作, 比如清除定时器/取消订阅等
          }
        }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
    
4). 可以把 useEffect Hook 看做如下三个函数的组合
        componentDidMount()
        componentDidUpdate()
    	componentWillUnmount() 
案例:
import React,{Component} from 'react';
import ReactDOM from 'react-dom';

function Dome(){
    const [count,setCount] = React.useState(0)

    React.useEffect(()=>{
        let timer = setInterval(()=>{
            setCount(count => count+1)
        },1000)
        return ()=>{  // 这里的return就相当于componentWillUnmount() 
            clearInterval(timer)
        }
    },[]) // 这里加上一个数组([]),就相当于 componentDidMount()
          // 如果你在里面写属性了,他就会监听你写入的属性, 这是就相当于 componentDidUpdate()

    // 加的回调
    function add(){
        // setCount(count+1) // 第一种写法
        setCount(count => count+1) // 第二种写法
    }

    // 卸载组件的回调
    function unmount(){
        ReactDOM.unmountComponentAtNode(document.getElementById('root'));
    }

    return(
        <div>
            <h1>当前求和为: {count}</h1>
            <button onClick={add}>点我</button>
            <button onClick={unmount}>点击卸载组件</button>
        </div>
    )
}

export default Dome

5.Ref Hook

1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
2). 语法: const refContainer = useRef()
3). 作用:保存标签对象,功能与React.createRef()一样
案例:
import React,{Component} from 'react';

function Dome(){
    // Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
    // 作用:保存标签对象,功能与React.createRef()一样
    const myRef = React.useRef()

     // 提示输入的回调
     function show(){
       alert(myRef.current.value);
    }

    return(
        <div>
            <input type="text" ref={myRef}/>
            <button onClick={show}>点击提示数据</button>
        </div>
    )
}

export default Dome

6.自定义Hooks函数

自定义Hooks 函数 和 用Hooks 创建组件很相似,跟我们平时用 JavaScript 写函数几乎一模一样,

可能就是多了些 React Hooks 的特性,自定义 Hooks 函数偏向于功能,而组件偏向于界面和业务逻辑。

案例:自定义Hooks 函数获取窗口大小
import React,{useState,useEffect,useCallback} from 'react'
 
function useWinSize(){
    const [size,setSize] = useState({  // 先用useState设置size状态
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })
 
    // 编写一个每次修改状态的方法 onResize
    const onResize = useCallback( // 使用callback,目的是为了缓存方法(useMemo是为了缓存变量)
        () => {
           setSize({
               width:document.documentElement.clientWidth,
               height:document.documentElement.clientHeight
           })
        },
        [],
    )
 
    // 在第一次进入方法时使用useEffect 来注册 resize 监听事件
    useEffect(() => {
        window.addEventListener('resize:',onResize)
        return () => {
            // 为了防止一直监听,在方法移除时,使用return 的方式移除监听
            window.removeEventListener('resize:',onResize) 
        }
    }, [])
    // 最后返回size变量
    return size; 
}
 
// 编写组件并使用自定义函数
function HWinsize(){
    const size=useWinSize()
    return(
        <div>
            页面size:{size.width} x {size.height}
        </div>
    )
}
export default HWinsize;

注意:

1. React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是唯一的

2.因为ref很消耗内存, 所以不要过度使用ref! 不要过度使用ref! 不要过度使用ref!

3.PureComponent的注意点:

    1) 只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false

    2) 不要直接修改state数据, 而是要产生新数据


总结

本篇文章主要介绍了React的 ref,dangerouslySetInnerHTML和Child,PureComponent,非受控组件和受控组件,Hooks , 其中的注意点作者已经在上面标明了, 最后我想说知识从来不是看看就会的,要多实践,多敲代码.
喜欢文章的可以三连一下

你可能感兴趣的:(React,react,javascript,前端,js)