React学习记录
这里写自定义目录标题
React学习记录
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
React 特点
1.声明式设计 −React采用声明范式,可以轻松描述应用。
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
3.灵活 −React可以与已知的库或框架很好地配合。
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
React 项目创建
$ create-react-app my-app
$ npm start
项目目录结构
my-app/
README.md
node_modules/
package.json
.gitignore
public/
favicon.ico
index.html
manifest.json
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
my-app下
public为网页主界面和相关资源:
1.index.html为整个项目的根,可改变项目title等
2.manifest.json配置应用的图标,名称等信息
其他为配置需要的资源
src为主要的项目编写目
1.App.js与App.css 一般作为主组件,通过这个组件定义项目布局等
2.index.js与index.css 通过ReactDOM.render vdom渲染至真实dom树的过程,一般只调用App.js组件
3.可在目录下创建component目录进行组件编写
React 渲染
通过ReactDOM.render vdom渲染至真实dom树
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
React JSX
不一定要使用JSX,但是使用起来会很方便
JSX, 一种 JavaScript 的语法扩展。可以简单的认为HTML与js 的合并(一些Html标识符如class被替代为className)
1.在JSX中写js代码,需写在{}中
2.不能使用ifelse 可用三元运算符替代
3.样式文件通过import导入
实例Header.jsx
import React, { Component , Fragment} from "react";
import './Header.less'
class Header extends Component{
constructor(props) {
super(props);
this.state = {
value :''
}
}
render(){
return (
<div className="header">
<span>ToDoList</span>
<form>
<input
type="text"
placeholder="添加ToDo"
value={this.state.value}
onChange={this.handleInputChange.bind(this)}
onKeyPress={this.keyPress.bind(this)}/>
</form>
</div>
)
}
handleInputChange(e) {
this.setState({
value : e.target.value
})
}
keyPress(e){
if (e.which !== 13) return
this.props.sonMess(this.state.value);
this.setState({
value : ''
})
e.preventDefault();
}
}
export default Header;
React 组件
两种方式来创建组件
1.通过函数创建
function HelloMessage(props) {
return <h1>Hello World!</h1>;
}
2.通过Es6 创建
class Welcome extends React.Component {
render() {
return <h1>Hello World!</h1>;
}
}
需导入import React, { Component , Fragment} from “react”;
最后将组件export default State出来 ,这样别的组件可以调用
传值方式
父传子:使用 this.props 对象
function HelloMessage(props) {
return <h1>Hello {props.name}!</h1>;
}
<HelloMessage name="Runoob"/>;
子串父:使用this.props对象 但是只能通过函数,函数传参数
class Task extends Component{
render(){
return (
<input type="checkbox" onChange={this.stateChange.bind(this)}/>
)
}
stateChange(e){
this.props.sonMess(msg);
}
}
<Task sonMess={this.getSonMess.bind(this)} />
getSonMess(item){
alert(item) //子组件传来的msg
}
默认 Props
HelloMessage.defaultProps = {
name: 'Runoob'
};
props验证
MyTitle.propTypes = {
title: PropTypes.string
};
实例
子组件Task.js
import React, { Component , Fragment} from "react";
import "./Task.less";
class Task extends Component{
constructor(props) {
super(props);
this.state = {
id : this.props.taskIndex
}
}
render(){
return (
<div className="task">
<div></div>
<input type="checkbox" checked={this.props.checked} onChange={this.stateChange.bind(this)}/>
<span>{this.props.value}</span>
<div onClick={this.taskDelete.bind(this)}>-</div>
</div>
)
}
stateChange(e){
this.props.sonMess({'value' : this.props.value , 'checked' : e.target.checked,'id':this.state.id});
}
taskDelete(e){
this.props.sonDeleteMess({'value' : this.props.value , 'checked' : this.props.checked,'id':this.state.id});
}
}
export default Task
父组件
import React, { Component , Fragment} from "react";
import './State.less'
import Task from "../Task/Task";
class State extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="state">
<div className="Run">
<div className="run-top">
<span>正在进行</span>
<span>{this.props.listRun.length}</span>
</div>
<div className="run-task">
{
this.props.listRun.map((item , index) => {
return <Task
checked={false}
key={index}
value={item.value}
taskIndex = {item.id}
sonMess={this.getSonMess.bind(this)}
sonDeleteMess={this.getSonDeleteMess.bind(this)}/>
})
}
</div>
</div>
<div className="Run">
<div className="run-top">
<span>已经完成</span>
<span>{this.props.listSuccess.length}</span>
</div>
<div className="run-task">
{
this.props.listSuccess.map((item , index) => {
return <Task
checked={true}
key={index}
value={item.value}
taskIndex = {item.id}
sonMess={this.getSonMess.bind(this)}
sonDeleteMess={this.getSonDeleteMess.bind(this)} />
})
}
</div>
</div>
</div>
)
}
getSonMess(item){
this.props.sonStateMess(item)
}
getSonDeleteMess(item){
this.props.sonTaskDelete(item)
}
}
export default State
React 状态State
State通过与用户交互,实现不同状态(不同的数据),然后进行渲染,使页面与用户数据一致
父组件或子组件都不能知道某个组件是有状态还是无状态,也就是说本组件以外,其他组件不能访问其状态
数据自顶向下流动:也称作单向数据流,状态由组件特有,只能影响该组件树下方的组件(通过父传子),并且同一个组件创建的不同实例也相互不影响,独立存在
与props的区别
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。
state与props的结合使用
在父组件中使用state与用户交互,通过props传给子组件
React 事件处理
1.驼峰式写法 如onClick
2.传入函数作为事件处理
3.事件处理函数中带e参数,e为响应节点,可通过e.target访问value等
4.必须使用preventDefault 对默认事件进行阻止动作
重点:
调用事件处理函数需要通过bind绑定this本组件,要不然访问不了本组件的数据
实例
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 这边绑定是必要的,这样 `this` 才能在回调函数中使用
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
React 列表
一般通过map
重点:需要给key值
key可以方便react识别那些元素发生了变化,最好是列表中唯一的标识,一般以index赋值
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
<li key={number.toString()}>{numbers}</li>
);
React 组件API
1.设置状态:setState
在组件内,不能直接通过this.state与= 改变状态,那样不会触发React渲染,需要调用setState 改变状态
setState()总是会触发一次组件重绘
setState 是异步的
如果一个操作必须要在一个 setState 之后进行的话。可以使用回调函数
this.setState({
listRun : list
})
2.替换状态:replaceState 不常用
3.设置属性:setProps 不常用
4.替换属性:replaceProps 不常用
5.强制更新:forceUpdate
默认情况下,当你的组件的 state 或者 props 改变,你的组件将会重绘
如果数据隐式改变,可以用调用 forceUpdate() 来告诉 React 它需要重新运行 render()。
6.获取DOM节点:findDOMNode
如果这个组件已经被挂载到了 DOM,它返回相应的浏览器原生的 DOM 元素
7.判断组件挂载状态:isMounted 不常用
React 组件生命周期
三个状态
1.Mounting:已插入真实 DOM
2.Updating:正在被重新渲染
3.Unmounting:已移出真实 DOM
生命周期(周期函数)分为两类:挂载卸载过程和更新过程
1. 挂载卸载过程
1.1.constructor()
constructor()中完成了React数据的初始化,它接受两个参数:props和context,
1.2.componentWillMount()
在渲染前调用,在客户端也在服务端。
1.3.componentDidMount()
在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
1.4.componentWillUnmount ()
在组件从 DOM 中移除之前立刻被调用。
2. 更新过程
2.1. componentWillReceiveProps (nextProps)
在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
2.2.shouldComponentUpdate(nextProps,nextState)
返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。
2.3.componentWillUpdate (nextProps,nextState)
在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
2.4.componentDidUpdate(prevProps,prevState)
在组件完成更新后立即调用。在初始化时不会被调用。
2.5.render()
React 后端数据获取
React 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI。
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));
}
React React 表单与事件
在React中,如果将表单绑定在state上,只能通过setState方法更新。
所以需要事件onChange来监听input的变化,并修改state
<form>
<input
type="text"
placeholder="添加ToDo"
value={this.state.value}
onChange={this.handleInputChange.bind(this)}
onKeyPress={this.keyPress.bind(this)}/>
</form>
handleInputChange(e) {
this.setState({
value : e.target.value
})
}
React ref
1.ReactDOM.render()渲染组件时返回的是组件实例(只能是class声明的组件);
2.渲染dom元素时,返回是具体的dom节点。
ref属性可以设置为一个回调函数
ref 属性接受一个回调函数,它在组件被加载或卸载时会立即执行。
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// 直接使用原生 API 使 text 输入框获得焦点
this.textInput.focus();
}
render() {
// 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 React
// 实例上(比如 this.textInput)
return (
<div>
<input
type="text"
ref={ (input)=>{this.textInput=input}}/>
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
上一篇: react-redux学习记录
下一篇: hashMap实现原理