function createElement(type, config, children) {
// 1. 创建一个对象
// 2.根据参数config修改这个对象
// 3.把children参数作为对象中props中的一个属性
let virtureDOM = {};
virtureDOM.type = type;
virtureDOM.ref = config.ref || null;
virtureDOM.key = config.key || null; let props = {}; // 虚拟dom的props
for (const attr in config) { // 遍历config 把除去ref和key的属性值复制到props中
if (attr === 'key' || attr === 'ref') continue;
else props[attr] = config[attr];
} const childrenLength = arguments.length - 2;// create可以传多个参数 第三个开始被认为是children
if (childrenLength === 1) {
props.children = children; // 如果只有一个 那么children就是第三个参数
} else if (childrenLength > 1) {
let childArray = Array(childrenLength); // 如果不止一个,就存入childArray数组中
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
} virtureDOM.props = props;
return virtureDOM;
} // 把创建的对象转为真实DOM元素最后插入到页面中
function render(virtureDOM, container, callback) {
let { type, props } = virtureDOM || {};
let realDom = document.createElement(type); for (let attr in props) {
if (!props.hasOwnProperty(attr)) break; // 如果不是私有属性 直接跳出 说明已经遍历到原型上了
if (!props[attr]) continue; // 如果这个attr没有有效值,那么继续找下一个
const val = props[attr];
// 处理classname变成class
if (attr === 'className') realDom.setAttribute('class', val); else if (attr === 'children') { // 处理children
if (typeof val === 'string') { // 如果只有一个字符串children 那么直接渲染text出来
let text = document.createTextNode(val);
realDom.appendChild(text);
}
else if (val instanceof Array) { // 如果children是数组, 那么就得遍历这个数组分情况再渲染
for (let i = 0; i < val.length; i++) {
if (typeof val[i] === 'string') {
let text = document.createTextNode(val[i]);
realDom.appendChild(text);
} else {
render(val[i], realDom);
}
}
}
else { // 如果children只有一个且不是数组也不是字符串 那么应该是createElement出来的虚拟dom。递归
render(val, realDom);
}
} else if (attr === 'style') { // 处理style属性
if (val === '') continue; // style 有可能值为空字符串
for (let sty in val) {
if (val.hasOwnProperty(sty)) realDom['style'][sty] = val[sty];
}
} else realDom.setAttribute(attr, val); // 基于setAttribute可以让设置的属性表现在html的结构上
}
container.appendChild(realDom);
callback && callback();
} const virtureDom2 = createElement('span',
{}, 'age is 18!'); const virtureDom = createElement('div',
{
id: 'box',
className: 'lp',
style: { color: 'red' },
key: 12,
ref: 'refs'
}, 'my name is LanPang ', virtureDom2); render(virtureDom, document.getElementById('root'), () => console.log('finish'));

实现简易版react中createElement和render方法的更多相关文章

  1. React中ref的使用方法

    React中ref的使用方法 在react典型的数据流中,props传递是父子组件交互的唯一方式:通过传递一个新的props值来使子组件重新re-render,从而达到父子组件通信.当然,就像reac ...

  2. react中的children使用方法

    使用过vue的小伙伴都知道vue中有个slot,也就是插槽,作用就是占位,那么再react中可以使用children来替代 父组件 render(){ return( <div> < ...

  3. react中常用的一些方法

    React.createClass:创建一个ReactClass(组件类),参数是一个对象且必须带有 render 属性方法,该方法必须返回一个封闭的容器(容器内可以有其它不限结构的容器)或 null ...

  4. 聊一聊React中虚拟DOM

    1. 什么是虚拟 DOM 在 React 中实际上是 render 函数中return 的内容会生成 DOM,return 中的内容由两部分组成,一部分是 JSX ,另一部分就是 state 中的数据 ...

  5. react中的setState的使用和深入理解

    前端框架从MVC过渡到MVVM.从DOM操作到数据驱动,一直在不断的进步着,提升着, angular中用的是watcher对象,vue是观察者模式,react就是state了,他们各有各的特点,没有好 ...

  6. React中的事件处理为什么要bind this?

    个人总结: 问: 请给我讲一下React中的事件处理为什么要bind this? 答: 好的,比如说我写了一个类组件,有个onClick属性 ,onClick={ this.fun },如果不bind ...

  7. React中的State与Props

    一.State 1.什么是 state 一个组件的显示形态可以由数据状态和外部参数决定,其中,数据状态为 state,外部参数为 props 2.state 的使用 组件初始化时,通过 this.st ...

  8. React中setState的怪异行为 ——setState没有即时生效

    setState可以说是React中使用频率最高的一个函数了,我们都知道,React是通过管理状态来实现对组件的管理的,当this.setState()被调用的时候,React会重新调用render方 ...

  9. react中怎么写css样式?

    JSX基本语法中关于react如何写css样式主要有三种方法 1.基于class --(className) 基于className ,通过className在style中给该class名的DOM元素 ...

随机推荐

  1. 14.6 kafka

    14.6 kafka 为什么用消息队列 举例 比如在一个企业里,技术老大接到boss的任务,技术老大把这个任务拆分成多个小任务,完成所有的小任务就算搞定整个任务了. 那么在执行这些小任务的时候,可能有 ...

  2. Fabric CA的部署与使用

    Fabric CA是Hyperledger Fbric的证书认证中心,提供以下功能:用户信息的登记与注册,数字证书的颁发与管理. 前言 之前使用CA服务一直是在docker容器中运行下载好的CA镜像, ...

  3. C语言合法标识符(hud2024)

    输入方式:先输入一个整型,再循环输入带空格的字符串. 思考:整型用scanf_s()输入.大循环输入字符串前用getchar()函数读取缓冲区的字符.然后,输入带空格的字符串就要用”gets_s()“ ...

  4. Kubernetes学习笔记(五):卷

    简介 卷是Pod的一部分,与Pod共享生命周期.它不是独立的Kubernetes对象,因此不能单独创建. 卷提供的存储功能不但可以解决容器重启后数据丢失的问题,还可以使数据在容器间共享. 一些卷的类型 ...

  5. 【Java】几种典型的内存溢出案例,都在这儿了!

    写在前面 作为程序员,多多少少都会遇到一些内存溢出的场景,如果你还没遇到,说明你工作的年限可能比较短,或者你根本就是个假程序员!哈哈,开个玩笑.今天,我们就以Java代码的方式来列举几个典型的内存溢出 ...

  6. Java——变量自增(++)自减(--)

    //运算符在操作数之后,称为“后增量”.i变量自增,返回自增之前的值;//运算符在操作数之前,称为“前增量”.i变量自增,返回自增之后的值.//自减同理 public static void test ...

  7. liunx tar 详解

     tar [-cxtzjvfpPN] 文件与目录 .... 参数说明 -c: 建立一个压缩文件的指令参数 (crate的缩写): -x:解开一个压缩文件的参数指令: -t:查看tarfile里面的文件 ...

  8. SpringBoot 安全管理(一)

    SpringBoot 安全管理(一) 一.springSecurity入门 添加依赖 <dependency> <groupId>org.springframework.boo ...

  9. 01 . Memcached简介及部署

    Memcached简介 memcached是一个自由开源,高性能,分布式内存对象存储系统 基于内存的key-valued存储,用来存储小块的任意数据(字符串,对象) 他是一个简洁的key-value存 ...

  10. vc程序设计--对键盘与鼠标的响应(1)

    // WindowsProject2.cpp : 定义应用程序的入口点. // /** * 当按下CTRL键时输出信息:CTRL键被压下 * 当按下K键时输出信息:K键被压下 * 当按下CTRL+K键 ...