Rendering components
A component must be rendered internally and returns a virtual DOM
This is the simplest component instance
const MyComponent = { // Component name, optional name: "MyComponent", // The rendering function of the component must be a virtual DOM render() { // Return to virtual DOM return { type: "div", children: `I'm text content`, }; }, };
The mountComponent function in the renderer completes the rendering of the component
function mountComponent(vnode, container, anchor) { // Get the component's option object through vnode, that is const componentOptions = ; // Get the render function of the component const { render } = componentOptions; // Execute the render function to get the content to be rendered by the component, that is, the virtual returned by the render function const subTree = render(); // Finally, call the patch function to mount the content described by the component, that is, subTree patch(null, subTree, container, anchor); }
Component update
Component initialization steps:
- After obtaining the data function, use reactive to turn it into a reactive
- In the render function, point this to state and pass state as the first parameter into the render function
Wrap the rendering task into a side effect function to achieve responsive update of data
To make the effect execute only once after each responsive data modification, the concept of a scheduler needs to be introduced.
This is the simplest scheduler example given in the book
That is, put the effect into the micro task queue first, wait until the execution stack is cleared before calling it out to execute
// Task cache queue, set can automatically dereloadconst queue = new Set(); // A flag that indicates whether the task queue is being refreshedlet isFlushing = false; // Create a Promise instance that resolves immediatelyconst p = (); // The main function of the scheduler is used to add a task to the buffer queue and start refreshing the queuefunction queueJob(job) { // Add job to the task queue (job); // If the queue has not started to be refreshed, refresh it if (!isFlushing) { // Set this flag to true to avoid repeated refreshes isFlushing = true; // Refresh the buffer queue in microtasks (() => { try { // Execute tasks in the task queue ((job) => job()); } finally { // Reset status isFlushing = false; = 0; } }); } }
Parent-child component
This is a simple parent-child component code
// Subcomponents<template> <MyComponent :title="title" /> </template> // Parent componentconst vnode = { type: MyComponent, props: { title: 'A Big Title' } }
Parent component update causes child component update (passive update) process:
- Parent component self-update
- The renderer checks that subTree finds that there is a vnode, and then calls patchComponent to achieve subcomponent update
setup function
The setup function is introduced in conjunction with the combination API
It has the following two return value forms
// Return functionconst comp = { setup() { return () => { return { type: "div", children: "give up for vuejs", }; }; }, }; // Return objectconst comp = { setup() { const count = ref(0); return { count, }; }, render() { return { type: "div", children: `count is ${}`, }; }, };
setup receives two parameters, namely props and setupContext
setupContext contains the following four main objects
- slots slots
- emit custom events
- attrs custom attributes
- expose
emit implementation
Just implement an emit function and add it to the setupContext object
This is the end of this article about the detailed analysis of the implementation principles of Vue components. For more related contents of implementation principles of Vue components, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!