• vue diff 算法学习


    之前跟着视频教程写过一遍虚拟dom的生成和diff 算法, vue 的虚拟dom 来自于 snabbdom 这个库, github代码仓库, 现在重新回顾一遍

    diff 算法是干啥的

    首先要知道 diff 算法到底是用来干什么的? diff 算法不是在两个集合里寻找不同的元素的, 而是找到符合你判断逻辑的相同虚拟节点。比如:vue里面的 sameNode,下面有代码 ;找到相同虚拟节点之后,执行 patch 逻辑, 这里的patch 是 vue 里面的dom操作 , 这里的sameNode匹配只是判断最外层vnode是否相同, 内部还需要 patch 函数进行操作

    diff 算法执行的逻辑

    匹配逻辑, 这里的匹配逻辑使用了多个指针一起走, 每一次循环都会执行一次下面的逻辑, 一次循环走过以后, 对应的下标也会改变, 这里注意下标的改变跟命中逻辑有关
    在这里插入图片描述

    //  diff 算法是用来寻找相同元素进行patch的
          // 下面的方法没有处理边界,
          // 比如你的新标签要比旧的多, 那就需要 diff算法结束后进行一次处理, 把剩余的新标签元素插入到dom中去,
          // 你的新标签如果比旧的少, 那就可能需要你删掉相应的标签
    
          const sameNode = (newNode, node) => {
            return node.key == newNode.key && node.tag === newNode.tag
          }
          const map = new Map()
    
          const arr = [
            { key: 1, tag: 'div' },
            { key: 2, tag: 'div' },
            { key: 5, tag: 'div' },
            { key: 4, tag: 'div' }
          ]
    
          const arr2 = [
            { key: 1, tag: 'div' },
            { key: 2, tag: 'div' },
            { key: 5, tag: 'div' },
            { key: 6, tag: 'div' }
          ]
    
          let startIndex = 0
          let endIndex = arr.length - 1
          let nStartIndex = 0
          let nEndIndex = arr2.length - 1
    
          //命中才能改变当前下标,
          while (startIndex <= endIndex && nStartIndex <= nEndIndex) {
            const item = arr[startIndex]
            const endItem = arr[endIndex]
            const nItem = arr2[nStartIndex]
            const nEndItem = arr2[nEndIndex]
    
            // 新前和旧前的值相等
            if (sameNode(nItem, item)) {
              startIndex++
              nStartIndex++
              console.log('命中了=>现在是新前===旧前', nItem, item)
            } else if (sameNode(nEndItem, endItem)) {
              nEndIndex--
              endIndex--
              console.log('命中了=>现在是新后===旧后', nEndItem, endItem)
            } else if (sameNode(nEndItem, item)) {
              startIndex++
              nEndIndex--
              console.log('命中了=>现在是新后===旧前', nEndItem, item)
            } else if (sameNode(nItem, endItem)) {
              endIndex--
              nStartIndex++
              console.log('命中了=>现在是新前===旧后', nItem, endItem)
            } else {
              console.log('sdfsdfsdfsdf')
              if (map.length === 0) {
                arr.forEach((item, index) => {
                  map.set(item.key, index)
                })
              }
    
              // 匹配有没有命中的元素
              const index = map.get(arr2[nStartIndex].key)
    
              if (index) {
                console.log('最后一个循环找到了,执行patch')
              } else {
                console.log(
                  '直接把旧标签用新的替换掉',
                  `${arr2[nStartIndex].key}${arr2[nStartIndex].tag}`
                )
              }
    
              nStartIndex++
            }
          }
    

    解释:

    1. sameNode

    const sameNode = (vnode, newVnode)=>{
    return vnode.key == newVnode.key && vnode.tag === newVnode.tag
    }
    

    推荐去这视频看一遍教程, 就能好好理解虚拟dom和diff算法了

  • 相关阅读:
    Java8 Optional使用方式
    ABAC框架-casbin
    Java数据脱敏(手机号|邮箱号|身份证号|银行卡号)
    使用OpenOffice将office文件转为pdf
    在线审批流设计
    Java 将带逗号的字符串转为List
    Java8 lambda常用操作
    Markdown合并单元格
    本博客已搬迁至rcst.xyz
    涂色(题解)
  • 原文地址:https://www.cnblogs.com/shiazhen/p/16322050.html
Copyright © 2020-2023  润新知