小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
ReactJS简介
- React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
- react只关注于视图层,官方对react的定位是:用于构建用户界面的 JavaScript 库
- 最流行的一门框架。轻量级前端框架(其实Vue也算是),支持JSX(JavaScript XML)语法,jsx是js内定义的一套XML语法,最终被解析成js。在JSX中可以将HTML于JS混写;同样采用虚拟DOM,高效。
React与vue.js的对比
虚拟Dom
- Vue的虚拟dom是基于snabbdom库所做的修改,为了保证页面的最小优化,snabbdom引入了diff算法,通过Diff算法找出前后两个虚拟DOM之间的差异,只更新改变了的DOM节点,而不重新渲染为改变的DOM节点。
- react定义的一种类似于XML的JS扩展语法:JSX。作用是用来创建react虚拟DOM。
组件化方面
- 模块化:从 代码 的角度,去分析问题,把我们编程时候的业务逻辑,分割到不同的模块中来进行开发,这样能够方便代码的重用;
- 组件化:从 UI 的角度,去分析问题,把一个页面,拆分为一些互不相干的小组件,随着我们项目的开发,我们手里的组件会越来越多,最后,我们如果要实现一个页面,可能直接把现有的组件拿过来进行拼接,就能快速得到一个完整的页面, 这样方便了UI元素的重用;组件是元素的集合体;
- Vue是如何实现组件化的:.vue 组件模板文件,浏览器不识别这样的.vue文件,所以,在运行前,会把 .vue 预先编译成真正的组件;
- template: UI结构
- script: 业务逻辑和数据
- style: UI的样式
4.React如何实现组件化:在React中实现组件化的时候,根本没有 像 .vue 这样的模板文件,而是,直接使用JS代码的形式,去创建任何你想要的组件;
- React中的组件,都是直接在 js 文件中定义的;
- React的组件,并没有把一个组件 拆分为 三部分(结构、样式、业务逻辑),而是全部使用JS来实现一个组件的;(也就是说:结构、样式、业务逻辑是混合在JS里面一起编写出来的)
移动APP开发
- Vue,结合 Weex 这门技术,提供了 迁移到 移动端App开发的体验
- React,结合 ReactNative,提供了迁移到 移动App的开发体验(RN用的最多,也是最火最流行的);
轻量化
都把注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。(vue-router、vuex、react-router、redux等等)
React中几个核心的概念
虚拟DOM(Virtual Document Object Model)
-
DOM的本质是什么:Document Object Model 页面元素 JS表示的UI界面元素
-
DOM和虚拟DOM的区别:
- DOM是由浏览器中的JS提供功能,所以我们只能人为的使用 浏览器提供的固定的API来操作DOM对象;
- 虚拟DOM:并不是由浏览器提供的,而是我们程序员手动模拟实现的,类似于浏览器中的DOM,但是有着本质的区别;
-
为什么要实现虚拟DOM:
- JavaScript需要借助浏览器提供的DOM接口才能操作真实DOM,修改DOM经常导致页面重绘,所以一般来说,DOM操作越多,网页的性能就越差
- 真实的DOM中,过多的内容修改,会带来多次的页面重绘,极大的损耗页面的性能。
- 而在使用虚拟DOM时,不管一次修改了多少内容,最后只会发生一次页面的重绘,大大的提高了页面的性能。
- 虚拟DOM设计的核心就是用高效的js操作,来减少低性能的DOM操作,以此来提升网页性能。
-
虚拟DOM的目的:
- 虚拟DOM并不能消除原生的DOM操作,你仍然需要通过浏览器提供的DOM接口来操作真实DOM树,才能使页面发生改变。虚拟DOM的设计似乎是多此一举。
- 但是虚拟DOM带来了一个重要的优势,那就是我们可以在完全不访问真实DOM的情况下,掌握DOM的结构
- 如果我们本打算手动进行三次真实DOM操作,有了虚拟DOM结构后,把这三次DOM操作简化成了一次,这不就带来了性能上的提升
-
React中的虚拟dom
- React中使用
jsx语法定义模板时,React会用它生成一个由JavaScript描述的虚拟DOM树,并将其保存在JavaScript内存中。这个虚拟DOM树还保留了我们在模板中定义的数据和视图的绑定关系,这为React自动根据数据变化更新视图提供了可能。随后当数据发生变化时,React重新生成一个虚拟DOM树,通过对比两个虚拟DOM树的差异,React就可以知道该如何高效地更新视图。接着它就会调用原生的DOM接口,去更新真实DOM。
- React中使用
Diff算法
diff算法其实就是对DOM进行different比较的一种算法
- tree diff:新旧DOM树,逐层对比的方式,就叫做 tree diff,每当我们从前到后,把所有层的节点对比完后,必然能够找到那些 需要被更新的元素;
- component diff:在对比每一层的时候,组件之间的对比,叫做 component diff;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件的类型不 同,则立即将旧组件移除,新建一个组件,替换到被移除的位置;
- element diff:在组件中,每个元素之间也要进行对比,那么,元素级别的对比,叫做 element diff;
- key:key这个属性,可以把 页面上的 DOM节点 和 虚拟DOM中的对象,做一层关联关系;
React项目的创建
react.docschina.org/docs/create…
Create React App
npx create-react-app my-app
cd my-app
npm start
SKIP_PREFLIGHT_CHECK=true
项目启动效果图
react.docschina.org/docs/render…
1.在项目中导入两个相关的包:
// 1. 在 React 学习中,需要安装 两个包 react react-dom
// 1.1 react 这个包,是专门用来创建React组件、组件生命周期等这些东西的;
// 1.2 react-dom 里面主要封装了和 DOM 操作相关的包,比如,要把 组件渲染到页面上
import React from 'react'
import ReactDOM from 'react-dom'
2.使用JS的创建虚拟DOM节点:
// 2. 在 react 中,如要要创建 DOM 元素了,只能使用 React 提供的 JS API 来创建,不能【直接】像 Vue 中那样,手写 HTML 元素
// React.createElement() 方法,用于创建 虚拟DOM 对象,它接收 3个及以上的参数
// 参数1: 是个字符串类型的参数,表示要创建的元素类型
// 参数2: 是一个属性对象,表示 创建的这个元素上,有哪些属性
// 参数3: 从第三个参数的位置开始,后面可以放好多的虚拟DOM对象,这写参数,表示当前元素的子节点
// <div title="this is a div" id="mydiv">这是一个div</div>
var myH1 = React.createElement('h1', null, '这是一个大大的H1')
var myDiv = React.createElement('div', { title: 'this is a div', id: 'mydiv',className:"duv" }, '这是一个div', myH1)
- 使用 ReactDOM 把元素渲染到页面指定的容器中:
// ReactDOM.render('要渲染的虚拟DOM元素', '要渲染到页面上的哪个位置中')
// 注意: ReactDOM.render() 方法的第二个参数,和vue不一样,不接受 "#app" 这样的字符串,而是需要传递一个 原生的 DOM 对象
ReactDOM.render(myDiv, document.getElementById('app'))
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 创建虚拟dom节点
let myli = React.createElement('li',null,'我是li')
let myul = React.createElement('ul',{className:'list'},myli)
ReactDOM.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>,
// 渲染指定dom
myul,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();