React
1 : 作为 MVC中的view层构建UI,也可以以插件的形式应用到 Web 应用非 UI 部分的构建中,轻松实现与其他 JS 框架的整合
2 : 对虚拟 DOM 中的微操作来实对现实际 DOM 的局部更新,提高性能。其组件的模块化开发提高了代码的可维护性
3 : 单向数据流,更加灵活,更加便捷 提高对代码可控性让每个模块根据数据量自动更新,让开发者可以只专注于数据部分,改善程序的可预测性。
4 : React 在虚拟的 DOM 上实现了一个 diff 算法,当要更新组件的时候,会更新变更的DOM节点 不会重新渲染整个DOM树
安装教程
安装npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm config set registry https://registry.npm.taobao.org
以后就可以 npm install [包名]
使用 create-react-app 快速构建 React 开发环境 自动创建的项目是基于 Webpack + ES6 。
npm install -g create-react-app //搭建环境
create-react-app react-dome //创建react项目
cd react-dome //进项目根目录
npm start //运行
元素渲染
在 public/index.html ,一切的开始都从这里开始,所以这个是代码执行的源头。
里面一个id的一个div 是将所有渲染的DOM渲染到这里面
src/App.js指定id的dom
//简单dom 将elementDOM渲染到id为example的div里面
const element = <h1>Hello, world!</h1>;
ReactDOM.render(
element,
document.getElementById('example')
);
ES6 类写法,用 this.props.属性名 来取值。
每一秒调用一下ReactDOM.render()。,渲染一下页面
//这个是 React.Component 的 ES6 类 拥有生命周期 封装了元素
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
//普通函数
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('example')
);
}
setInterval(tick, 1000);
//1.0
function tick(){
const element = (
<div>
<h1>Hello word</h1>
<h2>现在是{new Date().toLocaleTimeString()}</h2>
</div>
)
ReactDOM.render(element,document.getElementById('example'));
}
setInterval(tick, 1000);
//2.0
function Clock(props){
return (
<div>
<h2> 哈喽 我的朋友</h2>
<h2>现在时间是{props.data.toLocaleTimeString()}</h2>
</div>
)
}
function tick(){
ReactDOM.render(<Clock data={new Date()} />,document.getElementById('example'))
}
setInterval(tick, 1000);
// 3.0
var myStyle = {
fontSize: 10,
color: '#FF0000'
};
let i = '发热'
var arr = [
<h1>这是教程啊</h1>,
<h2>努力长大</h2>,
];
class Clock extends React.Component {
render() {
return (
<div>
<h2 style={myStyle}> 哈喽 我的朋友{5+5}{i === "发热" ? 'true' : 'false'}</h2>
{/* 注释 */}
{arr}
<h2>现在时间是{this.props.data.toLocaleTimeString()}</h2>
</div>
)
}
}
function tick() {
ReactDOM.render(<Clock data={new Date()} />, document.getElementById('example'))
}
setInterval(tick, 1000);
// 4.0
class Url extends React.Component{
render(){
return (
<h1>网址地址: {this.props.data}</h1>
)
}
}
class Name extends React.Component{
render(){
return (
<h1>网站名称: {this.props.data}</h1>
)
}
}
class Nickname extends React.Component{
render(){
return (
<h1>网址小名: {this.props.data}</h1>
)
}
}
const element = (
<div>
<Url data='www.baidu.com'/>
<Name data='百度'/>
<Nickname data='百度'/>
</div>
)
ReactDOM.render(element,document.getElementById('example'))
// 5.0
class Clock extends React.Component {
constructor(props) {//挂载过程
super(props); //必须要写的解决this指向问题
this.state = { date: new Date() }
}
componentDidMount() {//组件第一次渲染完成执行 生命周期钩子
this.timerID = setInterval(
() => this.tick(),1000
);
}
componentWillUnmount() {//组件的卸载和数据的销毁时进行 生命周期钩子
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h6>哈喽 我的朋友</h6>
<h3>现在时间为:{this.state.date.toLocaleTimeString()}</h3>
</div>
)
}
}
ReactDOM.render(<Clock />, document.getElementById('example'))
// 6.0
function FormattedDate(props) {
return <h2>现在是 {props.date.toLocaleTimeString()}.</h2>;
}
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<FormattedDate date={this.state.date} />
</div>
);
}
}
function APP(){
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
)
}
ReactDOM.render(
<APP />,
document.getElementById('example')
);
// 7.0
class HelloMessage extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
HelloMessage.defaultProps = { //默认值
name: 'Runoob'
};
const element = <HelloMessage/>;
ReactDOM.render(
element,
document.getElementById('example')
);
// 8.0
class Element extends React.Component{
constructor(props){
super();
this.state = {show : 1};
// 这边绑定是必要的,这样 `this` 才能在回调函数中使用
// this.clickr = this.clickr.bind(this)
}
// clickr(){
// this.setState({
// show : this.state.show + 1
// })
// }
clickr(num,e){
this.setState({
show : num
})
}
render(){
return (
<div>
<button onClick={(e)=>this.clickr(5,e)}>当前值为:{this.state.show}</button>
<br/>
<br/>
<br/>
<button onClick={this.clickr.bind(this,5)}>当前值为:{this.state.show}</button>
</div>
)
}
}
// 第一种方法 在constructor 进行提前绑定
// 第二种方法:不进行绑定 但方法改成 clickr = () =>{ 这个属性初始化器样子接收
// 第三种方法:不绑定 但请求的时候改成 onClick={(e)=>this.clickr(e)} 你可以在回调函数中使用 箭头函数 不建议
// 都是为了this能够指向内部
// 传参 onClick={this.clickr.bind(this,5)} 接收 clickr(num,e)
function Element(){
function clickr(){
console.log('点击了一下')
}
return (
<div>
<h3>登录页面</h3>
<button onClick={clickr}>登录</button>
</div>
)
}
ReactDOM.render(<Element/>,document.getElementById('example'));
// 9.0
function Greeting(props) {
var show = props.show
if (show) {
return <h1>欢迎登录.</h1>
} else {
return <h1>请先注册.</h1>
}
}
function LogoutButton(props) {
return <button onClick={props.onClick}>{props.data}</button>
}
class LoginContorl extends React.Component {
constructor(props) {
super();
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = { show: true, arr: [1, 2, 3, 4] }
}
handleLogoutClick() {
this.setState({
show: false
})
}
handleLoginClick() {
this.setState({
show: true
})
}
render() {
var show = this.state.show
var arr = this.state.arr
return (
<div>
<Greeting show={show} />
{show ? (
<LogoutButton onClick={this.handleLogoutClick} data="退出" />
) : (
<LogoutButton onClick={this.handleLoginClick} data="注册" />
)}
{arr.length > 0 &&
<h2>
您有{arr.length}条未读消息
</h2>
}
</div>
)
}
}
ReactDOM.render(<LoginContorl />, document.getElementById('example'))
// 10.0
function List(props) {
const listitem = props.numbers.map((item,index) =>
<li key={index}>{item}</li>
)
return (
<ul>{listitem}</ul>
)
}
var arr = [1, 2, 3, 4, 5]
ReactDOM.render(<List numbers={arr} />, document.getElementById('example'))
// list.map 返回的是一个数组 编辑数组下的所有所有元素
{listitem} 对于数组自动展开
function Blog(props) {
const top = (
<ul>
{props.value.map((item) =>
<li key={item.id}>{item.title}</li>
)}
</ul>
)
const buttom = props.value.map((item) =>
<div key={item.id}>
<h6 >{item.title}</h6>
<p>{item.content}</p>
</div>
)
return(
<div>
{top}
<p>哈哈哈哈哈哈哈哈哈哈哈哈,人人皆大弟</p>
{buttom}
</div>
)
}
var list = [
{ id: 1, title: 'Hello World', content: 'Welcome to learning React!' },
{ id: 2, title: 'Installation', content: 'You can install React from npm.' }
]
ReactDOM.render(<Blog value={list} />, document.getElementById('example'))
// 如果有多层,建议提出组件,只有一层
// 11.0
// 7个方法: 设置状态:setState 替换状态:replaceState 设置属性:setProps
// 替换属性:replaceProps 强制更新:forceUpdate 获取DOM节点:findDOMNode 判断组件挂载状态:isMounted
// setState(object nextState[, function callback])
// 例:this.setState(function(state) {
// return {clickCount: state.clickCount + 1};
// });
// 例2:this.setState({
// show: false
// })
// 方法一:使用preState,concat创建新数组
// this.setState((prevState)=>({
// books: prevState.books.concat(['React Guide'])
// }))
// 方法二:ES6 spread syntax
// this.setState(prevState=>({
// books:[...prevState,'React Guide']
// }))
// 替换状态:replaceState
// replaceState(object nextState[, function callback])
// nextState,将要设置的新状态,该状态会替换当前的state。
// callback,可选参数,回调函数。该函数会在replaceState设置成功,且组件重新渲染后调用。
// 设置属性:setProps
// setProps(object nextProps[, function callback])
// 替换属性:replaceProps
// replaceProps(object nextProps[, function callback])
// 强制更新:forceUpdate
// forceUpdate([function callback])
// 获取DOM节点:findDOMNode
// DOMElement findDOMNode()
// 返回值:DOM元素DOMElement
// 判断组件挂载状态:isMounted
// bool isMounted()
// 返回值:true或false,表示组件是否已挂载到DOM中
// 12.0
// 组件的生命周期可分成三个状态:
// Mounting:已插入真实 DOM
// Updating:正在被重新渲染
// Unmounting:已移出真实 DOM
// componentWillMount 在渲染前调用,在客户端也在服务端。
// componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
// componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
// shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
// 可以在你确认不需要更新组件时使用。
// componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
// componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
// componentWillUnmount在组件从 DOM 中移除之前立刻被调用
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('在渲染前调用!')
}
componentDidMount() {
console.log('第一次渲染后调用!')
}
componentWillReceiveProps(newProps) {
console.log(' prop (更新后)时被调用!')
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('在组件接收到新的props或者state但还没有render时被调用!');
}
componentDidUpdate(prevProps, prevState) {
console.log('在组件完成更新后立即调用!')
}
componentWillUnmount() {
console.log('DOM 中移除之前立刻被调用。!')
}
render() {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
}
ReactDOM.render(
<div>
<Button />
</div>,
document.getElementById('example')
);
// 13.0 AJAX
class UserGist 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} 用户最新的 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')
);
// 父子组件传参 调用方法 更新
class Content extends React.Component {
render() {
return <div>
<input type="text" value={this.props.myDataProp} onChange={this.props.updateStateProp} />
<h4>{this.props.myDataProp}</h4>
</div>;
}
}
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: event.target.value});
}
render() {
var value = this.state.value;
return <div>
<Content myDataProp = {value}
updateStateProp = {this.handleChange}></Content>
</div>;
}
}
ReactDOM.render(
<HelloMessage />,
document.getElementById('example')
);
// 14.0 Refs
<input ref="myInput" />
var input = this.refs.myInput;
var inputValue = input.value;
var inputRect = input.getBoundingClientRect();
class MyComponent extends React.Component {
handleClick() {
// 使用原生的 DOM API 获取焦点
this.refs.myInput.focus();
}
render() {
// 当组件插入到 DOM 后,ref 属性添加一个组件的引用于到 this.refs
return (
<div>
<input type="text" ref="myInput" />
<input
type="button"
value="点我输入框获取焦点"
onClick={this.handleClick.bind(this)}
/>
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);