diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..c72b2d2 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,3 @@ +export default { + transform: {}, +}; diff --git a/package.json b/package.json index 7c43092..5b04beb 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "description": "", "main": "index.js", "scripts": { - "test": "jest" + "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "jest": "^29.0.0" + }, + "devDependencies": { + "cross-env": "^7.0.3" } } diff --git a/test/index.spec.js b/test/index.spec.js index 94eb243..bb1ac34 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,35 +1,41 @@ -const { elementOpen, text, elementEnd, currentInfo } = require('../vdom/vnodeBack.js'); +import { elementOpen, text, elementEnd, currentInfo } from "../vdom/vnode.js"; -describe('idom', () => { - test('校验idom结构', async () => { - elementOpen('div') - elementOpen('p') - text('1') - elementEnd('p') - text('2') - elementEnd('div') - var currentNode = currentInfo.currentNode - expect(JSON.stringify(currentNode)).toBe('{"tagName":"div","children":[{"tagName":"p","text":"1"}],"text":"2"}') - }) -}) +describe("idom", () => { + test("校验idom结构", async () => { + elementOpen("div"); + elementOpen("p"); + text("1"); + elementEnd("p"); + text("2"); + elementEnd("div"); + var currentNode = currentInfo.currentNode; + expect(JSON.stringify(currentNode)).toBe( + '{"tagName":"div","children":[{"tagName":"p","text":"1"}],"text":"2"}' + ); + }); +}); -describe('idom2', () => { - test('重复调用的时候,生成结果独立互不影响', async () => { - elementOpen('div') - elementOpen('p') - text('1') - elementEnd('p') - text('2') - elementEnd('div') - var currentNode = currentInfo.currentNode - elementOpen('div') - elementOpen('p') - text('3') - elementEnd('p') - text('4') - elementEnd('div') - var currentNode2 = currentInfo.currentNode - expect(JSON.stringify(currentNode)).toBe('{"tagName":"div","children":[{"tagName":"p","text":"1"}],"text":"2"}') - expect(JSON.stringify(currentNode2)).toBe('{"tagName":"div","children":[{"tagName":"p","text":"3"}],"text":"4"}') - }) -}) \ No newline at end of file +describe("idom2", () => { + test("重复调用的时候,生成结果独立互不影响", async () => { + elementOpen("div"); + elementOpen("p"); + text("1"); + elementEnd("p"); + text("2"); + elementEnd("div"); + var currentNode = currentInfo.currentNode; + elementOpen("div"); + elementOpen("p"); + text("3"); + elementEnd("p"); + text("4"); + elementEnd("div"); + var currentNode2 = currentInfo.currentNode; + expect(JSON.stringify(currentNode)).toBe( + '{"tagName":"div","children":[{"tagName":"p","text":"1"}],"text":"2"}' + ); + expect(JSON.stringify(currentNode2)).toBe( + '{"tagName":"div","children":[{"tagName":"p","text":"3"}],"text":"4"}' + ); + }); +}); diff --git a/vdom/vnode.js b/vdom/vnode.js index 4839adb..64e22c2 100644 --- a/vdom/vnode.js +++ b/vdom/vnode.js @@ -4,24 +4,48 @@ {"tagName":"div","children":[{"tagName":"p","text":"1"}],"text":"2"} */ -var currentInfo = { - currentNode: null, - currentParent: null -} -function elementOpen(tagName) { - // TODO +export const currentInfo = { + currentNode: null, + currentParent: null, +}; + +// 添加 isOpen 状态后,代码可读性大大增强 +export function elementOpen(tagName) { + const { currentNode, currentParent } = currentInfo; + + const newParent = currentNode?.isOpen ? currentNode : currentParent; + const newNode = { tagName, isOpen: true, parent: newParent }; + + if (newParent) { + newParent.children = [...(newParent?.children || []), newNode]; + } + + currentInfo.currentNode = newNode; + currentInfo.currentParent = newParent; } -function text(textContent) { - // TODO +export function text(textContent) { + if (!currentInfo.currentNode?.isOpen) { + return; + } + + currentInfo.currentNode.text = textContent; } -function elementEnd(tagName) { - // TODO +export function elementEnd(tagName) { + const { currentNode, currentParent } = currentInfo; + + if (currentNode.tagName !== tagName || !currentNode?.isOpen) { + return; + } + + const nextNode = currentParent ? currentParent : currentNode; + const nextParent = nextNode.parent; + + currentInfo.currentNode = nextNode; + currentInfo.currentParent = nextParent; + + // 关闭节点后,节点不必保留父节点状态(可以从currentParent读取)和自身的 open 状态 + delete currentNode.parent; + delete currentNode.isOpen; } -module.exports = { - elementOpen, - text, - elementEnd, - currentInfo -}; \ No newline at end of file