Hi everyone, this is Kasong.
I'm fine on the weekend, so I'm ready to find an excellent library with a small amount of code to learn from. Finally, I chose the recently released petite-vue for the following reasons:
- The amount of code is small (only 5.8kb), and the source code is highly modular (compared to
React
), easy to read - Build based on
Vite
, executeyarn dev
to start debugging the source code - There is no
virtual DOM and compile-time solution, which can be used as a basis for reading the source code of
Vue
- The underlying responsive update principle is also applicable to
Mobx
,SolidJS
etc., reading multiple copies at a time
It was decided that it was him.
But weekend time is so precious, and I haven't used Vue
in 4 years, how can I learn the source code efficiently?
Best in without looking at the source code of the source learned .
Next, I use petite-vue
as an example to demonstrate the correct posture for learning the source code.
How come how soon
It can petite-vue
understood as: The real DOM
replace Vue
template simple Vue
.
For example, Demo
as follows:
<script type="module">
import { createApp } from '../src'
createApp({count: 0}).mount()
</script>
<div v-scope>
<button @click="count++">add 1</button>
<p>{{count}}</p>
</div>
div
and its descendants are the real DOM
tags, so the page is initialized as follows:
Then execute the following code to complete the initialization of petite-vue
createApp({count: 0}).mount()
At this time page:
When reading the source code of the framework, you should not debug it all the way from the entry function as soon as you get started. It is easy to get confused. The correct way is to peel it layer by layer like an onion:
So, let us take a look at the call stack of first screen rendering Performance
The call stack is roughly divided into two parts: the blue box and the red box. First look at the blue box on the left:
Judging by the createContext
and reactive
probably to create a responsive context. As for
response, we are still unclear.
Then look at the red box on the right:
From the depth of the call stack and the effect of page rendering, we guess that the work done in this part includes:
- Traverse
DOM
- Complete the two-way binding of data and view
- Initial rendering
Next, let's verify the conjecture.
Note that so far, we haven't read a line of source code yet
Verify traversal of the DOM
In the call stack, walk
and walkChildren
been called many times. There is a high probability that they are the specific traversal work execution method, let us confirm.
In the source walk
marked method log
:
export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
console.log('walk', node);
// ...
}
Excluding the text node corresponding to the line break "\n "
, the printing order is as follows:
walk div
walk <button>add 1</button>
walk "add 1"
walk <p>0</p>
walk "0"
From the printed results, this is a depth-first traversal (if there are child nodes, traverse the child nodes, and if there are no child nodes, traverse the sibling nodes)
Obviously, petite-vue
mount
When using depth-first traversal each associated with, and traverse to the context state associated DOM
node for processing.
In Demo
, the context contains the state {count: 0}
:
createApp({count: 0}).mount()
After traversing, <p>{{count}}</p>
becomes <p>0</p>
.
Determine the granularity of two-way binding
Next we need to confirm the scope of two-way binding, namely:
After the update is triggered, what range ofDOM
will be traversed again and the correspondingDOM
operation will be executed?
After opening Performance
, click <button>add 1</button>
trigger the update:
As you can see, there is no walk
, walkChildren
(or similar traversal process), and only reactiveEffect
is called to update DOM
.
This means mount
depth-first traversal of the establishment of state
one relationship between the method of updating the DOM.
Because the corresponding relationship is determined, no additional traversal process is needed to determine the DOM
that needs to be changed.
After updating the status, you only need to find the
update the DOM method and execute it.
For example: link the count
state with the following function:
function setCount(value) {
p.textContent = value;
}
Whenever count
changes, call setCount(count)
to update p
corresponding to DOM
.
Therefore, petite-vue
mainly includes two points:
mount
depth-first traversalDOM
, for statefulDOM
(such as<p>{{count}}</p>
) to establish a one-to-one correspondence between thestate and the
method of updating the DOM
update
found that whenstate corresponding
Method and performs DOM
It can be seen that even if you don't go deep into the source code, you can get a general understanding of the workflow.
If you want to go further, such as understanding how the relationship is established (involving responsive update ), then you need to go deep into the source code.
It is recommended Vue Mastery
of Vue 3 Reactivity
course, can be filled responsive update this knowledge.
to sum up
This article introduces how to read the source code of a complex framework-from abstract to concrete.
- From
mount
when theupdate
call stack when derivedoverall workflow
- Discover the core knowledge from the overall work process
After mastering the overall work flow and
responsive update, you can read the part you are interested in so that you will not fall into the huge amount of code.
Have you lost your studies?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。