实现简易版react中createElement和render方法
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方法的更多相关文章
- React中ref的使用方法
React中ref的使用方法 在react典型的数据流中,props传递是父子组件交互的唯一方式:通过传递一个新的props值来使子组件重新re-render,从而达到父子组件通信.当然,就像reac ...
- react中的children使用方法
使用过vue的小伙伴都知道vue中有个slot,也就是插槽,作用就是占位,那么再react中可以使用children来替代 父组件 render(){ return( <div> < ...
- react中常用的一些方法
React.createClass:创建一个ReactClass(组件类),参数是一个对象且必须带有 render 属性方法,该方法必须返回一个封闭的容器(容器内可以有其它不限结构的容器)或 null ...
- 聊一聊React中虚拟DOM
1. 什么是虚拟 DOM 在 React 中实际上是 render 函数中return 的内容会生成 DOM,return 中的内容由两部分组成,一部分是 JSX ,另一部分就是 state 中的数据 ...
- react中的setState的使用和深入理解
前端框架从MVC过渡到MVVM.从DOM操作到数据驱动,一直在不断的进步着,提升着, angular中用的是watcher对象,vue是观察者模式,react就是state了,他们各有各的特点,没有好 ...
- React中的事件处理为什么要bind this?
个人总结: 问: 请给我讲一下React中的事件处理为什么要bind this? 答: 好的,比如说我写了一个类组件,有个onClick属性 ,onClick={ this.fun },如果不bind ...
- React中的State与Props
一.State 1.什么是 state 一个组件的显示形态可以由数据状态和外部参数决定,其中,数据状态为 state,外部参数为 props 2.state 的使用 组件初始化时,通过 this.st ...
- React中setState的怪异行为 ——setState没有即时生效
setState可以说是React中使用频率最高的一个函数了,我们都知道,React是通过管理状态来实现对组件的管理的,当this.setState()被调用的时候,React会重新调用render方 ...
- react中怎么写css样式?
JSX基本语法中关于react如何写css样式主要有三种方法 1.基于class --(className) 基于className ,通过className在style中给该class名的DOM元素 ...
随机推荐
- 重学 Java 设计模式:实战工厂方法模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 进程间的通信——pipe通信
当进程创建管道文件后,其建立的子进程自动继承该文件. 管道通信分为命名管道和未命名管道,他们的区别是命名管道在当创建他的进程结束后,系统仍存有该文件 管道的命令格式为 pipe(fds) 其中 fds ...
- h5 编辑单选框的样式
radio单选框样式设置 input[type=radio] { display: inline-block; vertical-align: middle; width: 20px; height: ...
- 基于Unity实现油画风格的着色器
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cust ...
- 如何理解Java中的自动拆箱和自动装箱?
小伟刚毕业时面的第一家公司就被面试官给问住了... 如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区... 回到家后小伟赶紧查资料,我透,这不 ...
- 1.Redis介绍和使用场景
(1)持久化数据库的缺点 平常我们使用的关系型数据库有Mysql.Oracle以及SqlServer等,在开发的过程中,数据通常都是通过Web提供的数据库驱动来链接数据库进行增删改查. 那么,我们日常 ...
- lunix如何查看防火墙是否关闭和关闭开启防火墙命令
查看防火墙是否关闭的命令如下: 1.通过 /etc/init.d/iptables status 或者 service iptables status命令 2.通过 iptables -L命令 查看 ...
- vue-cli4配置文件别名
具体步骤如下: 1.在项目中新建vue.config.js文件 注意:此文件要与src文件夹同级 : 修改此文件后,需要重启项目 2.在vue.config.js文件中配置如截图 第一个参数:是你设置 ...
- 【Java8新特性】重复注解与类型注解,你真的学会了吗?
写在前面 在Java8之前,在某个类或者方法,字段或者参数上标注注解时,同一个注解只能标注一次.但是在Java8中,新增了重复注解和类型注解,也就是说,从Java8开始,支持在某个类或者方法,字段或者 ...
- Rocket - tilelink - AtomicAutomata
https://mp.weixin.qq.com/s/O7VTHqpCFNJQi3EpucXkIw 简单介绍AtomicAutomata的实现.(细节问题太多,恕不完全表述.) 1. ...