mini-react実現原理解説第四講
5210 ワード
文章は私のブログから始まりました.
https://github.com/mcuking/bl...
関連コードはhttps://github.com/mcuking/bl...を参照してください.
属性を更新
ここでは、diffアルゴリズムの概要について説明します.主に属性を更新する仕組みを紹介します.新しいvnodeのpropsと古いvnodeのpropsを比較して、は、新しいDOMノード属性のみに存在するセットを見つけ、setAttrs(olddom、onlyInLeft) を呼び出す.は、旧DOMノード属性のみに存在するセットを見つけ、removeAttrs(olddom、onlyInRight) を呼び出す.旧DOMノードと新しいDOMノードの両方に存在する属性のセットを見つけ、diffAttrs(olddom、bothIn.left、bothIn.right) を呼び出す. mini-react実現原理解説第一話 mini-react実現原理解説第二話 mini-react実現原理解説第三講 mini-react実現原理解説第四講 mini-react実現原理解説第五話
https://github.com/mcuking/bl...
関連コードはhttps://github.com/mcuking/bl...を参照してください.
属性を更新
ここでは、diffアルゴリズムの概要について説明します.主に属性を更新する仕組みを紹介します.新しいvnodeのpropsと古いvnodeのpropsを比較して、
//
const {onlyInLeft, onlyInRight, bothIn} = diffObject(vnode.props, olddom._vnode.props)
setAttrs(olddom, onlyInLeft)
removeAttrs(olddom, onlyInRight)
diffAttrs(olddom, bothIn.left, bothIn.right)
// VNode DOM
function diffObject(leftProps, rightProps) {
const onlyInLeft = {} // DOM
const onlyInRight = {} // DOM
const bothLeft = {} // DOM
const bothRight = {} // DOM
for (let key in leftProps) {
if (rightProps[key] === undefined) {
onlyInLeft[key] = leftProps[key]
} else {
bothLeft[key] = leftProps[key]
bothRight[key] = rightProps[key]
}
}
for (let key in rightProps) {
if (leftProps[key] === undefined) {
onlyInRight[key] = rightProps[key]
}
}
return {
onlyInLeft,
onlyInRight,
bothIn: {
left: bothLeft,
right: bothRight
}
}
}
// DOM
function setAttrs(dom, props) {
for (let k in props) {
// className , class
if (k === 'className') {
dom.setAttribute('class', props[k])
continue
}
// style
if (k === 'style') {
if (typeof props[k] === 'string') {
dom.style.cssText = props[k]
}
if (typeof props[k] === 'object') {
for (let v in props[k]) {
dom.style[v] = props[k][v]
}
}
continue
}
// on
if (k[0] === 'o' && k[1] === 'n') {
dom.addEventListener(k.substring(2).toLowerCase(), props[k], false)
continue
}
//
dom.setAttribute(k, props[k])
}
}
// DOM
function removeAttrs(dom, props) {
for (let k in props) {
if (k === 'className') {
dom.removeAttribute('class', props[k])
continue
}
if (k === 'style') {
dom.style.cssText = ''
continue
}
if (k[0] === 'o' && k[1] === 'n') {
dom.removeEventListener(k.substring(2).toLowerCase(), props[k], false)
continue
}
//
dom.removeAttribute(k, props[k])
}
}
// DOM
function diffAttrs(dom, newProps, oldProps) {
for (let k in newProps) {
if (newProps[k] === oldProps[k]) continue
if (k === 'className') {
dom.setAttribute('class', newProps[k])
continue
}
if (k === 'style') {
if (typeof newProps[k] === 'string') {
dom.style.cssText = newProps[k]
}
if (typeof newProps[k] === 'object' && typeof oldProps[k] === 'object') {
for (let v in newProps[k]) {
// css css , css css
if (newProps[k][v] !== oldProps[k][v]) {
dom.style[v] = newProps[k][v]
}
}
// css , css , css
for (let v in oldProps[k]) {
if (newProps[k][v] === undefined) {
dom.style[v] = ''
}
}
}
continue
}
if (k[0] === 'o' && k[1] === 'n') {
dom.removeEventListener(k.substring(2).toLowerCase(), oldProps[k], false)
dom.addEventListener(k.substring(2).toLowerCase(), newProps[k], false)
continue
}
//
dom.setAttribute(k, newProps[k])
}
}
関連記事