瞬间科学上网:http://www.svpn.tech/
2020 动手写个 react (2)
coding我们写一段 jsx ,有关 jsx 语法这里暂不做过介绍,留下伏笔const ele = ( const ele = (
> hello zidea ) ) 然后将上面 jsx 通过 babel 转换为 js 如下"use strict"; const ele = /*#__PURE__*/
React.createElement("div", { className: "box", size: "25" }, "hello ", /*#__PURE__*/React.createElement(
"span", null, "zidea")); 有了上面生成代码,我们简单地分析一下React.createElement(tag,attrs,children) tag 是要创建标签名称attrs 是以对象形式组织属性对象,对象中以键值对形式保存属性名和值
children 是若干个子元素实现 createElement 方法创建 React 对象const React = { createElement } 实现 creatElement 方法
// createElementfunctioncreateElement(tag,attrs,...children){ return { tag, attrs, children } }
exportdefault React; 引入 React 对象,使用 React 的 createElement 方法import React from./reactconst ele = (
hello react ) console.log(ele)
图实现渲染我们都知道在 React 中调用 ReactDom 的 render 方法然后传入虚拟节点和要将虚拟节点添加容器 dom 元素就可以实现将虚拟节点渲染到页面ReactDOM.render(ele
,document.querySelector("#root")) import React from./reactconst ele = (
> hello react ) // console.log(ele) ReactDOM.render(ele,document.querySelector(
"#root")) 接下依旧是创建文件夹 react-dom 然后在该文件夹下创建 index.js 文件实现 ReactDOM 的 render 方法const ReactDOM = { render }
functionrender(vnode,container){ //TODO } exportdefault ReactDOM; 有关常见一个 js 模块并且将 ReactDOM 对象暴露出来我就不做过多解释了。
接下来我们就专注 render 方法的实现文本节点实现functionrender(vnode,container){ //TODOif(vnode === undefined ) return。
; // vnode is equal stringif(typeof vnode === string){ //create textNodeconst textNode =
document.createTextNode(vnode) return container.appendChild(textNode) } } 参数和 react 没有什么区别vnode 虚拟节点container 容器
首先判断 vnode 是否为空,为空则直接返回然后判断 vnode 是否为字符串,如果为字符串这添加文本节点看效果ReactDOM.render(react,document.querySelector(
"#root")) 虚拟节点ReactDOM.render(ele,document.querySelector("#root")); console.log(vnode) functionrender
(vnode,container){ ... // deconstruct vnodeconst {tag} = vnode; //create dom objectconst
dom = document.createElement(tag) container.appendChild(dom) } 解构 vnode 对象根据 tag 创建 dom 对象将 dom 对象添加到容器中
【telegram指定翻墙地址:www.av1o.com】
获取属性functionrender(vnode,container){ ... // deconstruct vnodeconst {tag,attrs} = vnode;
//create dom objectconst dom = document.createElement(tag) if(attrs){ // property key: className box
Object.keys(attrs).forEach(key=>{ const val = attrs[key] }) } ... } 从虚拟节点(vnode)中解构出 attrs
然后遍历 attrs 获取属性值设置属性functionsetAttribute(dom,key,value){ } 实现 setAttribute 方法function setAttribute(dom,key,
value){ // convert className to class// 1. event 2.class 3.style etc // class caseif(key === className
){ key = class } // event caseif(/on\w+/.test(key)){ //to lower case key = key.toLowerCase(); dom[key] =
value || }elseif(key === style){ if(!value || typeofvalue === string){ dom.style.cssText =
value || ; }elseif(value && typeofvalue === object){ //{width:16}for(let k invalue
){ if(typeofvalue[k] === number){ dom.style[k] = value[k] + px }
else{ dom.style[k] = value[k] } } } }else
{ if(key in dom){ dom[key] = value || } if(value){ dom.setAttribute(key,
value) }else{ dom.removeAttribute(key) } } } 在 dom 上有许多属性,可以通过属性添加样式,添加事件,保存数据等。
我们这里通过判断 attrs 中属性键和值类型来一一进行判断class 属性如果键为 className 时,我们将键修改 class 虽然添加值if(key === className){ key =
class } 事件属性if(/on\w+/.test(key)){ //to lower case key = key.toLowerCase(); dom[key] = value
|| } 样式属性elseif(key === style){ if(!value || typeofvalue === string){ dom.style.cssText =
value || ; }elseif(value && typeofvalue === object){ //{width:16}for(let k invalue){
if(typeofvalue[k] === number){ dom.style[k] = value[k] + px }else{ dom.style[k] =
value[k] } } } } 样式情况相对于其他属性要复杂一些,分两种情况处理可能是字符串或者一个对象字符串情况直接赋值即可对象情况在开始处理对象情况,我们先看一看下面 jsx 对象编译为 javascript 对象后默认
const ele = ( hello zidea )
... style: { width: 16 } ... 这里 style 对象中嵌套一个对象,我们通过解析对象来获取每一个样式的名称和样式值样式值可能是数值也可能是字符串for(let k
invalue){ if(typeofvalue[k] === number){ dom.style[k] = value[k] + px }else{ dom.style[k] =
value[k] } } if(attrs){ // property key: className boxObject.keys(attrs).forEach(key=>{
const val = attrs[key] setAttribute(dom,key,val) }) } container.appendChild(dom) 渲染子节点通过递归形式来实现渲染子节点
functionrender(vnode,container){ ... vnode.children.forEach(child=>render(child,dom)) container.appendChild(dom) }
【飞机专用地址:vpn.shunjianboy.top】