手动封装 useState useEffect

852 阅读2分钟

前言

关于 react hooks 的优点,这里就不详细阐述了,大家可以去查看文档。 本文的主要重点是详细解释各种 hooks 的使用以及阐述一些简单的 hooks 实现来帮助我们理解 hooks。其中第一个 hooks 也是使用频率最高最重要的 Hooks 就是useState

useState的最大作用就是可以让你不编写class类组件的情况下使用state 。而useState的功能就是让你在函数式组件中使用 state。

话不多说上代码 这是单纯一个useState 的函数封装

let stateDate = []  // 用来存储函数组件中的数据(做缓存)
let Statei = 0 // 利用数组来保存数据 

function useState2(prop) { // 默认执行 第一次进行传参
    let createIndex = Statei
    // 判断 stateDate 数组上一次位置有没有数据 如果没有数据说明没有传参
    stateDate[createIndex] = stateDate[createIndex] ? stateDate[createIndex] : prop
    function setProp(newProp) { //   newProp 是通过调用 setCont 传递过来的值 
        // 改变数组中当前位置数据 stateDate[createIndex] 是上一次调用的值(初始值?)
        stateDate[createIndex] = newProp
        Statei = 0  // 加上初始值
        render()
    }
    Statei++ // 每修改一次 步长都要改变
    return [stateDate[createIndex], setProp] // 返回值是数组
}

useEffect 用于处理组件中的effect(副作用),通常用于请求数据,事件处理,订阅等相关操作。这里已监听数据变化为例,来浅封装useEffect的用法

单纯一个useEffect的函数封装

function useEffect2(callback, arr) { // callback 要执行的函数  arr 传入要被监听的数据
    let oldState = stateDate[Statei]  //  获取上一次调用的 stateDate 的值
    // 如果上一次调用有值 那么进行判断 数组去重后 的长度和要监听数据的长度是否一致 
    // oldState 上一次更改的值 === arr 监听的值 那么说明数据没有被更改
    let isChange = oldState ? [...new Set([...oldState, ...arr])].length !== arr.length : false
    if (!arr || isChange) { // 如果没有传参 或者是 监听数据被更改
        callback()
    }
    // 如果有下次调用此函数那么 缓存数组下标++
    stateDate[Statei++] = arr
}

利用react渲染虚拟DOM 进行构建页面

<script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.1/umd/react.development.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.1/umd/react-dom.development.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
<script type="text/babel">  // babel 编译
function App() {  // 渲染函数组件  hooks 写法 不用看浪费时间
    let [cont, setCont] = useState2(0)
    let [num, setNum] = useState2(5)
    useEffect2(() => {
        console.log('useEffect', 'cont');
    }, [cont])
    useEffect2(() => {
        console.log('useEffect', 'num');
    })
    return (
        <div>
            <p>conut:{cont}</p>
            <p><button onClick={
                () => {
                    setCont(cont) // 传入它本身代表数据没有被更改
                }
            }>++</button></p>
            <p>num:{num}</p>
            <p><button onClick={
                () => {
                    setNum(num + 1) // 数据更改
                }
            }>加加</button></p>
            虚拟
        </div>
    )
}

function render() {  // 渲染虚拟dom
    ReactDOM.render(
        <App />,
        document.getElementById('root')
    )
}

render()
</script>

页面视图

aa.jpg

附上cdn链接

react^17.0.1--| react-dom^17.0.1--| babel^7.0.0

---记录旅行遇到的事迹         仅用于旅行记录 欢迎志同道合的朋友