1.react介绍
本质:React 是一个用于构建用户界面的 JAVASCRIPT 库。不是一个MVC框架,而是一个前端界面开发工具,用于构建组件化UI的库。所以顶多算是MVC中的V(view)。
特点:减少与DOM的交互。React可以与已知的库或框架很好地配合。 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。 React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
主要能做什么:1.轻松地创建用户交互界面,声明式编写UI(声明式:声明式编程的计算在运行时构建完成,命令式编程的计算在编译时构建完成,声明式是一个很大的概念,详情可以百度),2.组件化构建页面3.可以用作开发原生应用的框架 React Native
核心:虚拟DOM,Diff算法
虚拟dom和高效的渲染:React将DOM抽象为虚拟DOM,虚拟DOM其实就是用一个对象来描述DOM,通过对比前后两个对象的差异,最终只把变化的部分重新渲染,提高渲染的效率
为什么用虚拟dom,当dom反生更改时需要遍历 而原生dom可遍历属性多大231个 且大部分与渲染无关 更新页面代价太大
为啥要学:react ,Angular,Vue三大框架我更倾向Vue,原因学过的基本都清楚,不过项目要用react也没办法。
2.react的基本使用
导入基本相关库,react.js
是 React 的核心库,react-dom.js
是提供与 DOM 相关的功能,Browser.js
的作用是将 JSX 语法转为 JavaScript 语法,babel.js将es6转es5。
定义变量的方法:let和const,属于es6语法,两个都属于定义变量,const为ECMAScript带来了定义常量的能力,let用于块状作用域,类似局部变量
// 1. 导入 react import React from ‘react‘ import ReactDOM from ‘react-dom‘ const element =<h1 title="Hello, world!">Hello, world!</h1>; // 3. 渲染//ReactDOM.render() 接受两个参数,第一个为 React 组件(虚拟dom对象),第二个为组件插入的容器,第三个 参数3:回调函数 ReactDOM.render(element, document.getElementById(‘app‘))
上述属于 JSX语法,最终会被编译为 createElement() 方法
const divVD = React.createElement(‘h1‘, { title: ‘hello,word!‘ }, ‘Hello,world!‘)
样式:
直接引入 <div style={{ width: "300px" }}>{text}</div> 但可能名字不一样,如marginTop = margin-top或者
import styles from ‘../Derivative/DeritvativeList.less‘;
<div className={styles.tableList}><div>
3.JSX
为了把 HTML 模板直接嵌入到 JS 代码里面,这样就做到了模板和组件关联,但是 JS 不支持这种包含 HTML 的语法,所以需要通过工具将 JSX 编译输出成 JS 代码才能使用.
与html差异(特点):
1:如果在 JSX 中给元素添加类, 需要使用 className 代替 class ,label 的 for属性,使用htmlFor代替
2:直接使用 JS代码,直接在 JSX 中通过 {} 中间写 JS代码即可
JSX 中不能使用 if else 语句,可以用三元符代替
React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签,即组件是大写开头。
4.组件
组件:是由一个个的HTML元素组成的,概念上来讲, 组件就像JS中的函数。它们接受用户输入(props),并且返回一个React对象,用来描述展示在页面中的内容
作用:组件可以让你把UI分割为独立、可复用的模块
定义组件的两种方法:
1.函数定义
function HelloMessage(props) {
return <h1>Hello World!</h1>;
}
2.class定义
class Welcome extends React.Component {
render() {
return <h1>Hello World!</h1>;
}
}
注意:
1.组件只能有一个顶层标签,组件名必须大写,必须有返回值:jsx对象或null。
2.通过 class 创建(有状态组件) ---》场景用于一定的业务逻辑,需要操作数据, 通过 JS函数 创建(无状态组件)---》场景用于仅仅展示数据
在es6中class仅仅是一个语法糖,不是真正的类,本质上还是构造函数+原型
实现继承
// 实现继承的方式 class Studentextends Person { constructor() { // 必须调用super(), super表示父类的构造函数 super() this.name= ‘D‘ } } class Welcome extends React.Component { constructor(props) { super(props) } render() { return <h1>Hello, {this.props.name}</h1> } }
5.props和state
通常用props传递大量数据,state用于存放组件内部一些简单的定义数据
props 作用:给组件传递数据,一般用在父子组件之间 props是只读的,无法给props添加或修改属性,内容:React把传递给组件的属性转化为一个对象并交给 props
state 作用:用来给组件提供组件内部使用的数据只有通过class创建的组件才具有状态 状态是私有的,完全由组件来控制
只需更新组件的 state,然后根据新的 state 重新渲染用户界面
注意:不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!不要在 render() 方法中调用 setState() 方法来修改state的值
propTypes
作用:通过类型检查,提高程序的稳定性
使用:给类提供一个静态属性 propTypes(对象),来约束props
// 引入模块
import PropTypes from ‘prop-types‘
// ...以下代码是类的静态属性:
// propTypes 静态属性的名称是固定的!!!
static propTypes = {
initCount: PropTypes.number, // 规定属性的类型
initAge: PropTypes.number.isRequired // 规定属性的类型,且规定为必传字段
}
或者
propTypes: {
title: React.PropTypes.string.isRequired,
},
props={title:‘hello‘}
reder(){return <h>{this.props.title}</h> }
6.单向数据流
单向数据流:数据主要从父节点传递到子节点(通过props)。如果顶层(父级)的某个props改变了,React会重渲染所有的子节点
state
和
props
的区别在于前者(state)只存在于组件内部,只能从当前组件调用this.setState
修改state值(不可以直接修改this.state!
)
一般我们更新组件都是通过改变state,再附给props进行改变组件的属性值。
function FormattedDate(props) {
return <h2>现在是 {props.date.toLocaleTimeString()}.</h2>;
}
<FormattedDate date={this.state.date} />
组件沟通:最为常见的组件沟通也就是父子了。
一般情况是:* 父组件更新组件状态 -----props-----> 子组件更新
另一种情况是:* 子组件更新父组件状态 -----需要父组件传递回调函数-----> 子组件调用触发
子组件更新父组件:父组件通过props传递一个回调函数到子组件中,这个回调函数可以更新父组件,子组件就是通过触发这个回调函数,从而使父组件得到更新。
回调函数是什么?很多人看完过后回调函数是啥都不知道。
回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调,这么一说大家应该有印象了。
说完单向数据流,也说下双向绑定:值和UI双绑定,Angular2用的就是双向绑定
7.组件的生命周期
生命周期函数:从组件被创建,到组件挂载到页面上运行,再到页面关闭组件被卸载,这三个阶段总是伴随着组件各种各样的事件,那么这些事件,统称为组件的生命周期函数!
组件的生命周期包含三个阶段:创建阶段(Mounting)、运行和交互阶段(Updating)、卸载阶段(Unmounting)
创建阶段(Mounting):该阶段的函数只执行一次
constructor() 1 获取props 2 初始化state 通过 constructor() 的参数props获取
class Hello extends React.Component { constructor(props) { // 获取 props super(props) // 初始化 state this.state = { count: props.initCount } } } // 初始化 props // 语法:通过静态属性 defaultProps 来初始化props Hello.defaultProps = { initCount: 0 };
componentWillMount() :组件被挂载到页面之前调用,其在render()之前被调用,因此在这方法里同步地设置状态将不会触发重渲染
注意:无法获取页面中的DOM对象 注意:可以调用 setState() 方法来改变状态值
用途:发送ajax请求获取数据 ,
componentWillMount() { console.warn(document.getElementById(‘btn‘)) // null this.setState({ count: this.state.count + 1 }) }
render() :渲染组件到页面中,无法获取页面中的DOM对象 不要在render方法中调用 setState() 方法,否则会递归渲染
render() { console.warn(document.getElementById(‘btn‘)) // null return ( <div> <button id="btn" onClick={this.handleAdd}>打豆豆一次</button> </div> ) }
componentDidMount() :组件已经挂载到页面中 可以进行DOM操作,比如:获取到组件内部的DOM对象 可以发送请求获取数据 可以通过 setState() 修改状态的值
注意:在这里修改状态会重新渲染 ,用于比较多还是获取url后面带过来的参数再重新绚烂页面
componentDidMount() { // 此时,就可以获取到组件内部的DOM对象 console.warn(‘componentDidMount‘, document.getElementById(‘btn‘)) const { dispatch } = this.props; dispatch({ type: ‘deriveEventRule/DataTypes‘, }); const query = this.props.location.search; const arr = query.split(‘&‘); const eventid = arr[0].substr(9); dispatch({ type: ‘deriveEventAct/formSaveDeriveEventData‘, payload: { eventId: eventid}, }); }
运行和交互阶段(Updating):该阶段的函数执行多次 每当组件的props或者state改变的时候,都会触发运行阶段的函数
componentWillReceiveProps() :组件接受到新的props前触发这个方法
参数:当前组件props值 可以通过 this.props 获取到上一次的值
使用:若你需要响应属性的改变,可以通过对比this.props和nextProps并在该方法中使用this.setState()处理状态改变
注意:修改state不会触发该方法
componentWillReceiveProps(nextProps, nextState) { console.warn(‘newProps‘, nextProps) console.warn(‘newstate‘, nextState) }
shouldComponentUpdate() :返回值决定是否重新渲染组件,返回true重新渲染,否则不渲染
优势:通过某个条件渲染组件,降低组件渲染频率,提升组件性能
说明:如果返回值为false,那么,后续render()方法不会被调用
场景:根据随机数决定是否渲染组件 // - 第一个参数:最新属性对象 // - 第二个参数:最新状态对象
shouldComponentUpdate(nextProps, nextState) { return true}
componentWillUpdate() :组件将要更新 参数:最新的属性和状态对象
注意:不能修改状态 否则会循环渲染 componentWillUpdate(nextProps, nextState) { }
render() :渲染
作用:重新渲染组件,与Mounting阶段的render是同一个函数 注意:这个函数能够执行多次,只要组件的属性或状态改变了,这个方法就会重新执行
componentDidUpdate():组件已经被更新
参数:旧的属性和状态对象 componentDidUpdate(prevProps, prevState) { }
卸载阶段(Unmounting) 组件销毁阶段:组件卸载期间,函数比较单一,只有一个函数,这个函数也有一个显著的特点:组件一辈子只能执行依次! 使用说明:只要组件不再被渲染到页面中,那么这个方法就会被调用( 渲染到页面中 -> 不再渲染到页面中 )
componentWillUnmount():在卸载组件的时候,执行清理工作
如:清除定时器 清除componentDidMount创建的DOM对象
state和setState 使用 setState() 方法修改状态,状态改变后,React会重新渲染组件 注意:不要直接修改state属性的值,这样不会重新渲染组件
使用:1 初始化state 2 setState修改state
constructor(props) { super(props) // 正确姿势!!!
// -------------- 初始化 state --------------
this.state = { numcount: props.num } }
this.setState({ count: this.state.numcount + 1 })
8.组件绑定
1 通过React事件机制 onClick 绑定 推荐 <input type="button" value="触发单击事件" onClick={this.handleCountAdd} onMouseEnter={this.handleMouseEnter} />
2 JS原生方式绑定(通过 ref 获取元素),有时候我们可能需要直接获取真实的dom节点,而不是虚拟dom。组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM。只有当它插入容器以后,才会变成真实的 DOM 。采用diff算法将虚拟 DOM 上发生变动的部分,反映在真实 DOM上。
绑定一个 ref 属性到 render 的返回值上:<input ref="myInput" />
这样我们就获取该真实dom:
var input = this.refs.myInput;
var inputValue = input.value;
事件绑定中的this
1 通过 bind 绑定
// 自定义方法: handleClick(arg1, arg2) { this.setState({ msg: ‘点击事件修改state的值‘ + arg1 + arg2 }) } render() { return ( <div> <button onClick={ // 无参数 // this.handleClick.bind(this) // 有参数 this.handleClick.bind(this, ‘abc‘, [1, 2]) }>点击处理</button> <h1>{this.state.msg}</h1> </div> ) } 在构造函数中使用 constructor() { super() this.handleBtnClick = this.handleBtnClick.bind(this) } // render() 方法中: <button onClick={ this.handleBtnClick }>点击处</button
2 通过 箭头函数 绑定
<input type="button" value="在构造函数中绑定this并传参" onClick={ () => { this.handleBtnClick(‘参数1‘, ‘参数2‘) } } />
handleBtnClick(arg1, arg2) { this.setState({ msg: ‘在构造函数中绑定this并传参‘ + arg1 + arg2 }); }
9.受控组件
在React中,可变的状态通常保存在组件的state中,并且只能用 setState() 方法进行更新. React根据初始状态渲染表单组件,接受用户后续输入,改变表单组件内部的状态。 因此,将那些值由React控制的表单元素称为:受控组件。
受控组件的特点: 表单元素 由React通过JSX渲染出来 由React控制值的改变,也就是说想要改变元素的值,只能通过React提供的方法来修改
只能通过setState来设置受控组件的值
// 模拟实现文本框数据的双向绑定 <input type="text" value={this.state.msg} onChange={this.handleTextChange}/>
// 当文本框内容改变的时候,触发这个事件,重新给state赋值 handleTextChange = event => { console.log(event.target.value) this.setState({ msg: event.target.value }) }
10.Ajax
通过 Ajax 请求从服务器获取数据,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI
class UserUpdate extends React.Component { constructor(props) { super(props); this.state = {username: ‘‘, lastGistUrl: ‘‘}; } componentDidMount() { this.serverRequest = $.get(this.props.source, function (result) { var lastGist = result[0]; this.setState({ username: lastGist.owner.login, lastGistUrl: lastGist.html_url }); }.bind(this)); } componentWillUnmount() { this.serverRequest.abort(); } render() { return ( <div> {this.state.username} 用户地址: <a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a> </div> ); } } ReactDOM.render( <UserUpdate source="https://localhost:8080/user" />, document.getElementById(‘example‘) );
原文地址:https://www.cnblogs.com/tansuiqing/p/10176293.html