• React中的Fiber更新机制如何执行的setState


    一、认识链表

    概率:链表是一种物理存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

    1、实现一个单链表

    /** 链表节点类*/
    class Node{
        constructor(val){
            this.val = val		//节点所存值
            this.next = null    //指针,指向下一个节点
        }
    }
    /** 链表类*/
    class LinkList{
        constructor(){
            this.head = null    //链表头
            this.length = 0		//链表长度
        }
    	/** 新增节点并加入链表*/
        add(val){
            let node = new Node(val)   
            if(this.head == null){      //若表头为空,则将节点放入表头
                this.head = node
                this.length++
            }else{
                let current = this.head
                while(current.next){      //循环,直到链表的指针为空
                    current = current.next
                }
                current.next = node
                this.length++
            }
    
        }
    }
    
    
    let list1 = new LinkList()
    
    list1.add(1)
    list1.add(2)
    list1.add(3)
    list1.add(4)
    console.log(list1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2、输出结果如下:链表结果
    在这里插入图片描述

    二、setState 状态更新机制

    疑问:
    1、setState是同步还是异步?
    2、setState为何可以传对象又可以传一个函数?

    接下来解决这些疑问:

    函数setState调用关系主要分为以下两个部分:
    1、将要更新的状态添加到更新队列中;
    2、产生一个调度任务。调度任务会遍历更新队列并计算出最终要更新的状态,将其更新到组件实例中,然后完成组件渲染操作。

    1、将要更新的状态添加到更新队列中,看看代码的实现

    class Queue{
        constructor(payload){
            this.payload = payload
            this.nextNode = null
        }
    }
    
    
    class ListQueue{
        constructor(){
            this.firstNode = null   //链表头
            this.lastNode =null		//链表尾
            this.initState = {}		//初始值
        }
    	//	将每一个setState任务加入链表队列中
        enqueue(queue){
            if(this.firstNode ==null){
                this.firstNode = this.lastNode =queue
            }else{
                this.lastNode.nextNode = queue
                this.lastNode = queue
            }
        }
    }
    
    let listQueue =new ListQueue()
    
    
    listQueue.enqueue(new Queue({num:1}))
    listQueue.enqueue(new Queue({num:2}))
    listQueue.enqueue(new Queue((state)=>{state.num++}))
    listQueue.enqueue(new Queue({id:5}))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    2、调度任务遍历更新队列

    class ListQueue{
        constructor(){
            this.firstNode = null
            this.lastNode =null
            this.initState = {}
        }
    
        enqueue(queue){
            if(this.firstNode ==null){
                this.firstNode = this.lastNode =queue
            }else{
                this.lastNode.nextNode = queue
                this.lastNode = queue
            }
        }
    	
    	//调度更新方法
        forceUpdate(){
            let current = this.firstNode
            let currentState = this.initState
            while(current){   //依次取出每一个节点值  更新
                let updateState = typeof current.payload =='function'?current.payload(currentState):current.payload   //判断对象还是函数
                currentState ={...currentState,...updateState
                }    //覆盖原来值
                current = current.nextNode
            }
            return currentState
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    3、最后执行一下listQueue.forceUpdate()就可以将state中的值改变了

  • 相关阅读:
    5G投资下降,遥遥领先的主流5G或被运营商抛弃,“假5G”更获青睐
    【实践篇】Redis最强Java客户端(一)之Redisson入门介绍
    LeetCode刷题复盘笔记——51. N 皇后(一文搞懂回溯解决经典的N皇后问题上篇)
    数据库管理-第157期 Oracle Vector DB & AI-08(20240301)
    网络ip地址冲突会出现什么情况
    人工智能 AI 概念梳理
    突破编程_C++_面试(模板编程(3))
    实用,eBay账号关联问题该如何解决?
    【Linux operation 44】Linux(red hat)查看看内核版本方法
    计蒜客T1777 蜗牛爬行(C语言实现)
  • 原文地址:https://blog.csdn.net/weixin_42662753/article/details/127636668