最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 我在react里写vue3 ,还写了自定义hooks和Hoc构建了响应式

    正文概述 掘金(我不是外星人)   2021-04-06   381

    前言

    自从vue3.0正式发布之后,vue3.0核心响应式部分被单独抽离成@vue/reactivity包,也就是说,我们可以脱离vue框架之外,单独使用@vue/reactivity做一些其他的愉快的事?,于是乎笔者突发奇想,为何不用@vue/reactivityreact中,构建响应式,省着每次调用this.setState,useState,直接通过改变state值,做到更新视图。

    ???说干就干,为了可以量化生产,复用逻辑,我在function组件中写了一个自定义hooks-useReactive ,在class组件中写了一个高阶组件reactiveHoc

    reactvue 是不是有点不讲武德呢?

    我在react里写vue3 ,还写了自定义hooks和Hoc构建了响应式

    实际写这篇文章的目的是:

    • 1 在重温一下vue3.0响应式原理,reactiveeffect
    • 2 如何编写一个响应式的自定义hooks,学会写自定义hook
    • 3 如何编写一个响应式的HOC,学会写hoc

    函数组件-自定义hooks - useReactive

    编写

    useReactive自定义hooks

    import { reactive, effect  } from '@vue/reactivity'
    import React, {  useRef , useEffect, useMemo, useState } from 'react'
    function useReactive (initState){
       const reactiveState = useRef(initState) // state 
       const [  ,forceUpdate ] = useState(0)
       const state = useMemo(()=> reactive(reactiveState.current)  ,[ reactiveState.current ]) 
       useEffect(()=>{
           let isdep = false
           effect(()=>{
               for(let i in state ){ state[i] } //依赖收集
               isdep && forceUpdate(num => num + 1)  // 强制更新
               if(!isdep) isdep = true
           })
       },[ state ])
       return state
    }
    

    思路:

    • ① 用useRef保存响应式对象,并构建响应式,为什么选择useRef,在函数组件执行更新中,只有Ref-Hooks一直使用的是原始对象,这之前的hooks原理中讲过。这样做的好处,防止函数组件更新时候,响应式对象丢失。
    • ② 用useMemo缓存响应式对象,当Ref对象被篡改,重新构建响应式。
    • ③ 用useEffect做响应式的依赖收集,用开关isdep,防止初始化@vue/reactivityeffect初始化执行时,引起的forceUpdate引发的,额外的组件更新。
    • ④ 用一个useState,做强制更新。
    • ⑤ 在effect对象中,for(let i in state ){ state[i] }遍历 Ref对象 ,做依赖收集。

    使用

    function Index(){
       const state = useReactive({ number:1  , name:'alien' })
       return <div className="box" >
           <div className="show" >
               <div> 你的姓名是: { state.name } </div>
               <div>{ new Array(state.number).fill(0).map(()=> '?') }</div>
           </div>
           <div className="constrol" >
                <div> <button onClick={ ()=> state.number++ } >?++</button> </div>
                <div> <button onClick={ ()=> state.number-- } >?--</button>  </div>
                <input placeholder="姓名" value={state.name}  onChange={ (e:any) =>  state.name = e.target.value   }  />       
           </div>
       </div>
    }
    

    效果

    我在react里写vue3 ,还写了自定义hooks和Hoc构建了响应式

    类组件-反向继承hoc-reactiveHoc

    function组件中,我们可以使用自定义hook,构建响应式; 那么在class类组件中,我们如何构建响应式呢,每次在业务组件中引进reactiveeffect,手动绑定,显然不是很切合实际,也不是我们的追求,这个时候,hoc高阶组件就派上用场了。我们接着往下看:

    编写

    reactiveHoc高阶组件

    import { reactive , effect  } from '@vue/reactivity'
    import React from 'react'
    function reactiveHoc(Component){
        const self_componentDidMount = Component.prototype.componentDidMount
        return class WrapComponent extends Component{
            constructor(props){
                super(props)
                this.state = reactive(this.state)
            }
            __isFirst = false
            componentDidMount(){
                effect(()=>{
                    for(let i in this.state ){ this.state[i] }  //构建响应式
                    this.__isFirst && this.forceUpdate()
                    !this.__isFirst && (this.__isFirst = true )     
                }) 
                self_componentDidMount && self_componentDidMount.call(this)
            }
        }
    }
    

    思路:

    • 为什么要选择反向继承模式 HOC 呢? ,因为我们可以通过一个反正继承的hoc,访问到内部的state状态,对于内部的state,进行reactive响应式处理。
    • ② 劫持类组件周期componentDidMount,在hoccomponentDidMount中同样做依赖收集。

    使用

    @reactiveHoc
    class Index extends React.Component{
        constructor(props){
            super(props)
            this.state={
                number:0,
                name:'alien'
            }
        }
        componentDidMount(){
            console.log(6666)
        }
        render(){
            const { state } :any= this
            return <div className="box" >
            <div className="show" >
                <div> 你的姓名是: { state.name } </div>
                <div>{ new Array(state.number).fill(0).map(()=> '?') }</div>
            </div>
            <div className="constrol" >
                 <div> <button onClick={ ()=> state.number++ } >?++</button> </div>
                 <div> <button onClick={ ()=> state.number-- } >?--</button>  </div>
                 <input placeholder="姓名" value={state.name}  onChange={ (e:any) =>  state.name = e.target.value   }  />       
            </div>
        </div>
        }
    }
    

    总结

    本文主要的目的并不是教大家在react@vue/reactivity构建响应式,可以当娱乐玩玩罢了,主要目的是结合上两篇文章,教大家更好编写自定义hookshoc。早日进阶react技术栈。

    最后, 送人玫瑰,手留余香,觉得有收获的朋友可以给笔者点赞,关注一波 ,陆续更新前端超硬核文章。

    如果文章中,有不明白地方,建议先看往期文章:

    react-hooks三部曲

    • 第一部: react-hooks如何使用 150+ 赞?

    • 第二部:玩转react-hooks,自定义hooks设计模式及其实战 225+ ?赞

    • 第三部:「react进阶」一文吃透react-hooks原理 730+ ?赞

    react-hoc

    • 「react进阶」一文吃透React高阶组件(HOC) 320+ 赞?

    vue3.0响应式原理

    • vue3.0响应式原理 250+ 赞?

    起源地下载网 » 我在react里写vue3 ,还写了自定义hooks和Hoc构建了响应式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元