1、React简介
1.1、React概述
React
是用于构建用户界面的 javascript
库,具有声明式、组件化等特点。
1.2、MVC和MVVM模式
MVC(Model-View-Controller,模型-视图-控制器),Model指模型数据,View是显示的界面,Controller是控制层,控制层用于接收到用户的操作,然后进行一系列的处理后,发送给Model,接收到Model的响应后再交给View视图层。
MVVM(Model-View-ViewModel,模型-视图-视图模型),Model指模型数据,View是指浏览器渲染的网页,ViewMode是Model和View的桥梁,称为视图模型,由ViewModel完成数据的绑定。
在Vue中,JS对象就是Model,HTML标签就是View,Vue实例就是ViewModel。
2、React环境搭建
2.1、使用webpack搭建React开发环境
参考博客:https://blog.csdn.net/p445098355/article/details/104517094
2.2、使用create-react-app脚手架
安装脚手架
cnpm i -g create-react-app
创建项目
create-react-app 项目名称
3、JSX语法
jsx
全程是 javascript XML
,是一个 JavaScript 的语法扩展。jsx
要按照 xml
的编写规范,即:
- 最外层只能有一个根标记;
- 每个标记都必须要有闭合标签;
在 jsx
中可以使用 {...}
来编写 javascript
表达式。
4、React组件
4.1、函数组件
使用构造函数声明的组件被称为函数组件,因其内部没有 state
属性,所以又被称为无状态组件,代码如下:
import React from 'react';
import ReactDOM from 'react-dom';const App = () => {return (<div>函数组件</div>)
}ReactDOM.render(<App />,document.getElementById('root'));
可以通过 props
属性获取到组件标签上定义的属性值,例如:
import React from 'react';
import ReactDOM from 'react-dom';const App = (props) => {return (<div>函数组件,props值: {props.name}</div>)
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
4.2、类组件
使用 class
关键字创建的组件,称为类组件,因其内部可以有 state
属性,又被称为有状态组件,代码如下:
import React from 'react';
import ReactDOM from 'react-dom';class App extends React.Component {render() {return (<div>类组件</div>)}
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
在使用类组件的标签时,标签上定义的属性都会通过类组件的构造函数,传递到组件内部,然后在组件内容使用 this.props
获取到外界的传值,代码如下:
import React from 'react';
import ReactDOM from 'react-dom';class App extends React.Component {//构造函数constructor(props){super(props)console.log(props)}render() {return (<div>类组件,props值: {this.props.name}</div>)}
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
每个类组件都有自己独享的内部状态,即 state
属性。如果要操作 state
必须要使用 setState()
函数,该函数是一个异步函数,对 state
修改后,会再次调用 render()
函数重新渲染页面。
class App extends React.Component {//构造函数constructor(props){super(props)this.state = {value: 'hello'}}//按钮点击事件,接收到视图层的指令,操作数据模型,最后在把操作结果返回给视图handleClick(str){this.setState({value: str})}render() {return (<div>{this.state.value}<button onClick={this.handleClick.bind(this,'world')}>修改state</button></div>)}
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
4.3、函数组件和类组件的区别
在说明函数组件和类组件的区别时,要看3个方面:
- 组件内是否有
this
; - 组件内是否有
state
; - 组件内是否有生命周期钩子;
只要符合上面的3点,就是一个有状态组件,即类组件。
4.4、组件通信
父组件向子组件传值
import React from 'react';
import ReactDOM from 'react-dom';
// import App from './App';class App extends React.Component {render(){return (<div>{/* 自定义组件,可以在组件上自定义属性 */}<Button text="百度一下" subText="点击提交数据" textColor="red"/></div>)}
}//无状态组件,只显示UI效果,没有太多的业务逻辑
const Button = (props) => {return (<button title={props.subText} style={{color: props.textColor}}>{props.text}</button>)
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
子组件向父组件传值
import React from 'react';
import ReactDOM from 'react-dom';
// import App from './App';class App extends React.Component {//自定义组件的点击事件,text为默认参数,即封装Button组件时传入的一个参数handleClick(text){console.log('自定义组件被点击了。。。。',text)}render(){return (<div>{/* 自定义组件,可以在组件上自定义属性,也可以自定义事件 */}<Button text="百度一下" subText="点击提交数据" textColor="red" onClick={this.handleClick.bind(this)}/></div>)}
}//无状态组件,只显示UI效果,没有太多的业务逻辑
const Button = (props) => {return (<button title={props.subText} style={{color: props.textColor}} onClick={()=>{props.onClick(props.text)}}>{props.text}</button>)
}ReactDOM.render(<App name="Tom" />,document.getElementById('root'));
4.5、封装自定义组件
自定义按钮组件
import React, { Component } from 'react'export default class Button extends Component {//HTML的button标签原生点击事件函数handleClick(){this.props.onClick()}render() {return (<div><button style={{color: this.props.fontColor}} onClick={this.handleClick.bind(this)}>{this.props.text}</button></div>)}
}
自定义输入框组件
import React, { Component } from 'react'export default class Input extends Component {//input标签原生键盘事件的函数handlePress(e){if(e.charCode === 13){this.props.onEnter(e.target.value)}}render() {return (<div><input onKeyPress={this.handlePress.bind(this)}></input></div>)}
}
在父组件中使用自定义组件
import React, { Component } from 'react'
import Button from './Button'
import Input from './Input'export default class App extends Component {handleClick(){console.log('click....')}//Input组件上的回车事件handleEnter(val){console.log('enter...',val)}render() {return (<div><Input onEnter={this.handleEnter.bind(this)}></Input><Button text="提交" fontColor="red" onClick={this.handleClick.bind(this)}></Button></div>)}
}
5、UI组件库
5.1、使用Element-React组件库
需要安装:
# 安装element-react
cnpm i element-react --save# 安装elementui的主题
cnpm install element-theme-default --save# 按钮react-hot-loader
cnpm install react-hot-loader@next -D
Button组件使用案例:
import React, { Component } from 'react'
import {Button
} from 'element-react'
import 'element-theme-default'export default class App extends Component {constructor(){super()this.state = {isLoading: false,btnText: '点击下载'}}handleLoading = ()=>{this.setState({btnText: '下载中',isLoading: true},()=>{//模拟下载过程setTimeout(()=>{this.setState({btnText: '下载完成',isLoading: false})},2000)})}render() {return (<div><Button type="info" loading={this.state.isLoading} onClick={this.handleLoading}>{this.state.btnText}</Button><Button>上传<i className="el-icon-upload2"></i></Button></div>)}
}
Menu和Table组件的使用案例:
import React, { Component } from 'react'
import {Button,Menu,Table
} from 'element-react'
import 'element-theme-default'export default class App extends Component {constructor(){super()this.state = {column: [{label: '姓名',prop: 'name'},{label: '年龄',prop: 'age'},{label: '电话',prop: 'phone'},{label: '操作',render: (obj,e,index)=>{ //渲染函数的默认参数为当前点击的数据对象return (<React.Fragment><Button type="info" size="small">修改</Button> <Button type="danger" size="small">删除</Button></React.Fragment>)}}],data: [{name: '张三',age: 20,phone: '13099998888'},{name: '李四',age: 21,phone: '13099998888'},{name: '王五',age: 22,phone: '13099998888'}]}}render() {return (<div><Menu mode="horizontal" theme="dark" defaultActive="1" style={{marginBottom: '20px'}}><Menu.Item index="1">首页</Menu.Item><Menu.SubMenu index="2" title="新闻"><Menu.Item index="2-1">国内新闻</Menu.Item><Menu.Item index="2-2">国际新闻</Menu.Item><Menu.Item index="2-3">社会新闻</Menu.Item></Menu.SubMenu></Menu><Table style={{width: '100%'}} columns={this.state.column} data={this.state.data}></Table></div>)}
}
5.2、Ant Design UI库
安装
cnpm i antd --save
引入组件
# 按需引入
import { DatePicker } from 'antd';# 引入样式
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
6、路由
BrowserRouter
<BrowserRouter>
使用 HTML5 提供的 history API (pushState
, replaceState
和 popstate
事件) 来保持 UI 和 URL 的同步。一个应用程序中只需要有一个 <BrowserRouter>
即可。
在 index.js
中使用:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {BrowserRouter} from 'react-router-dom'ReactDOM.render(<BrowserRouter><App /></BrowserRouter>,document.getElementById('root'));
HashRouter
<HashRouter>
使用 URL 的 hash
部分(即 window.location.hash
)来保持 UI 和 URL 的同步。与 <BrowserRouter>
用法类似,但是 <HashRouter>
在页面中显示的路由地址里有 #
符号。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {HashRouter} from 'react-router-dom'ReactDOM.render(<HashRouter><App /></HashRouter>,document.getElementById('root'));
Link
为你的应用提供声明式的、可访问的导航链接。
import { Link } from 'react-router-dom';<Link to="/about">About</Link>
配合 Route
使用。
Route
<Route>
可能是 React Router 中最重要的组件,它可以帮助你理解和学习如何更好的使用 React Router。它最基本的职责是在其 path
属性与某个 location 匹配时呈现一些 UI。
import { BrowserRouter as Router, Route } from 'react-router-dom';<Router><div><Route exact path="/" component={Home} /><Route path="/news" component={News} /></div>
</Router>
Link、Route配合使用案例:
import React, { Component } from 'react'
import {Menu} from 'element-react'
import 'element-theme-default'
import {Link,Route,Switch} from 'react-router-dom'export default class App extends Component {render() {return (<div><Menu mode="horizontal" theme="dark" defaultActive="1" style={{marginBottom: '20px'}}><Menu.Item index="1">首页</Menu.Item><Menu.SubMenu index="2" title="新闻"><Menu.Item index="2-1"><Link to="/guonei">国内新闻</Link></Menu.Item><Menu.Item index="2-2"><Link to="/guoji">国际新闻</Link></Menu.Item><Menu.Item index="2-3"><Link to="/shehui">社会新闻</Link></Menu.Item></Menu.SubMenu></Menu><Switch><Route path="/guonei" component={GuoneiNews}></Route><Route path="/guoji" component={GuojiNews}></Route><Route path="/shehui" component={ShehuiNews}></Route></Switch></div>)}
}
参考博客:https://www.jianshu.com/p/97e4af32811a
7、Redux状态管理
Store
用于连接 action
和 reducer
重要对象,一个redux应用程序中只能有一个 store
对象。
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
Reducer
Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
Action
Action 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch()
将 action 传到 store。
const action = {type: "ADD_TODO",text: 'Build my first Redux app'
}
核心API
在使用redux时,需要掌握的核心API:
- store.getState() :用于获取最新的store对象
- store.subscrbe() :用于监听store中的数据变化
- store.dispatch() :用于向reducer派发action对象