这是我参与更文挑战的第8天
前面我们已经将virtualDOM转化为真实DOM了,但是这些真实DOM是没有任何属性的,接下来我们就为真实DOM添加属性
为真实DOM添加属性
分析:
这些属性全部存储在虚拟DOM的props里面,我们只需要在创建元素的时候找到virtualDOM的属性props,然后遍历props属性,在遍历的过程当中就可以将这些属性添加给真实DOM元素了,但是在添加属性的时候我们还需要考虑一些不同的情况,因为不同情况我们要去做不同的处理,如果是事件属性,那么我们就要为该元素去添加事件;还要判断这个属性是否是value属性或者是checked属性,因为这两个属性是无法使用setAttribute方法去设置它的,我们还需要看看这个属性是否是children属性,children不是属性是子元素但是也存在props中;还需要看这个属性是否是className属性,如果是className的话我们就给元素添加class属性;如果是普通属性就可以用setAttribute方法给真实DOM去设置就行了。
代码实现:
export default function updateNodeElement(newElement, virtualDOM) {
// 获取节点对应的属性对象
const newProps = virtualDOM.props
Object.keys(newProps).forEach(propName => {
// 获取属性值
const newPropsValue = newProps[propName]
// 判断属性是否是事件属性 onClick => click
if(propName.slice(0, 2) === "on") {
const eventName = propName.toLowerCase().slice(2)
// 为元素添加事件
newElement.addEventListener(eventName, newPropsValue)
} else if(propName === "value" || propName === "checked") {
newElement[propName] = newPropsValue
} else if (propName !== "children") {
if(propName === "className") {
newElement.setAttribute('class', newPropsValue)
} else {
newElement.setAttribute(propName, newPropsValue)
}
}
})
}
复制代码
在生成真实DOM文件夹引用这个方法:
import updateNodeElement from "./updateNodeElement"
export default function mountNativeElement (virtualDOM, container) {
let newElement = null
···
else {
// 元素节点
newElement = document.createElement(virtualDOM.type);
updateNodeElement(newElement, virtualDOM);
复制代码
小结:
当我们创建真实元素节点的时候,调用updateNodeElement
给这个元素添加属性,属性存在virtualDOM的props中,所以这个updateNodeElement
传两个参数,一个是当前的真实DOM,newElement(给谁设置属性),一个是virtualDOM(这些属性藏在哪),在把props里面的属性全部拿出来,属性为事件使用addEventListener添加监听事件,value和checked使用newElement[propName] = newPropsValue
,接下来除children这个节点,其他节点为className转化为class,其他的直接setAttribute。