1.概述
https://reactjs.org/
构建用户界面的js库
react只对视图负责
facebook出品
更快的dom渲染和易于维护的dom层
分多模块,react-dom等按需引入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--解析jsx语法-->
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<!--识别jsx语法-->
<script type="text/babel">
/*
jsx语法 react提供的语法,js+xml
*/
// 页面要展示的信息 渲染内容位置
ReactDOM.render(
<div>Hello React <p>!!</p></div>,
document.getElementById('root')
);
</script>
</body>
</html>
2.jsx语法
列表数据渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
var arr = ['zhangsan', 'lisi', 'wangwu'];
// 列表渲染 jsx语法
// 遇到{}按js语法解析
// 遇到<>按xml语法解析
// 语法略怪
ReactDOM.render(
<ul>
{
arr.map(function (item, index) {
// 列表元素需要指定key作为唯一元素索引
return <li key={index}>{ item }</li>
})
}
</ul>,
document.getElementById('root')
);
</script>
</body>
</html>
标签作为数组元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<!--识别jsx语法-->
<script type="text/babel">
var arr = [<p>p1</p>, <p>p2</p>, <p>p3</p>];
ReactDOM.render(
<div>
{
arr.map(function (item, index) {
return item
})
}
</div>
,
document.getElementById('root')
);
</script>
</body>
</html>
复杂数据渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
var userinfo = [
{
name: 'vincent',
age: 20,
sex: '男'
},
{
name: 'lisi',
age: 19,
sex: '男'
},
{
name: 'wangwu',
age: 18,
sex: '女'
}
];
ReactDOM.render(
<ul>
{
userinfo.map(function(item, index){
return (
<div key={index}>
<h3>{ item.name }</h3>
<p>{ item.age }</p>
</div>
)
})
}
</ul>
,
document.getElementById('root')
);
</script>
</body>
</html>
组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件首字母大写
var Hello = React.createClass({
render:function () {
return (
<div>Hello World!</div>
)
}
});
// ReactDOM.render(<Hello/>, document.getElementById('root'))
ReactDOM.render(<div><Hello/><Hello/></div>, document.getElementById('root'))
</script>
</body>
</html>
抽取标签变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function tick() {
var current = (
<div>
<h3>当前时间</h3>
<p>{ new Date().toLocaleTimeString() }</p>
</div>
)
ReactDOM.render(
current, document.getElementById('root')
)
}
setInterval(tick, 1000);
// tick()
</script>
</body>
</html>
组件嵌套 业务逻辑
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件只能存在一个根容器
// 组件可以嵌套
// 组件可以具有业务逻辑
// 组件首字母大写
var Root = React.createClass({
render:function () {
return (
<div>
<p>我是组件</p>
</div>
)
}
});
var Nav = React.createClass({
render:function () {
var navArr = ['百度', '谷歌', 'Bing']
return (
<div>
<ul>
{
navArr.map(function(item, index){
return <li><a href="#" key={index}>{ item }</a></li>
})
}
</ul>
</div>
)
}
});
var RightNav = React.createClass({
render:function () {
return (
<div>
<ul>
<li><a href="#">新闻</a></li>
<li><a href="#">地图</a></li>
<li><a href="#">视频</a></li>
</ul>
</div>
)
}
});
ReactDOM.render(
<div>
<Nav />
<RightNav />
</div>,
document.getElementById('root'))
</script>
</body>
</html>
组件数据交互
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件数据交互
var Hello = React.createClass({
render:function () {
return (
<div>
{ this.props.title }
<Demo demo="你是demo"/>
</div>
)
}
});
var Demo = React.createClass({
render:function () {
return (
<div>{ this.props.demo }</div>
)
}
});
ReactDOM.render(
<Hello title="hello component" />,
document.getElementById('root'))
</script>
</body>
</html>
不同数据渲染相同组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件首字母大写
var Root = React.createClass({
render:function () {
var nav1 = ['百度', '谷歌', 'Bing']
var nav2 = ['新闻', '地图', '视频']
return (
<div>
<Nav navArr={nav1} />
<Nav navArr={nav2} />
</div>
)
}
});
var Nav = React.createClass({
render:function () {
return (
<div>
<ul>
{
this.props.navArr.map(function(item, index){
return <li><a href="#" key={index}>{ item }</a></li>
})
}
</ul>
</div>
)
}
});
ReactDOM.render(
<Root />,
document.getElementById('root'))
</script>
</body>
</html>
传递多个参数 复杂参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// createClass v16版本去掉,采用继承方式实现
// 传递多个参数 复杂参数
var Hello = React.createClass({
render:function () {
var p1 = this.props.title
var p2 = this.props.name
var p3 = this.props.info
console.log(p3)
return (
<div>
{ p1 }{ p2 }
</div>
)
}
});
var info = {
name: 'vincent',
age: 20
}
ReactDOM.render(
<Hello title="hello" name="react" info={info} />,
document.getElementById('root'))
</script>
</body>
</html>
样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
<style>
.container{
color: red;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件添加样式
var Hello = React.createClass({
render:function () {
var styleObj = { color: 'green',fontSize: '30px'}
return (
// 不能用class
// 行内样式 {{}}
// 驼峰
// style接收的是object对象
<div className="container">
<p>哈哈</p>
<span style={styleObj}>hello</span>
</div>
)
}
});
ReactDOM.render(
<Hello />,
document.getElementById('root'))
</script>
</body>
</html>
事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 事件
var Hello = React.createClass({
handlerClick:function(event) {
// this 当前组件
console.log(this)
console.log(event)
},
// onmouseover类似,驼峰命名
render:function () {
return (
<div>
<button onClick={this.handlerClick}>按钮</button>
</div>
)
}
});
ReactDOM.render(
<Hello />,
document.getElementById('root'))
</script>
</body>
</html>
state-组件内部状态
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// state 组件内部状态 属性 数据等
// 组件之后再无dom,jquery废了
// 点击按钮改变文本
// 网络请求修改数据场景
var Hello = React.createClass({
// 固定写法
getInitialState:function(){
return{
value: "呵呵"
}
},
changeInfo:function(){
// 点击按钮修改state
this.setState({
value: "嘿嘿"
})
},
render:function () {
return (
<div>
<p>{this.state.value}</p>
<button onClick={this.changeInfo}>按钮</button>
</div>
)
}
});
ReactDOM.render(
<Hello />,
document.getElementById('root'))
</script>
</body>
</html>
state连续改变
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 连续改变state
// set stage会导致视图重绘
// react使用虚拟dom解决性能问题
var Hello = React.createClass({
getInitialState:function(){
return{
value: true
}
},
changeInfo:function(){
this.setState({
// 取反
value: !this.state.value
})
},
render:function () {
var value = this.state.value;
// react中三目运算符非常频繁
var info = value ? '孙悟空' : '六耳猕猴';
return (
<div>
<p>{ info }</p>
<button onClick={this.changeInfo}>按钮</button>
</div>
)
}
});
ReactDOM.render(
<Hello />,
document.getElementById('root'))
</script>
</body>
</html>
state和props的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// state和props的应用
// state用于组件状态
// props用于传递数据
// 组件功能应该是单一化的
var Person = React.createClass({
render:function () {
var name = this.props.name
var age = this.props.age
return (
<div>
<h3>{ name }</h3>
<p>{ age }</p>
</div>
)
}
});
var User = React.createClass({
getInitialState:function(){
return{
name: 'Vincent',
age: 20
}
},
changeInfo:function(event){
this.setState({
name: 'Ime',
age: 30
})
},
render:function () {
return (
<div>
<Person name={this.state.name} age={this.state.age} />
<button onClick={this.changeInfo}>按钮</button>
</div>
)
}
});
ReactDOM.render(
<User />,
document.getElementById('root'))
</script>
</body>
</html>
生命周期
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 组件生命周期
// 初始化props -> getInitialState -> componentWillMount(组件渲染之前)
// -> render -> componentDidMount(组件渲染之后)
// 运行中 -> 属性改变 -> componentWillReceiverProps -> shouldComponentUpdate
// 运行中 -> state改变 -> shouldComponentUpdate(state改变之后)
// -> componentWillUpdate(组件更新前) -> componentDidUpdate(组件更新后)
// 运行中 -> 卸载 Unmount -> componnetWillUnmount(组件卸载之前) -> 运行中
// 移除组建时执行卸载
// 不建议修改props
// 网络请求放到哪个生命周期函数中?
var MyComponent = React.createClass({
// 初始化props
getDefaultProps:function() {
},
// 初始化state
getInitialState:function() {
return{
value: '孙悟空'
}
},
// 组件渲染之前
componentWillMount:function() {
console.log('组件渲染之前');
},
// 组件渲染之后
componentDidMount:function() {
console.log('组件渲染之后');
},
// state改变之后
shouldComponentUpdate:function() {
console.log('state改变之后');
return true;
},
// 组件更新前
componentWillUpdate:function() {
console.log('组件更新前');
},
// 组件更新后
componentDidUpdate:function() {
console.log('组件更新后');
},
// props改变后
componentWillReceiverProps:function() {
console.log('props改变后');
},
changeInfo:function() {
this.setState({
value: '六耳猕猴'
})
},
// 渲染函数
render:function () {
return (
<div>
<p>{ this.state.value }</p>
<button onClick={ this.changeInfo }>按钮</button>
</div>
)
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('root'))
</script>
</body>
</html>
生命周期的使用
网络请求渲染数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
<script src="dist/browser.min.js"></script>
<script src="dist/jquery.js"></script>
<script src="dist/react.js"></script>
<script src="dist/react-dom.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// 生命周期的使用-网络请求渲染数据
var Hello = React.createClass({
getInitialState:function() {
return{
info: [{
title: "",
content: "",
img: ""}]
}
},
componentDidMount:function() {
$.ajax({
type: 'get',
url: '16_life_demo.php',
success: function (data) {
this.setState({
info: JSON.parse(data).banner
})
}.bind(this)
})
},
// 生命周期函数中网络请求获取数据
render:function () {
return (
<div>
<ul>
{
this.state.info.map(function (item, index) {
return (
<li key={index}>
<h3>{item.title}</h3>
<span>{item.content}</span>
<img src={item.img} alt=""/>
</li>
)
})
}
</ul>
</div>
)
}
});
ReactDOM.render(
<Hello />,
document.getElementById('root'))
</script>
</body>
</html>
3.环境-脚手架
# 配置阿里镜像
npm config set registry https://registry.npm.taobao.org
# 创建项目
npx create-react-app 01-install
# 低版本node报错:
# The engine "node" is incompatible with this module.
# 启动
npm start
标签一定要闭合
src/user/index.js
import React, {Component} from 'react'
class User extends Component {
render() {
return (
<div>
// 接收参数
<h3>用户:{this.props.name}</h3>
</div>
)
}
}
export default User
src/App.js
import React, {Component} from 'react';
import User from "./user"
function App() {
return (
<div className="App">
// 传递参数
<User name="vincent" />
<User name="lili" />
<User name="lucy" />
</div>
);
}
export default App;
类型检查
// 类型检查-增强程序健壮性
// 类型验证
/*
User.prototypes ={
name: PropTypes.string
}
// 验证必选项
User.prototypes = {
name: PropTypes.string.isRequired
}
User.defaultProps = {
name: '默认值'
}*/
网络请求
通过jquery进行网络请求
import React, {Component} from 'react'
import $ from "jquery"
export default class Login extends Component {
constructor() {
super()
// state状态放在构造函数中
this.state = {
time: '2018-01',
banner: [{
title: '',
content: '',
img: ''
}]
}
}
// 状态更改
handlerClick(event) {
this.setState({
time: '2020-09-10'
})
}
// 网络请求
componentDidMount() {
console.log('组件渲染后');
$.ajax({
type: 'get',
url: 'http://localhost/06_react/01_jsx/16_life_demo.php',
success: function (data) {
console.log(data);
this.setState({
banner: JSON.parse(data).banner
})
}.bind(this)
})
}
render() {
var { banner } = this.state;
return (
<div>
登录时间: {this.state.time}
<ul>
{
banner.map(function (item, index) {
return <li key={index}>{item.title}</li>
})
}
</ul>
<button onClick={this.handlerClick.bind(this)}>按钮</button>
</div>
)
}
}
表单绑定事件
import React, {Component} from "react"
export default class Info extends Component{
constructor() {
super();
// 受控组件
this.state = {
username: 'vincent',
password: '123'
}
}
usernameChange(event) {
console.log(event.target.value)
this.setState({
username: event.target.value
})
}
passwordChange(event) {
this.setState({
password: event.target.value
})
}
// 提交表单
handleSubmit(event) {
console.log(this.state.username, this.state.password)
// 业务逻辑
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit.bind(this)}>
<input onChange={this.usernameChange.bind(this)} value={this.state.username} type="text" name="username" />
<input onChange={this.passwordChange.bind(this)} value={this.state.password} type="password" name="password" />
<input type="submit" value="submit" />
</form>
</div>
)
}
}
非受控组件绑定事件
import React, {Component} from "react"
export default class InputDemo extends Component{
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event) {
// 相当于操作原生dom
// 性能不如state方式
console.log(this.input.value)
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input ref={(input) => this.input = input} type="text" name="username" />
<input type="password" name="password" />
<input type="submit" value="submit" />
</form>
</div>
)
}
}
ref操作dom
import React, {Component} from "react"
export default class RefDemo extends Component{
constructor() {
super();
// react不能直接操作dom
// 给当前div设置文本信息
// ref操作dom
this.myRef = React.createRef();
}
handleClick(event) {
this.myRef.current.innerHTML = "world天"
}
render() {
return (
<div ref={this.myRef}>
hello
<button onClick={this.handleClick.bind(this)}>点击</button>
</div>
)
}
}
fetch网络请求
App.js
import React, {Component} from 'react';
import Login from './login'
import HttpDemo from './login/httpDemo'
export default class App extends Component {
constructor() {
super();
this.state = {
banner: [{
title: '',
content: '',
img: ''
}]
}
}
componentDidMount() {
// fetch网络请求-get
var result = fetch('http://localhost/06_react/01_jsx/16_life_demo.php')
.then(res => {
return res.json()
}).then(data => {
console.log(data.banner)
this.setState({
banner: data.banner
})
})
}
render() {
return (
<div className="App">
<Login />
<HttpDemo />
<ul>
{
this.state.banner.map((item, index) => {
return <li key={index}>{item.title}</li>
})
}
</ul>
</div>
);
}
}
fetch post请求
import React from 'react'
export default class Login extends React.Component {
constructor() {
super()
this.state = {
isLogin: false,
username: '',
password: ''
}
}
// post请求
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost/04_php/basic/b1_ajax.php',{
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'username='+this.state.username+'&password=' + this.state.password
}).then(res => {
return res.json()
}).then(data => {
this.setState({
isLogin: data.msg
})
})
}
usernameChange(event) {
this.setState({
username: event.target.value
})
}
passwordChange(event) {
this.setState({
password: event.target.value
})
}
render() {
var { isLogin, username, password } = this.state;
var showView = isLogin ? <p>登录成功</p> : <p>登录失败</p>
return (
<div>
<form onSubmit={this.handleSubmit.bind(this)}>
<input value={username} onChange={this.usernameChange.bind(this)} type="text"/>
<input value={password} onChange={this.passwordChange.bind(this)} type="text"/>
<input type="submit" value='submit' />
</form>
<div>
登录:{ showView }
</div>
</div>
)
}
}
封装http请求
http/http.js
/*封装http请求*/
export function httpGet(url) {
var result = fetch(url);
return result;
}
export function httpPost(url, data) {
var result = fetch(url, {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params(data)
})
return result;
}
function params(obj) {
var result = '';
var item;
for(item in obj) {
result += '&' + item + '=' +encodeURIComponent(obj[item]);
}
if(result) {
result = result.slice(1);
}
return result;
}
封装请求调用
src/login/httpDemo.js
import React, {Component} from 'react'
import {httpPost, httpGet} from '../http/http'
export default class HttpDemo extends Component {
componentDidMount() {
httpPost('http://localhost/04_php/basic/b1_ajax.php', {
username: 'vincent',
password: '123'
}).then(res => {
return res.json()
}).then(data => {
console.log(data)
});
}
render() {
return (
<div>
哈哈
</div>
)
}
}
mock
此处跨域只适用于开发阶段
# 跨域处理
npm ru eject
# 报错
# npm run eject Remove untracked files, stash or commit any changes, and try again.
# 解决
git add .
git commit -m "init"
路由
# 3.x版本
npm install --save react-router@3.x
# 4.x版本
npm install --save react-router r
eact-router-dom
ANTD
阿里出品
https://ant.design/docs/react/getting-started-cn
npm install --save antd
# app.css顶部
@import '~antd/dist/antd.css';
# 按需加载
# 注掉app.css顶部引入
npm install -D react-app-rewired
# package.json修改react-app-rewired
npm install -D babel-plugin-import
# 异常: npm ERR! 01-antd@0.1.0 start: `react-app-rewired start`
# 解决:
npm uninstall react-app-rewired
npm i react-app-rewired@2.0.2-next.0
网友评论