一、react的基本概念
1.1 react的定义:
根据官方文档介绍,react是一个只关注用户界面的js库(说白了就是将数据渲染成页面的一个js库),关于js库我们并不陌生,如jquery。当然学习react只学习react.js是不够的,还要学习他的衍生物,如react-router,redux等等,他们组合在一起被称作为react全家桶或者技术栈。
1.2 react的特点:
1.2.1 声明式,所谓的声明式就好比,在之前用jquery时我们需要操作dom,很费劲,而声明式就可以做到你告诉react我们要更新dom,让react去操作,我们只需要告诉他就行,即为应用的每一个状态设计简洁的视图,在数据改变时react也可以高效的更新界面。因此我们只要更新数据,就可以得到我们想要的界面。
1.2.2 组件化,组件化就是将独立的功能抽离出去当作一个组件,最后将这些组件组合到一起形成一个系统,每个组件都有其特定的内部状态。
1.2.3 一次学习,随处编写,是因为react不仅可以编写web应用,还可以编写native应用叫做react-native,编写的程序可以运行在手机上)。
1.2.4 高效,react是高效率的,就其原因有,他采用虚拟dom技术,不是直接操作dom,这样可以减少更新的次数。其次是dom diff算法,最小化页面的重新绘制,这样可以减少更新的区域。
1.2.5 单向数据流,此概念较抽象,后面会逐渐解析到
二、react的基本用法(此法只是为了了解react的基本用法,真实项目中不会这么用)
2.1 通过前面的了解,我们知道了react是一个js库,既然是一个js库,我们只要通过script标签引入便可以使用它,可以通过cdn的方式引入,下面根据官方文档示例简单体会一下react的神奇之处。如图,用jsx来编码 image.png,新建一个项目,结构如下: QQ图片20190213230035.png
打开浏览器,可以看到如下结果:虚拟dom被渲染到真实dom中了。 image.png ,上面引入了三个库,一个是react的核心库,一个是react-dom是基于react的一个专门操作dom的扩展库。一个是babel库,用于将jsx(是js的扩展语法)代码转为js代码。
三、虚拟dom
react提供了创建虚拟dom的方法React.createElement, 例如创建一个虚拟h1,React.createElement('h1', {id: 'myTitle'}, 'hello react'),如下面的代码:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>react-demo1</title>
</head>
<body>
<div id="root">
</div>
<div id="test">
</div>
<!--react的核心库-->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!--是基于react的专门操作dom的扩展库-->
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script type="text/javascript">
var msg = 'hello React'
var msgId = "Box"
const vDom1 = React.createElement('h1', {id: msgId.toUpperCase()}, msg.toLowerCase())
ReactDOM.render(vDom1, document.getElementById('root'))
</script>
<script type="text/babel">
var msg = 'hello React'
var msgId = "Box"
const vDom2 = <h3 id={msgId.toLowerCase()}>{msg.toUpperCase()}</h3> // 这是jsx的语法,用起来简单,但最终还是成React.createElement执行
// 这里虚拟dom的h3最终会转化为真实dom的h3, 也就是说虚拟dom和真实dom是一一对应的。
var realDom = document.getElementById('test')
debugger
ReactDOM.render(vDom2, document.getElementById('test'))
</script>
</body>
</html>
分别用创建虚拟dom的方式和jsx的方式进行react的渲染,都可以将创建的标签渲染到页面中,其实jsx的方式最终也是转化为了React.createElement来执行的。如下:
image.png
那么虚拟dom和真实dom有啥样的关系?首先创建一个最简单的虚拟dom,
const vDom = React.createElement('h1', {id: 'title'}, 'react技术栈')
console.log(vDom ) // 得到如下属性:
{$$typeof: Symbol(react.element), type: "h1", key: null, ref: null, props: {…}, …}
$$typeof: Symbol(react.element)
key: null
props: {id: "title", children: "react技术栈"}
ref: null
type: "h1"
_owner: null
_store: {validated: false}
_self: null
_source: null
__proto__: Object
// 其次获取一个真实的dom,
const div = document.getElementById('box)
可以得到div dom对象的属性如下:
accessKey: ""
align: ""
assignedSlot: null
attributeStyleMap: StylePropertyMap {size: 0}
attributes: NamedNodeMap {0: id, id: id, length: 1}
autocapitalize: ""
baseURI: "file:///C:/Users/nan/Desktop/react-demo1/index.html"
childElementCount: 0
childNodes: NodeList [text]
children: HTMLCollection []
classList: DOMTokenList [value: ""]
className: ""
clientHeight: 0
clientLeft: 0
clientTop: 0
clientWidth: 472
contentEditable: "inherit"
dataset: DOMStringMap {}
dir: ""
draggable: false
firstChild: text
firstElementChild: null
hidden: false
id: "test"
innerHTML: "↵↵ "
innerText: ""
inputMode: ""
isConnected: true
isContentEditable: false
lang: ""
lastChild: text
lastElementChild: null
localName: "div"
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: script
nextSibling: text
nodeName: "DIV"
nodeType: 1
nodeValue: null
nonce: ""
offsetHeight: 0
offsetLeft: 8
offsetParent: body
offsetTop: 85
offsetWidth: 472
onabort: null
onauxclick: null
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onblur: null
oncancel: null
oncanplay: null
oncanplaythrough: null
onchange: null
onclick: null
onclose: null
oncontextmenu: null
oncopy: null
oncuechange: null
oncut: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
ondurationchange: null
onemptied: null
onended: null
onerror: null
onfocus: null
ongotpointercapture: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onloadeddata: null
onloadedmetadata: null
onloadstart: null
onlostpointercapture: null
onmousedown: null
onmouseenter: null
onmouseleave: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onpaste: null
onpause: null
onplay: null
onplaying: null
onpointercancel: null
onpointerdown: null
onpointerenter: null
onpointerleave: null
onpointermove: null
onpointerout: null
onpointerover: null
onpointerup: null
onprogress: null
onratechange: null
onreset: null
onresize: null
onscroll: null
onsearch: null
onseeked: null
onseeking: null
onselect: null
onselectstart: null
onstalled: null
onsubmit: null
onsuspend: null
ontimeupdate: null
ontoggle: null
onvolumechange: null
onwaiting: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
onwheel: null
outerHTML: "<div id="test">↵↵ </div>"
outerText: ""
ownerDocument: document
parentElement: body
parentNode: body
prefix: null
previousElementSibling: div#root
previousSibling: text
scrollHeight: 0
scrollLeft: 0
scrollTop: 0
scrollWidth: 472
shadowRoot: null
slot: ""
spellcheck: true
style: CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
tabIndex: -1
tagName: "DIV"
textContent: "↵↵ "
title: ""
translate: true
__proto__: HTMLDivElement
通过对比,很明显的知道虚拟dom对象要比真实dom轻量很多。虚拟dom只有很少的属性。而且真实dom的更改都会引起页面的重绘,而虚拟dom在渲染在真实dom之前是不会重绘页面的,这就是虚拟dom高效的原因。
四,jsx(全称为javascript xml)
- 首先jsx是一种语法,是react定义的一种类似与xml的js扩展语法:xml + js
- 作用: 用来创建react虚拟dom元素对象,之前就提到过,最终会转化为React.createElement执行,他的特点如下:
1.标签名任意(不仅可以写html的标签,而且还可以自定义标签),比如:
const vDom = <div>你好 react</div> // 这种写法不能加单引号或者双引号,最终产生的是一个对象
const vDom2 = <MyReact></MyReact> // 这种标签叫做组件标签
2.标签属性任意(HTML标签属性或者其他属性)
3.语法规则(遇到< 开头的代码,以标签的语法解析:html同名标签转为html同名元素其他标签需要特别解析。遇到{ 开头的代码以js语法解析,标签中的js代码必须用{}包含)
通过以上的了解,这里做一个简单的示例:(动态的展示列表数据)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>react-demo1</title>
</head>
<body>
<div id="root">
</div>
<!--react的核心库-->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!--是基于react的专门操作dom的扩展库-->
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script type="text/babel">
/**
* 有几个问题:
* 1.展示一个列表,那么数据结构应为list,这里定义一个名为persons的数组作为list
* 2. 如何将数据的数组转化为标签的数组? 利用数组的map方法,map可以由返回值组成一个新的数组
* 3. react要求列表数据需要一个唯一的key
*/
// 定义列表数据
let persons = ['唐僧','孙悟空', '猪八戒', '沙参']
// 创建虚拟dom,列表用ul li来呈现
// 注意,一旦有嵌套的标签就用()包含
const ul = (
persons.map((name, index) => <li key={index}>{name}</li>)
)
// 将虚拟dom渲染到真实dom中
ReactDOM.render(ul, document.getElementById('root'))
</script>
</body>
</html>
得到的效果如下:
image.png
从以上的这个例子可以得出几个问题,1. 需要什么样的数据结构,2.如何将数据转化为标签数据。
五,模块与组件,模块化与组件化
1.模块:向外提供提供特定功能的js程序,一般一个 js 文件就是一个模块(一般模块内部有数据,简单理解就是变量,和对数据的操作,简单理解就是函数),模块可以达到复用js,简化js的编写,提高js的运行效率。
- 组件: 用来实现特(局部)功能效果的代码集合(html,css,js),简单说就是一个界面的局部功能模块,既然是界面功能,那么就必须包含html/css/js三要素
3.模块化: 就是指在编写项目的时候是不是以模块的方式编写的,是,就是模块化项目,不是,就不算模块化项目
- 组件化: 形容项目的编码方式,一个项目是由各个组件组合而成,则这个项目就是组件化项目。
以上就是react入门要了解的概念。
网友评论