react,想必作为前端开发一定不陌生,组件化以及虚拟dom使得react成为最受欢迎额前端框架之一。我们知道react是基于虚拟dom的,但是什么是虚拟dom呢,其实就是一组js对象,那么我们今天就来认识什么是虚拟dom,以及如何转成真实的dom结构,完整的 简易版react 在个人github,实现了diff算法,组件渲染,组件更新,钩子函数。
一.认识虚拟dom
首先我们看如下代码
const title = <h1 className="title">Hello, world!</h1>;
这并不是合法的js代码,它是一种被称为jsx的语法扩展,通过它我们就可以很方便的在js代码中书写html片段。
本质上,jsx是语法糖,上面这段代码会被babel转换成如下代码
我们下载插件 babel-plugin-transform-react-jsx,并且配置.babelrc文件
{
"presets": ["env"],
"plugins": [
["transform-react-jsx", {
"pragma": "React.createElement"//大部分框架喜欢改成h
}]
]
}
于是页面中的jsx就会被babel转成如下的结构
const title = React.createElement(
'h1',
{ className: 'title' },
'Hello, world!'
);
可以看出babel已经把一个dom元素分解成标签名称h1,属性集合对象,以及内部子节点(这里是hello world文本节点),我们首先修改这个方法,为了转成我们需要的结构
function createElement( tag, attrs, ...children ) {
return {
tag,
attrs,
children
}
}
// 将上文定义的createElement方法放到对象React中
const React = {
createElement,
}
函数的参数...children
使用了ES6的rest参数,它的作用是将后面child1,child2等参数合并成一个数组children。
现在我们来试试调用它,一下结构都是babel自动调用React.createElement给我们转成的,当然你也可以自己写方法将真实的dom转为js对象
const element = (
<div>
hello<span>world!</span>
</div>
);
console.log( element );
二.将上列的虚拟dom结构转成真实的dom
1.如果遇到文本节点则直接返回新建的文本节点
//处理文本节点
if( typeof vnode === 'string'){
const textNode = document.createTextNode( vnode )
return textNode;
}
2.处理普通的元素
//普通的dom
const dom = document.createElement( vnode.tag );
if( vnode.attrs ){
Object.keys( vnode.attrs ).forEach( key => {
const value = vnode.attrs[ key ];
setAttribute( dom, key, value ); // 设置属性
} );
}
vnode.children.forEach( child => render( child, dom ) ); // 递归渲染子节点
return dom ; // 返回虚拟dom为真正的DOM
3.遇到普通元素的属性,需要这是属性节点,但是分为两种,一种是普通的属性,比如className,另一种是方法绑定,比如是onClick
function setAttribute( dom, name, value ) {
// 如果属性名是className,则改回class
if ( name === 'className' ) name = 'class'; // 如果属性名是onXXX,则是一个事件监听方法
if ( /on\w+/.test( name ) ) {
name = name.toLowerCase();
dom[ name ] = value || '';
// 如果属性名是style,则更新style对象
} else if ( name === 'style' ) {
if ( !value || typeof value === 'string' ) {
dom.style.cssText = value || '';
} else if ( value && typeof value === 'object' ) {
for ( let name in value ) {
// 可以通过style={ width: 20 }这种形式来设置样式,可以省略掉单位px
dom.style[ name ] = typeof value[ name ] === 'number' ? value[ name ] + 'px' : value[ name ];
}
}
// 普通属性则直接更新属性
} else {
if ( name in dom ) {
dom[ name ] = value || '';
}
if ( value ) {
dom.setAttribute( name, value );
} else {
dom.removeAttribute( name, value );
}
}
}
三.查看完整的代码
function render ( vnode, container ){
return container.appendChild( _render( vnode ) );
}
function _render( vnode ){
if ( typeof vnode === 'number' ) {
vnode = String( vnode );
}
//处理文本节点
if( typeof vnode === 'string'){
const textNode = document.createTextNode( vnode )
return textNode;
}
//处理组件
if ( typeof vnode.tag === 'function' ) {
const component = createComponent( vnode.tag, vnode.attrs );
setComponentProps( component, vnode.attrs );
return component.base;
}
//普通的dom
const dom = document.createElement( vnode.tag );
if( vnode.attrs ){
Object.keys( vnode.attrs ).forEach( key => {
const value = vnode.attrs[ key ];
setAttribute( dom, key, value ); // 设置属性
} );
}
vnode.children.forEach( child => render( child, dom ) ); // 递归渲染子节点
return dom ; // 返回虚拟dom为真正的DOM
}
//实现dom挂载到页面某个元素
const ReactDOM = {
render: ( vnode, container ) => {
container.innerHTML = '';
return render( vnode, container );
}
}
现在我们已经实现将虚拟dom转为真实的dom,已经绑定属性,我们现在来像react一样调用这个方法
const element = (
<div>
hello<span>world!</span>
</div>
); ReactDOM.render(
element,
document.getElementById( 'main' )
);
现在就实现往页面中元素id为main的元素上挂载了该element。
react系列一,react虚拟dom如何转成真实的dom的更多相关文章
-
react系列从零开始-react介绍
react算是目前最火的js MVC框架了,写一个react系列的博客,顺便回忆一下react的基础知识,新入门前端的小白,可以持续关注,我会从零开始教大家用react开发一个完整的项目,也会涉及到w ...
-
React系列文章:JSX生成真实DOM结点
在上一篇文章中,我们介绍了Babel是如何将JSX代码编译成可执行代码的,随后也实现了一个自己的解析器,模拟了Babel编译的过程. 现在我们再来回顾一下,假定有如下业务代码: const style ...
-
React 学习(一) ---- React Element /组件/JSX
学习React的时候,你可能听到最多的就是要先学习webpack, babel,要先学会配置然后才能学react 等等,一堆的配置就把我们吓着了,根本就没有心情就学习react了.其实在最开始学习re ...
-
React 引入import React 原理
本质上来说JSX是React.createElement(component, props, ...children)方法的语法糖. 所以我们如果使用了JSX,我们其实就是在使用React,所以我们就 ...
-
从 0 到 1 实现 React 系列 —— 1.JSX 和 Virtual DOM
看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...
-
深刻理解 React (一) ——JSX和虚拟DOM
版权声明:本文由左明原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/155 来源:腾云阁 https://www.qclou ...
-
React会自动把虚拟DOM数组展开
React会自动把虚拟DOM数组展开,放在父级虚拟DOM中,这个特性还是我同事帮我解决一个问题的时候,偶然发现的. 如何将一个数据数组转换为一个虚拟DOM的数组,需要使用map,如下: const n ...
-
【React 7/100 】 虚拟DOM和Diff算法
虚拟DOM和Diff算法 React更新视图的思想是:只要state变化就重新渲染视图 特点:思路非常清晰 问题:组件中只有一个DOM元素需要更新时,也得把整个组件的内容重新渲染吗? 不是这样的 理想 ...
-
React入门-JSX和虚拟dom
1.JSX理解 举例: const element = <h1>Hello, world!</h1>; 这被称为 JSX,是一个 JavaScript 的语法扩展.建议在 Re ...
随机推荐
-
[转]Web APi之认证(Authentication)及授权(Authorization)【一】(十二)
本文转自:http://www.cnblogs.com/CreateMyself/p/4856133.html 前言 无论是ASP.NET MVC还是Web API框架,在从请求到响应这一过程中对于请 ...
-
SQLite 粗劣内容
SQLite 的官网 http://addons.mozillan.org/firefox/addon/sqlite-manager/ http://www.sqlite.org sqlite3 *s ...
-
React Native的环境搭建以及开发的IDE
(一)前言 前面的课程我们已经对React Native的环境搭建以及开发的IDE做了相关的讲解,今天我们的主要讲解的是应用设备运行(Running)以及调试方法(Debugging).本节的前提条件 ...
-
SaltStack安装篇
一.基础介绍1.简介 salt 是一个基础平台管理工具 salt是一个配置管理系统,能够维护预定于状态的远程节点 salt是一个分布式远程执行系统,用来在远程节点上执行命令和查询数据 2.salt的核 ...
-
css问题 ie7兼容性问题
1.响应式网站用百分比时ie7不兼容:试试将margin:0 10% 改为margin-left:15%; 左边是可以的,但是右边就不行了 2.ie7的span 里的字会出现白色背景 ,是因为没有定高 ...
-
在HTML文件中加载js
js加载只分为两种: 1.全局js,放在<head>标签里面,整个页面很多都用到的,它是优先加载的. 2.局部js,放在</html>结束标签以内的任何位置,它是第二加载的.
-
ubuntu12.04安装QQ2013
1.下载Longene QQ2013SP6 http://pan.baidu.com/s/1hq83fWo 2.安装 1)如果之前安装过旧版本需要先卸载(通过dpkg -l | grep qq查看). ...
-
Windows noinstall zip 安装MySQL。
听完数据库老师的课,想在Windows下通过命令行的方法安装MySQL5.7,于是开了这个坑,终于把这个坑填上了. 第一步:下载MySQL 的noinstall zip ,点击该链接下载,或者复制链接 ...
-
linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
-
ABB机器人---PCSDK简介
BB机器人为用户提供了大量便捷的二次开发及应用工具,PCSDK就是其中一项. 1) 首先,机器人使用PCSDK,必须要有pc interface选项. 2)此处举例使用C#编写简单界面,实现与机器人数 ...