前言
简介
构建用户界面的JAVASCRIPT库,主要用于构建UI
起源于 Facebook 的内部项目,用来架设 Instagram 的网站,拥有较高的性能,代码逻辑非常简单,并于 2013 年 5 月开源。
特点
1.声明式设计 −React采用声明范式,可以轻松描述应用。
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
3.灵活 −React可以与已知的库或框架很好地配合。
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
JSX语法
const element = <h1>Hello, world!</h1>;
React 书写格式
以前使用JS 定义一个变量使用 var 现在用 const
const div = document.createElement('div');
渲染方法
所有的 js,html 都可通过它进行渲染绘制,他有两个参数,内容和渲染目标 js 对象
ReactDOM.render(<App />, div);
React 安装和构建React 开发环境
通过 npm 使用 React
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
$ npm config set registry https://registry.npm.taobao.org
//使用
$ cnpm install [name]
使用 create-react-app
快速构建 React 开发环境
create-react-app 自动创建的项目是基于 Webpack + ES6
$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
在浏览器中打开 http://localhost:3000/
H5项目说明
简介
使用create-react-app
脚手架搭建,采用react+antd+mobile
技术
项目路径在H5dev 项目的 m文件里
Build目录
里是 npm run build
命令后 打包存放的目录
Public
跟域名访问的目录
Src
自己开发的项目文件
Api目录
主要存放了 一下接口相关的
Components
存放了一些公用组件
Config
存放了配置文件
Images
图片
Pages
每个页面的路径
Style
样式
Utils
存放一些公用方法
Index.js
入口文件
Router.js
路由文件
Activity 存放了一些活动
常见用法
1.元素渲染
const element = <h1>Hello, world!</h1>;
ReactDOM.render(
element,
document.getElementById('example')
);
2.更新元素渲染
创建一个新的元素,然后将它传入 ReactDOM.render()
方法
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('example')
);
}
setInterval(tick, 1000);
3.元素取值和赋值
用 this.props.属性名
来取值。
可以多层 props 来传值,在 ReactDOM.render 定义属性值,传给调用方法 App,再在调用的ES6类调用中用 props.属性直接赋值过去。
var myStyle = {color:'red',textAlign:'center'}
class Name extends React.Component {
render() {
return <h1 style={myStyle}>网站名称:{this.props.name}</h1>;
}
}
class Url extends React.Component {
render() {
return <h1>网站地址:{this.props.url}</h1>;
}
}
class Nickname extends React.Component {
render() {
return <h1>网站地址:{this.props.nickname}</h1>;
}
}
function App(props) {
return (
<div>
<Name name={props.name}/>
<Url url={props.url}/>
<Nickname nickname={props.nickname}/>
</div>
);
}
多个属性的传入注意不用逗号或分号隔开而是空格符隔开:
ReactDOM.render(
<App name={"StevenHu教程"} url={"http://www.runoob.com"} nickname={"Runoob"}/>,
document.getElementById('example')
);
4.JSX语法
执行更快,类型安全,在编译过程中就能发现错误
const element = <h1>Hello, world!</h1>;
JSX, 一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面
JSX 是在 JavaScript 内部实现的。JSX 就是用来声明 React 当中的元素
var myDivElement = <div className="foo" />;
ReactDOM.render(myDivElement, document.getElementById('example'));
5.独立文件
你的 React JSX 代码可以放在一个独立文件上,例如我们创建一个 helloworld_react.js 文件,代码如下
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
在 HTML 文件中引入该 JS 文件
<body>
<div id="example"></div>
<script type="text/babel" src="helloworld_react.js"></script>
</body>
6.JavaScript 表达式
ReactDOM.render(
<div>
<h1>{1+1}</h1>
</div>
,
document.getElementById('example')
);
在 JSX 中不能使用 if else 语句,但可以使用 conditional (三目运算) 表达式来替代。以下实例中如果变量 i 等于 1 浏览器将输出 true, 如果修改 i 的值,则会输出 false.
ReactDOM.render(
<div>
<h1>{i == 1 ? 'True!' : 'False'}</h1>
</div>
,
document.getElementById('example')
);
7.样式
React 推荐使用内联样式
。
var myStyle = {
fontSize: 100,
color: '#FF0000'
};
ReactDOM.render(
<h1 style = {myStyle}>StevenHu教程</h1>,
document.getElementById('example')
);
8.注释
注释需要写在花括号中,实例如下:
ReactDOM.render(
<div>
<h1>StevenHu教程</h1>
{/*注释...*/}
</div>,
document.getElementById('example')
);
9.数组
JSX 允许在模板中插入数组,数组会自动展开所有成员
var arr = [
<h1>StevenHu教程</h1>,
<h2>学的不仅是技术,更是梦想!</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
10.事件处理
- React 事件绑定属性的命名采用驼峰式写法,而不是小写
- 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
HTML 通常写法是:
<button onclick="activateLasers()">
激活按钮
</button>
React 中写法为:
<button onClick={activateLasers}>
激活按钮
</button>
11.不能使用返回 false 的方式阻止默认行为, 你必须明确的使用 preventDefault
通常我们在 HTML 中阻止链接默认打开一个新页面,可以这样写
<a href="#" onclick="console.log('点击链接'); return false">
点我
</a>
React 的写法
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('链接被点击');
}
return (
<a href="#" onClick={handleClick}>
点我
</a>
);
}
12.bind用法
类的方法默认是不会绑定 this 的。如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候 this 的值会是 undefined。
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>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('example')
);
13.向事件处理程序传递参数
class Popper extends React.Component{
constructor(){
super();
this.state = {name:'Hello world!'};
}
preventPop(name, e){ //事件对象e要放在最后
e.preventDefault();
alert(name);
}
render(){
return (
<div>
<p>hello</p>
{/* 通过 bind() 方法传递参数。 */}
<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}
14.条件渲染
React 中的条件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI。
先来看两个组件
function UserGreeting(props) {
return <h1>欢迎回来!</h1>;
}
function GuestGreeting(props) {
return <h1>请先注册。</h1>;
}
创建一个 Greeting 组件,它会根据用户是否登录来显示其中之一
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// 尝试修改 isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('example')
);
15.与运算符 &&
可以通过用花括号包裹代码在 JSX 中嵌入任何表达式 ,也包括 JavaScript 的逻辑与 &&,它可以方便地条件渲染一个元素
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
您有 {unreadMessages.length} 条未读信息。
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('example')
);
如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
16.三目运算符
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
17.阻止组件渲染
在极少数情况下,你可能希望隐藏组件,即使它被其他组件渲染。
让 render 方法返回 null 而不是它的渲染结果即可实现
。
在下面的例子中,<WarningBanner />
根据属性 warn 的值条件渲染。如果 warn 的值是 false,则组件不会渲染
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
警告!
</div>
);
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {showWarning: true}
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick() {
this.setState(prevState => ({
showWarning: !prevState.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? '隐藏' : '显示'}
</button>
</div>
);
}
}
ReactDOM.render(
<Page />,
document.getElementById('example')
);
组件的 render 方法返回 null 并不会影响该组件生命周期方法的回调
18.使用 JavaScript 的 map() 方法来创建列表
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
<li>{numbers}</li>
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('example')
);
19.修改state里面的属性
// Correct
this.setState({comment: 'Hello'});
20.状态更新可能是异步的
例如,此代码可能无法更新计数器
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
正确
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
上方代码使用了箭头函数,但它也适用于常规函数:
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
21.React 事件
通过 onClick 事件来修改数据
class HelloMessage extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello Runoob!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: '菜鸟教程'})
}
render() {
var value = this.state.value;
return <div>
<button onClick={this.handleChange}>点我</button>
<h4>{value}</h4>
</div>;
}
}
ReactDOM.render(
<HelloMessage />,
document.getElementById('example')
);
React 组件生命周期
组件的生命周期可分成三个状态
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
生命周期的方法
componentWillMount
在渲染前调用
componentDidMount
在第一次渲染后调用
componentWillReceiveProps
在组件接收到一个新的 prop (更新后)时被调用。在初始化render时不会被调用。
shouldComponentUpdate
返回一个布尔值在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
componentWillUpdate
组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用
componentDidUpdate
在组件完成更新后立即调用。在初始化时不会被调用
componentWillUnmount
在组件从 DOM 中移除之前立刻被调用
生命周期介绍
初始化调用
1、getDefaultProps()
设置默认的props,也可以用dufaultProps设置组件的默认属性.
2、getInitialState()
在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props
3、componentWillMount()
组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。
4、 render()
react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
5、componentDidMount()
组件渲染之后调用,只调用一次。
更新
1、componentWillReceiveProps(nextProps)
组件初始化时不调用,组件接受新的props时调用。
2、shouldComponentUpdate(nextProps, nextState)
react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候
3、componentWillUpdata(nextProps, nextState)
组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state
4、render()
组件渲染
5、componentDidUpdate()
组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。
卸载
6、componentWillUnmount()
组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
初始化 state , setNewnumber 用于更新 state。所有生命周期在 Content 组件中
class Button extends React.Component {
constructor(props) {
super(props);
this.state = {data: 0};
this.setNewNumber = this.setNewNumber.bind(this);
}
setNewNumber() {
this.setState({data: this.state.data + 1})
}
render() {
return (
<div>
<button onClick = {this.setNewNumber}>INCREMENT</button>
<Content myNumber = {this.state.data}></Content>
</div>
);
}
}
class Content extends React.Component {
componentWillMount() {
console.log('Component WILL MOUNT!')
}
componentDidMount() {
console.log('Component DID MOUNT!')
}
componentWillReceiveProps(newProps) {
console.log('Component WILL RECEIVE PROPS!')
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('Component WILL UPDATE!');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component DID UPDATE!')
}
componentWillUnmount() {
console.log('Component WILL UNMOUNT!')
}
render() {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
}
ReactDOM.render(
<div>
<Button />
</div>,
document.getElementById('example')
);
React AJAX(数据请求)
React 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI。
当使用异步加载数据时,在组件卸载前使用 componentWillUnmount
来取消未完成的请求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
class UserGist extends React.Component {
constructor(props) {
super(props);
this.state = {username: '', lastGistUrl: ''};
}
componentDidMount() {
this.serverRequest = $.get(this.props.source, function (result) {
console.log(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} 用户最新的 Gist 共享地址:
<a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a>
</div>
);
}
}
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
document.getElementById('example')
);
</script>
</body>
</html>
补充
①Component定义和Render使用
import React from 'react';
class CommentBox extends React.Component {
render(){
return(
<div className="ui comments">
<h1>评论</h1>
<div className="ui divider"></div>
</div>
);
}
}
export {CommentBox as default};
第二种
class CommentList extends React.Component {
render(){
let commentNodes = this.props.data.map(comment =>{
return (
<Comment author={comment.author} date={comment.date}>
{comment.text}
</Comment>
);
})
}
};
②this.props.children
表示组件的所有子节点
this.props.children的值有三种可能:
- 当前组件没有子节点,为 undefined
- 若只有一个子节点,类型为 Object
- 若有多个子节点,类型为 Array
通常不直接处理this.props.children,而是用React.Children.map/forEach等API来操作,
该API进行了类型处理,保证不会出错。
③加载本地json
[图片上传失败...(image-d44f69-1559823451981)]