console
<html>
<body>
<button onclick="createUl()">生成节点</button>
<button onclick="update()">更新节点</button>
<div class="list" id="mian">
<ul>
<li>你好</li>
<li>李红艳</li>
</ul>
</div>
</body>
<script>
Element.prototype.render = function() {
let el = document.createElement(this.tagName),
props = this.props,
propName,
propValue;
for (propName in props) {
propValue = props[propName]
el.setAttribute(propName, propValue)
}
this.children.forEach(function(child) {
let childEl = null
if (child instanceof Element) {
childEl = child.render()
} else {
childEl = document.createTextNode(child)
}
el.appendChild(childEl)
})
return el
}
const elem = Element({
tagName: 'ul',
props: {
'class': 'list2'
},
children: [
Element({
tagName: 'li',
children: ['item2'],
props: {
'class': 'item_1'
}
}),
Element({
tagName: 'li',
children: ['item2'],
props: {
'class': 'item_1'
}
})
]
})
function createUl() {
let sele = document.querySelector("body").appendChild(elem.render())
console.log('sele', sele)
}
function Element({
tagName,
props,
children
}) {
if (!(this instanceof Element)) {
return new Element({
tagName,
props,
children
})
}
this.tagName = tagName
this.props = props || {}
this.children = children || {}
}
function update() {
const body = document.querySelector('body')
const list = document.querySelector('.list2')
const newElem = Element({
tagName: 'ul',
props: {
'class': 'list3'
},
children: [
Element({
tagName: 'li',
children: ['1111111'],
props: {
'class': 'item_1'
}
})
]
})
updateElement(body, newElem, elem)
}
function changed(elem1, elem2) {
const result = JSON.stringify(elem1) !== JSON.stringify(elem2) ||
typeof elem1 === 'string' && elem1 !== elem2
return result
}
function updateElement($root, newElem, oldElem, index = 0) {
if (!oldElem) {
$root.appendChild(newElem.render())
} else if (!newElem) {
$root.removeChild($root.childNodes[index])
} else if (changed(newElem, oldElem)) {
console.log('newElem', newElem, 'index', index, '$root', $root)
if (typeof newElem === 'string') {
$root.childNodes[index].textContent = newElem
} else {
let newDom = newElem.render()
let oldDom = oldElem.render()
let innerHTML = oldDom.innerHTML
let childNodes = Array.from($root.childNodes)
let index = childNodes.findIndex(item => item.innerHTML === innerHTML)
if (index >= 0) {
$root.replaceChild(newDom, $root.childNodes[index])
}
}
} else if (newElem.tagName) {
let newLen = newElem.children.length
let oldLen = oldElem.children.length
for (let i = 0; i < newLen || i < oldLen; i++) {
updateElement(
$root.childNodes[index],
newElem.children[i],
oldElem.children[i],
i)
}
}
}
</script>
</html>