(React 框架)React技术
1、简介
React 是Facebook 开发并开源的前端框架
当时他们的团队在市面上没找到合适的MVC 框架,就自己写一个 JS 框架,用来架设 instagram(图片分享社交网路),2013年开源
React 解决的是前端MVC 框架中的view 视图层的问题。
2、Virual DOM
DOM(文档对象模型Document Object Model)
将网页内所有内容映射到一颗树形结构的层级对象模型上,浏览器提供对DOM的支持,用户可以是用脚本调用DOM API 来动态的修改DOM 结点,从而达到修改网页的目的,这种修改是浏览器中完成的,浏览器会根据DOM 的改变重绘 改变DOM 结点部分。
修改DOM 重新渲染代价太高,前端框架为了提高效率,尽量减少DOM 的重绘,提出了Virtual DOM,所有的修改都是在现在的Cirtual DOM 上完成的,通过比较算法,找出浏览器DOM 之间的差异,使用这个差操作DOM,浏览器只需要渲染这部分变化就行了
React 实现了DOM Diff 算法,可以高效的对比Virtual DOM 和DOM 之间的差异。
3、支持JSX 语法
jsx 是 一种JavaScript 和XML 混写的语法,是JavaScript的扩展
XML 被设计为传输和存储数据,其焦点是数据的内容。 HTML 被设计用来显示数据,其焦点是数据的外观
4、测试程序
修改 /src/index.js:
修改 根目录下的 index.html:在html文件中,提供一个div标签,同时提供id ,使得react可以通过id找到
启动 npm start 后
程序解释:
import React from "react"; 导入 react 模块
import ReactDom from "react-dom";导入react 的DOM 模块
class Root extends React.Component :组件类定义,从React.Component 类上继承,这个类生成JSXElement对象即React元素。
render()渲染函数,返回组件中渲染的内容,注意,只能返回唯一一个顶级元素回去
ReactDom.render(<Root/>, document.getElementById("root")):第一个参数是JSXElement对象,第二个是DOM的Element元素,将React元素添加到DOM的Element 元素中并渲染。 也可以使用name,如果Element元素的属性定义了name,document.getElementsByName("newroot")
(不推荐使用)还可以使用React.createElement创建react元素,第一参数是react组件或者一个HTML的标签明后才能(如:div,span)
增加一个子元素: (这就是SPA网页,单页应用,普通的爬虫就只能爬基本页面了,因为此时,css和js分割开了) 图二是 DOM数,虚拟DOM 是react的事
注意:
- React组件的render函数return ,只能是一个顶级元素
- JSX语法是XML,要求所有元素必须闭合,注意<br />
JSX 规范:
- 约定标签中首字符小写就是html标记,首字母大写就是组件
- 要求严格的HTML标记,要求所有标签都必须是闭合的,br也应该写成<br /> ,/ 前留一个空格
- 单行省略小括号,多行使用小括号
- 元素有嵌套,建议多行,注意缩进
- JSX表达式:表达式使用{ } 括起来,如果大括号内使用了引号,会当做字符串处理,例如 <div>{'2>1?true:fase'}</div>
5、组件状态 state
每一个 React组件 都有一个状态属性 state,它是一个JavaScript对象,可以为他定义属性来保存值
如果状态变化了,会触发UI 的重新渲染,使用setState()方法可以修改stste值
注意:state是每个组件自己内部使用的,是组件自己的属性
依然修改/src/index.js
解决方式1:
可以使用延时函数,setTimeout(()=> this.setState({ p1: ' jerry' }), 3000) 是一个异步函数
但是 不要这样使用,把setState放在别的地方
复杂状态的例子
浏览器结果:
========》点击后
div的id 是t1 ,鼠标按下事件捆绑了一个函数,只要鼠标按下就出触发调用 getEventTrigger 函数,浏览器会送给他一个参数 event, event是事件对象,当事件触发时,event 包含触发这个时间的对象
HTML DOM的JavaScript 事件
使用React 实现上面的传统的HTML
分析:
Toggle类
它有自己的state属性
当render完成后,网页上有一个div标签,div标签对象捆绑了一个click 时间的处理函数,div标签内有文本内容
如果通过点击左键,即触发了一个click方法关联的handleClick 函数,在这个函数里将状态改变
状态值state,的改变 将引发render重绘
如果组件自己的state变了,只会触发自己的render方法重绘。
注意:
{this.handleClick.bind(this)} 不能外加括号
this.handleClick.bind(this) 一定要绑定this,否则当触发捆绑的函数时,this是函数执行的上下文决定的,this已经不是触发事件的对象了。
console.log(event.target.id) 取回的产生的对象的id,但是这不是我们封装的组件对象,所以
console.log(event.target ===this) 是false,所以这里一定要使用this,而这个this是通过绑定来的
event.target 就是生成的一个块 <div>-----</div>
React中的事件:
使用小驼峰
使用JSX表达式,表达式中指定事件处理函数
不能使用return false 如果要组织事件默认行为,使用event。preventDefault()
6、属性props:
props 就是组件的属性properties。
把React组件当作标签使用,可以为其增加属性,如下:
<Toggle name="school" parent={this} />
为上面的Toggle 元素增加属性:
- name="school" ,这个属性 会作为一个单一的对象传递给组件,加入到组件的porps 属性中
- parent = {this} 注意这个this是在Root 元素中,指的是Root组件本身
- 在Root中为使用JSX 语法为Toggle 增加子元素,这些子元素也会被加入到Toggle组件的props.childern中
尝试修改props 的属性值,会抛出 TypeError:cannot assign to read only property “name” of object # <Object>异常
应该说, state是私有 private 的属于组件自己的属性,组件外无法直接访问,可以修改state但是建议使用setState方法
props是公有public属性组件外也可以访问,但是只读。
7、构造器constructor:
使用ES 6 的构造器,要提供一个参数props, 并把这个参数使用super传递给父类
8、组件的生命周期:
组件的生命周期可分为三个状态
- Mounting :已 插入真实的DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实的DOM
组件的生命周期状态,说明在不同时机访问 组件,组件正在处于生命周期的不同转台上
在不同的生命周期状态访问,就产生不同的方法。
- 装载组件触发
- componentWillMOunt 在渲染前调用, 在客户端---也在服务端。只会在装载之前调用一次。
- componentDidMount 在第一次渲染后调用,只在客户端,之后组件已经生成了对应的DOM 结构可以通过this.getDOMNode()来进行访问,如果你想和其他JS 框架一起使用,可以在这个方法中调用setTimeout,setInterval或者发送AJAX 请求等操作(防止异步操作阻塞UI),只在装载完成后调用一次,在render之后
- 更新组件触发,这些方法不会再首次render组件的周期调用
- componentWillReceiveProps(nextProps)在组件接收到一个新的prop的时候,调用,这个方法在初始化render时不会被调用
- shouldComponentUpdate(nextProps,nextState)返回一个布尔值,组件接收到新的props或者state时被调用,在初始化时或者使用forceUpdate时不会被调用
- 可以在你确认不需要更新组件时 使用
- 如果设置为false,就是不允许更新组件,那么componentWillUpdate,componentDidupdate不会执行
- componentWillUpdate(nextProps, nextState) 在组件接收到新的props或者state但还没有render时被调用,在初始化时不会被调用
- componentDidUpdate(prevProps,prevState)在组件完成更新后立即被调用,在初始化时不会被调用
- 卸载组件触发
- componentWillUnmount 在组件从DOM中移除的时候,立即被调用
有图可知:
constructor 构造器是最早执行的函数
触发更新生命周期函数,需要更新 state 或 props
因此,重写编写 /scr/index.js
构造两个组件,在子组件SUb中,加入所有生命周期函数
测试:装载,卸载组件的生命周期函数。
1 import React from 'react'; 2 import ReactDom from 'react-dom'; 3 4 5 class Sub extends React.Component { 6 constructor (props){ 7 console.log("sub constructor") 8 super(props); 9 this.state = {count:0}; 10 } 11 handleClick(event) { 12 this.setState({count:this.state.count + 1}); 13 } 14 render() { 15 console.log('sub render'); 16 return ( 17 <div id="sub" onClick={this.handleClick.bind(this)}> 18 Sub's count = {this.state.count} 19 </div> 20 ); 21 } 22 23 componentWillMount() { 24 console.log('sub componentwillmont') 25 } 26 27 componentDidMount() { 28 console.log('sub componentdidmount') 29 } 30 componentWillUnmount(){ 31 console.log('sub componentdidunmount') 32 } 33 34 35 } 36 37 38 class Root extends React.Component{ 39 constructor (props) { 40 console.log("root constructor") 41 super(props); 42 this.state = {}; 43 44 } 45 render (){ 46 return( 47 <div> 48 <Sub /> 49 </div> 50 ) 51 } 52 } 53 54 ReactDom.render(<Root/>, document.getElementById("newroot"));
结果:
增加,更新组件函数:
演示 props的改变,为Root增加一个click事件处理函数
1 import React from 'react'; 2 import ReactDom from 'react-dom'; 3 import { runInAction } from 'mobx'; 4 5 6 class Sub extends React.Component { 7 constructor (props){ 8 console.log("sub constructor") 9 super(props); 10 this.state = {count:0}; 11 } 12 handleClick(event) { 13 this.setState({count:this.state.count + 1}); 14 } 15 render() { 16 console.log('sub render'); 17 return ( 18 <div style={{height:200 + "px", color:'red', backgroundColor:"#aaffff"}}> 19 <a id='sub' onClick={this.handleClick.bind(this)}> 20 sub'x count = {this.state.cont} 21 </a> 22 </div> 23 ); 24 } 25 26 componentWillMount() { 27 //constructor 之后,第一次render之前 28 console.log('sub componentwillmont') 29 } 30 31 componentDidMount() { 32 // 第一次render之前 33 console.log('sub componentdidmount') 34 } 35 componentWillUnmount(){ 36 //清理工作 37 console.log('sub componentdidunmount') 38 } 39 40 componentWillReceiveProps(nexProps) { 41 // props更新时,街道新的props,交给shouldComponentUpdate 42 // props组件内只读,只能从外部改变 43 console.log(this.props) 44 console.log(nexProps) 45 console.log('sub com---receiveProps', this.state.count) 46 } 47 48 shouldComponentUpdate(nexProps, nextState) { 49 // 是否组件更新,props 或state 方式改变,返回布尔值,true才会更新 50 console.log('sub shuold--------', this.state.count, nextState) 51 return true 52 53 } 54 55 componentWillUpdate(nexProps, nextState) { 56 //同意更新后,真正更新前,之后调用rener 57 console.log('will update', this.state.count, nextState) 58 } 59 60 componentDidUpdate(prevProps, prevState){ 61 //同意更新后,真正更新后,在render在之后调用 62 console.log('did Update', this.state.count, prevState) 63 } 64 65 } 66 67 68 class Root extends React.Component{ 69 constructor (props) { 70 console.log("root constructor") 71 super(props); 72 this.state = {flag:true, name:'root'}; 73 74 } 75 handleClick(event){ 76 this.setState({ 77 flag:!this.state.flag, 78 name:this.state.flag ? this.state.name.toLowerCase() : this.state.name.toUpperCase() 79 }) 80 } 81 render (){ 82 return( 83 <div id='t1' onClick={this.handleClick.bind(this)}> 84 my name is {this.state.name} 85 <Sub /> {/* 父组件的render,会引起下一级组件的更新流程,导致props重新发送,即使子组件props没有改变*/} 86 </div> 87 ) 88 } 89 } 90 91 ReactDom.render(<Root/>, document.getElementById("newroot"));
componentWillMount 第一次装载,在首次render之前,例如控制state,props
conpinentDidMount 第一次装载结束,在首次render之后,
注:++ 原位置自动加1 ,+= 是调到栈里,加1 再返回
10、无状态组件
React从15.0 开始支持无状态组件,定义如下:
无状态组件,也叫函数式组件
开发中,很多情况下,组件其实很简单,不需要state状态,也不需要使用生命周期函数,无状态组件很好的满足了需要
无状态组件函数应该提供一个参数props,返回一个React元素
无状态组件函数本身就是 render函数
改写上面的代码:箭头函数
11、高阶组件
如果要在上例的Root组件进行增强怎么办,例如将Root 组件的div 外部在加入其它的 div
简化Wrapper
1 import React from 'react'; 2 import ReactDom from 'react-dom'; 3 // let Wrapper = function (Component/*传入组件*/, props) { 4 // return ( 5 // <div> 6 // {props.schoolName} 7 // <hr /> 8 // <Component /> 9 // </div> 10 // ) 11 // } 12 // 柯里化 13 let Wrapper = function (Component) { 14 function _wrapper(props) { 15 return ( 16 <div> 17 {props.schoolName} 18 <hr /> 19 <Component /> 20 </div>) 21 } 22 return _wrapper 23 } 24 // 第一次简化 25 let Wrapper = function(Component) { 26 return function _wrapper(props){ 27 return ( 28 <div> 29 {props.schoolName} 30 <hr /> 31 <Component /> 32 </div>) 33 } 34 } 35 //第二次简化 36 let Wrapper = function(Component) { 37 return (props) => { 38 return ( 39 <div> 40 {props.schoolName} 41 <hr /> 42 <Component /> 43 </div>) 44 } 45 } 46 // 第三次简化 47 let Wrapper = (Component) =>(props) => 48 ( 49 <div> 50 {props.schoolName} 51 <hr /> 52 <Component /> 53 </div> 54 ) 55 56 //整理 57 let Wrapper = (Component) =>(props) => <div> {props.schoolName} <hr /> <Component /> </div> 58 71 let Root = (props) => <div>Root</div> 72 73 // 返回新组件 74 let NewComp = Wrapper(Root) 75 ReactDom.render(<NewComp schoolName="jerry"/>, document.getElementById('newroot'))
测试:加入子组件(无状态组件)
12、装饰器
新版的ES2016中增加了装饰器的支持,因此可以使用装饰器来改造上面的代码。
装饰器是装饰函数,类,不能对一个变量装饰(这样是不对的)
ES 2016 的装饰器只能装饰类,所以,将Root改写成类
让Root 也显示schoolName
13、带参装饰器
想给装饰器函数增加一个id 参数
1 import React from 'react'; 2 import ReactDom from 'react-dom'; 3 4 let Wrapper = (id, Component) =>(props) => 5 ( 6 <div id={id}> 7 {props.schoolName} 8 <hr /> 9 <Component /> 10 </div> 11 ) 12 13 // 柯里化 14 let Wrapper = id => Component => (props) => 15 ( 16 <div id={id}> 17 {props.schoolName} 18 <hr /> 19 <Component {...props}/> 20 </div> 21 ) 22 23 24 @Wrapper('123') // Root = wrapper("123")(Root) = (props) => ..... 25 26 class Root extends React.Component { 27 render(){ 28 return <div>Root ---- {this.props.address}</div> 29 } 30 } 31 32 ReactDom.render(<Root schoolName="jerry" address="somewhere"/>, document.getElementById('newroot'))
转载于:https://www.cnblogs.com/JerryZao/p/9986008.html
(React 框架)React技术相关推荐
- 四:以理论结合实践方式梳理前端 React 框架 ——— React 高级语法
事件处理 react 内置组件的事件处理 react 内置组件是指 react 中已经定义好的,可以直接使用的如 div.button.input 等与原生 HTML 标签对应的组件 <!DOC ...
- React框架简介(JSX语法、组件、虚拟DOM渲染)
目录 React框架 为什么要学习React React特点 React核心 JSX语法 语法详解 React开发过程 实际DOM 虚拟DOM React组件 函数组件 类组件 虚拟DOM渲染过程 R ...
- 移动开发者如何更好地学习 React Native? | 技术头条
作者 | 魔笛 责编 | 郭芮 2015年3月,Facebook正式发布react-native,只支持iOS平台:2015年9月,Facebook发布了React Native for Androi ...
- 前端框架React Js入门教程【转】
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- [译] 项目什么时候需要 React 框架呢?
本文讲的是[译] 项目什么时候需要 React 框架呢?, 原文地址:When Does a Project Need React? 原文作者:CHRIS COYIER 译文出自:掘金翻译计划 译者: ...
- React项目-点餐后台管理系统-react框架实现后台管理系统(包含权限处理)--新手入坑必看!(一)
点餐后台管理系统(react) 一.前言 二.项目介绍 三.相关技术 四.项目实现的功能 4.1.功能分析 4.2.项目结构 4.3.axios封装及mock数据 4.3.1.axios封装 4.3. ...
- 十一:以理论结合实践方式梳理前端 React 框架 ———框架架构
前言书明观念 从第一代码农写下第一行代码开始到上个世纪的80年代的软件危机,码农一直在考虑一个问题,怎么让代码写起来更容易.更简单.更舒适?抛开大牛.大神(大牛.大神哪那么容易找到啊 _-)级别的人员 ...
- 从0实现react框架,React Fiber架构和Fiber Diff算法
react框架是目前最为流行的前端框架之一,尤其在很多大厂,应用更为广泛.相对于一些mvvm框架,react上手需要一定的技术基础,但掌握后,编码体验和性能是很不错的.react整体思想是函数式编程, ...
- React框架的学习
前端-React框架 一.环境搭建 使用 create-react-app 快速构建 React 开发环境 二.react目录以及文件 目录结构 组件基础模板 三.React的知识点 1.JSX语法 ...
最新文章
- 解决日常bug的正确姿势
- MongoDB 4.0 事务实现解析
- Dumpzilla工具第615行bug的解决办法
- labview求n阶乘的和_LABVIEW求1到N所有数的阶乘之和
- Ring3下实现进程保护,不用hook
- matlab复数方程的根,matlab解一元三次方程,得到的都是复数根。
- Html5中的Video元素使用方法
- html中如何写平方根等,平方根的符号怎么打出来 电脑打字,平方根的符号怎样打出来?...
- 函数式编程语言:LISP/Scheme 小语种简介
- 正则表达式匹配 任意字符和空格的一个简便方式?
- vue中使用setTimeout
- (纯CSS)悬浮一个元素,让另一个元素改变属性
- 7-1 defer调用
- Spring 整合 Redis
- Win8 MSDN 简中/繁中/英文正式版下载(微软官方原版)
- 【网络技术题库整理5】网络安全技术
- snownlp抛出错误_9snowNLP常见用法
- STM32CubeMX安装(全图文安装步骤,一步不落下)
- mysql 未找到 WinSxS_win7的winsxs文件清理方法
- vue二级路由和重定向问题