Skip to content

Commit

Permalink
实现nextTick
Browse files Browse the repository at this point in the history
  • Loading branch information
jindy committed Jun 18, 2022
1 parent 496b02a commit de2bd59
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 24 deletions.
31 changes: 31 additions & 0 deletions example/NextTick/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

import { h, ref, nextTick, getCurrentInstance } from '../../lib/guide-mini-vue.esm.js'
export const App = {
name: 'App',
setup() {
const count = ref(1)
const instance = getCurrentInstance()
function onClick() {
for (let index = 0; index < 100; index++) {
console.log('update')
count.value = index
}
}

console.log('111', instance)
nextTick(() => {
console.log('222', instance)
})

return {
count,
onClick,
}
},
render() {
const btn = h('button', { onClick: this.onClick }, 'update')
const p = h('p', {}, 'count:' + this.count)
return h('div', {}, [btn, p]
)
}
}
16 changes: 16 additions & 0 deletions example/NextTick/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>component update</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="./main.js"></script>
</body>

</html>
6 changes: 6 additions & 0 deletions example/NextTick/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import { createApp } from '../../lib/guide-mini-vue.esm.js'
import { App } from './App.js'

const rootContainer = document.querySelector('#app')
createApp(App).mount(rootContainer)
32 changes: 32 additions & 0 deletions lib/guide-mini-vue.cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,32 @@ function createAppAPI(render) {
};
}

const queue = [];
let isFlushPending = false;
const p = Promise.resolve();
function queueJobs(job) {
if (!queue.includes(job)) {
queue.push(job);
}
queueFlush();
}
function nextTick(fn) {
return fn ? p.then(fn) : p;
}
function queueFlush() {
if (isFlushPending)
return;
isFlushPending = true;
nextTick(flushJobs);
}
function flushJobs() {
isFlushPending = false;
let job;
while ((job = queue.shift())) {
job && job();
}
}

function shouldUpdateComponent(prevVNode, nextVNode) {
const { props: prevProps } = prevVNode;
const { props: nextProps } = nextVNode;
Expand Down Expand Up @@ -513,6 +539,11 @@ function createRenderer(options) {
instance.subTree = subTree;
patch(prevSubTree, subTree, container, instance, anchor);
}
}, {
scheduler() {
console.log("scheduler - update");
queueJobs(instance.update);
},
});
}
function processElement(n1, n2, container, parentComponent, anchor) {
Expand Down Expand Up @@ -862,6 +893,7 @@ exports.createTextVNode = createTextVNode;
exports.getCurrentInstance = getCurrentInstance;
exports.h = h;
exports.inject = inject;
exports.nextTick = nextTick;
exports.provide = provide;
exports.proxyRefs = proxyRefs;
exports.ref = ref;
Expand Down
33 changes: 32 additions & 1 deletion lib/guide-mini-vue.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,32 @@ function createAppAPI(render) {
};
}

const queue = [];
let isFlushPending = false;
const p = Promise.resolve();
function queueJobs(job) {
if (!queue.includes(job)) {
queue.push(job);
}
queueFlush();
}
function nextTick(fn) {
return fn ? p.then(fn) : p;
}
function queueFlush() {
if (isFlushPending)
return;
isFlushPending = true;
nextTick(flushJobs);
}
function flushJobs() {
isFlushPending = false;
let job;
while ((job = queue.shift())) {
job && job();
}
}

function shouldUpdateComponent(prevVNode, nextVNode) {
const { props: prevProps } = prevVNode;
const { props: nextProps } = nextVNode;
Expand Down Expand Up @@ -509,6 +535,11 @@ function createRenderer(options) {
instance.subTree = subTree;
patch(prevSubTree, subTree, container, instance, anchor);
}
}, {
scheduler() {
console.log("scheduler - update");
queueJobs(instance.update);
},
});
}
function processElement(n1, n2, container, parentComponent, anchor) {
Expand Down Expand Up @@ -852,4 +883,4 @@ function createApp(...args) {
return renderer.createApp(...args);
}

export { createApp, createRenderer, createTextVNode, getCurrentInstance, h, inject, provide, proxyRefs, ref, renderSlots };
export { createApp, createRenderer, createTextVNode, getCurrentInstance, h, inject, nextTick, provide, proxyRefs, ref, renderSlots };
1 change: 1 addition & 0 deletions src/runtime-core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { createTextVNode } from "./vnode"
export { getCurrentInstance } from "./component"
export { provide, inject } from "./apiProvide"
export { createRenderer } from "./renderer"
export { nextTick } from "./scheduler"
53 changes: 31 additions & 22 deletions src/runtime-core/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EMPTY_OBJ } from "../shared"
import { ShapeFlags } from "../shared/ShapeFlags"
import { createComponentInstance, setupComponent } from "./component"
import { createAppAPI } from "./createApp"
import { queueJobs } from "./scheduler"
import { shouldUpdateComponent } from "./shouldUpdateComponentUtils"
import { Fragment, Text } from "./vnode"

Expand Down Expand Up @@ -74,33 +75,41 @@ export function createRenderer(options) {
}

function setupRenderEffect(instance: any, initialVNode, container, anchor) {
instance.update = effect(() => {
if (!instance.isMounted) {
console.log("init")
const { proxy } = instance
instance.update = effect(
() => {
if (!instance.isMounted) {
console.log("init")
const { proxy } = instance

const subTree = (instance.subTree = instance.render.call(proxy))
const subTree = (instance.subTree = instance.render.call(proxy))

patch(null, subTree, container, instance, anchor)
patch(null, subTree, container, instance, anchor)

//只有当全部的element渲染完毕,才能获取到el
initialVNode.el = subTree.el
instance.isMounted = true
} else {
console.log("update")
const { next, vnode } = instance
if (next) {
next.el = vnode.el
updateComponentPreRender(instance, next)
}
//只有当全部的element渲染完毕,才能获取到el
initialVNode.el = subTree.el
instance.isMounted = true
} else {
console.log("update")
const { next, vnode } = instance
if (next) {
next.el = vnode.el
updateComponentPreRender(instance, next)
}

const { proxy } = instance
const subTree = instance.render.call(proxy)
const prevSubTree = instance.subTree
instance.subTree = subTree
patch(prevSubTree, subTree, container, instance, anchor)
const { proxy } = instance
const subTree = instance.render.call(proxy)
const prevSubTree = instance.subTree
instance.subTree = subTree
patch(prevSubTree, subTree, container, instance, anchor)
}
},
{
scheduler() {
console.log("scheduler - update")
queueJobs(instance.update)
},
}
})
)
}

function processElement(
Expand Down
27 changes: 27 additions & 0 deletions src/runtime-core/scheduler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const queue: any[] = []
let isFlushPending = false
const p = Promise.resolve()
export function queueJobs(job) {
if (!queue.includes(job)) {
queue.push(job)
}
queueFlush()
}

export function nextTick(fn) {
return fn ? p.then(fn) : p
}

function queueFlush() {
if (isFlushPending) return
isFlushPending = true
nextTick(flushJobs)
}

function flushJobs() {
isFlushPending = false
let job
while ((job = queue.shift())) {
job && job()
}
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": [
"DOM",
"es6"
"es6",
"ES2016"
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
Expand Down

0 comments on commit de2bd59

Please sign in to comment.