Vue3源码解读之patch

例子代码

本篇将要讲解dom diff,那么咱们结合下面的例子来进行讲解,这个例子是在上一篇文章的基础上,加了一个数据变更,也就是list的值发生了改变。html中增加了一个按钮change,通过点击change按钮来调用change函数,来改变list的值。例子位于源代码/packages/vue/examples/classic/目录下,下面是例子的代码:

const app = Vue.createApp({
   
    data() {
   
        return {
   
            list: ['a', 'b', 'c', 'd']
        }
    },
    methods: {
   
        change() {
   
            this.list = ['a', 'd', 'e', 'b']
        }
    }
});
app.mount('#demo')
DOCTYPE html>
<html>
<head>
    <meta name="viewport"
          content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no,target-densitydpi=medium-dpi,viewport-fit=cover"
    />
    <title>Vue3.js hello exampletitle>

    <script src="../../dist/vue.global.js">script>
head>
<body>
<div id="demo">
    <ul>
        <li v-for="item in list" :key="item">
            {
  {item}}
        li>
    ul>
    <button @click="change">changebutton>
div>
<script src="./hello.js">script>
body>
html>

源码解读

关于Vue3中数据发生变更,最终影响到页面发生变化的过程,我们本篇文章只对componentEffect以及以后的代码进行讲解,对于数据变更后,是如何执行到componentEffect函数,以及为何会执行componentEffect,后面的文章再进行讲解。

componentEffect

来看下componentEffect更新部分的代码:

参考Vue3源码视频讲解:进入学习

  // @file packages/runtime-core/src/renderer.ts
  function componentEffect() {
   
    if (!instance.isMounted) {
   
        // first render
    } else {
   
        let {
   next, bu, u, parent, vnode} = instance
        let originNext = next
        let vnodeHook: VNodeHook | null | undefined

        if (next) {
   
            updateComponentPreRender(instance, next, optimized)
        } else {
   
            next = vnode
        }
        next.el = vnode.el

        // beforeUpdate hook
        if (bu) {
   
            invokeArrayFns(bu)
        }
        // onVnodeBeforeUpdate
        if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {
   
            invokeVNodeHook(vnodeHook, parent, next, vnode)
        }
        const nextTree = renderComponentRoot(instance)
        const prevTree = instance.subTree
        instance.subTree = nextTree

        if (instance.refs !== EMPTY_OBJ) {
   
            instance.refs = {
   }
        }
        patch(
            prevTree,
            nextTree,
            hostParentNode(prevTree.el!)!,
            getNextHostNode(prevTree),
            instance,
            parentSuspense,
            isSVG
        )
        next.el = nextTree.el

你可能感兴趣的:(vue.js)