一、React 相关概念:
1.1. 含义:
- React 是一个用于构建用户界面的JavaScript库。
- React主要用于构建UI,很人多认为 React 是 MVC 中的 V(视图)。
- React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
- React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
1.2. 作用:
- 用做UI: 许多人把React当做MVC设计模式中的视图(view),当把React成为你的技术掌握之后, 它可以很轻松应用于一个小功能的项目。
- 虚拟DOM:React用一个”虚拟DOM”实现了超高的性能,配合nodeJS也可以实现在服务端的渲染,不存在耗时的浏览器dom渲染。
- 数据流: React是一种减少引用数据流的实现方式,并且比传统的方式更容易实现数据绑定。
- React Native 项目就是使用 React 和 JavaScript 创建本机 APP。
1.3. 特点:
- 声明式设计 −React采用声明范式,可以轻松描述应用。
- 高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
- 灵活 −React可以与已知的库或框架很好地配合。
- JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
- 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
- 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
二、安装
- 关于安装这里不再赘述,你可以在官网 http://facebook.github.io/react/ 下载最新版;
- 也可以直接使用 cdn 上的React CDN 库,地址如下:
<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
说明:
1.react.min.js - React 的核心库;
2.react-dom.min.js - 提供与 DOM 相关的功能;
3.browser.min.js - 用于将 JSX 语法转为 JavaScript 语法,关于 JSX 语法在下面说明。
三、 React JSX 语法说明
- JSX 的语法如下:
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
以上代码将一个 h1 标题,插入 id="example" 节点中。
如果我们需要使用 JSX,则 <script> 标签的 type 属性需要设置为 text/babel。
我们可以在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中
- 完整示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
</head>
<body>
<div id="em1"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, YijiangWang! {1+2}</h1>,
document.getElementById('em1')
)
</script>
</body>
</html>
四、 组件
- 通过方法
React.createClass
方法用于生成一个组件类; - 如果我们需要向组件传递参数,可以使用 this.props 对象,实例如下:
var Yjw_component = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(
<Yjw_component name="Yjw" />,
document.getElementById('example')
);
注意:
1.原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头;
2.组件类只能包含一个顶层标签,否则也会报错。
- 复合组件:
//自定义符合组件
/**
* 注意点:
* 1、组件首字母要大写
* 2、不能 return 多个控件,如果需要返回多个控件,可以在最外层用一个控件进行包装
* 3、return 控件时,要用 () 进行包装
* */
var Contenttxt = React.createClass({
render:function () {
return (
<h1>{this.props.contentt}</h1>
)
}
});
var Titletxt = React.createClass({
render:function () {
return (
<h2>{this.props.titlet}</h2>
)
}
});
var Article = React.createClass({
render:function () {
return (
<div>
<Titletxt titlet={this.props.titlet} />
<Contenttxt contentt={this.props.contentt} />
</div>
)
}
});
ReactDOM.render(
<Article titlet="I'm the title" contentt="I'm the content"></Article>,
document.getElementById("example")
)
五、React State(状态)
//自定义一个组件
var Yjw = React.createClass({
//定义初始状态
getInitialState:function () {
return {like:true};
},
//定义一个点击事件
handle:function () {
this.setState({like:!this.state.like})
},
render:function () {
var text = this.state.like?"喜欢":"不喜欢";
return (
<h1 onClick={this.handle}>{this.props.titlet}如果你 <ins>{text}</ins> 我,就点我</h1>
)
},
});
//渲染一个组件
ReactDOM.render(
<Yjw/>,
document.getElementById("example")
)
六、React Props
- 设置默认 props
var Dprop = React.createClass({
getDefaultProps:function () {
return {
name:"yijiang"
}
},
render:function () {
return (
<h1>这里是默认的:{this.props.name}</h1>
)
}
});
ReactDOM.render(
<Dprop name="mage"/>,
document.getElementById("prop1")
);
- props 和 state 结合使用
var Name = React.createClass({
render:function () {
return <h1>I'm {this.props.name}</h1>
}
});
var Site = React.createClass({
render:function () {
return <a href={this.props.site}>{this.props.site}</a>
}
});
var Website = React.createClass({
getInitialState:function () {
return {
name:"yijiang",
site:"www.baidu.com"
}
},
clickName:function () {
this.setState({name:"magege"});
},
render:function () {
return (
<div onClick={this.clickName}>
<Name name={this.state.name}/>
<Site site={this.state.site}/>
</div>
)
}
});
ReactDOM.render(
<Website/>,
document.getElementById("prop2")
);
- prop 验证:这里验证 title 必须为 string 类型,并且是必须字段:
var Vprop = React.createClass({
propTypes:{
title:React.PropTypes.string.isRequired
},
render:function () {
return (<h1>{this.props.title}</h1>)
}
});
ReactDOM.render(
<Vprop title="123"/>,
document.getElementById("prop3")
)
更多的验证器说明如下
React.createClass({
propTypes: {
// 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
// 可以被渲染的对象 numbers, strings, elements 或 array
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 用 JS 的 instanceof 操作符声明 prop 为类的实例。
optionalMessage: React.PropTypes.instanceOf(Message),
// 用 enum 来限制 prop 只接受指定的值。
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 可以是多个对象类型中的一个
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 指定类型组成的数组
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 指定类型的属性构成的对象
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 特定 shape 参数的对象
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 任意类型加上 `isRequired` 来使 prop 不可空。
requiredFunc: React.PropTypes.func.isRequired,
// 不可空的任意类型
requiredAny: React.PropTypes.any.isRequired,
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
},
/* ... */
});
六、React 组件 API
-
设置状态:setState
-
替换状态:replaceState
-
设置属性setProps
-
替换属性replaceProps
-
强制更新:forceUpdate
-
获取DOM节点:findDOMNode
-
判断组件挂载状态:isMounted
这里列举两例:setState 和 setProps,其它 API 使用大同小异,这里不一一例举:
//setState
var Sta = React.createClass({
getInitialState:function () {
return {
clickCount:0
}
},
// clickEvent:function () {
// this.setState({clickCount:this.state.clickCount+1})
// },
//这里两个 clickEvent 方法作用相同
clickEvent:function () {
this.setState(function (state) {
return {clickCount:state.clickCount+1}
})
},
render:function () {
return <h1 onClick={this.clickEvent}>点击的次数为:{this.state.clickCount}</h1>
}
});
ReactDOM.render(
<Sta/>,
document.getElementById("example1")
);
//setProps
var Sprop = React.createClass({
getInitialProps:function () {
return {
clickCount:0
}
},
clickEvent:function () {
this.setProps({clickCount:this.props.clickCount+1})
},
//这里两个 clickEvent 方法作用相同
// clickEvent:function () {
// this.setProps(function (state) {
// return {clickCount:state.clickCount+1}
// })
// },
render:function () {
return <h1 onClick={this.clickEvent}>点击的次数为:{this.props.clickCount}</h1>
}
});
ReactDOM.render(
<Sta/>,
document.getElementById("example2")
)
七、生命周期函数
- 生命周期的方法有:
- componentWillMount 在渲染前调用,在客户端也在服务端。
- componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。
- componentWillReceiveProps 在组件接收到一个新的prop时被调用。这个方法在初始化render时不会被调用。
- shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。 可以在你确认不需要更新组件时使用。
- componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
- componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
- componentWillUnmount在组件从 DOM 中移除的时候立刻被调用。
<body>
<div id="em1"></div>
<div id="em2"></div>
<script type="text/babel">
//定义一个 Hello 组件,并且每秒钟重新渲染一次
var Hello = React.createClass({
//初始化 state
getInitialState:function () {
return {opacity:1.0}
},
componentDidMount:function () {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= 0.2;
if (opacity < 0.1){
opacity = 1.0;
}
this.setState({opacity:opacity})
}.bind(this),1000);
},
render:function () {
return (
<div style={{opacity:this.state.opacity}}>
Hello {this.props.name}
</div>
)
}
});
ReactDOM.render(
<Hello name="Yijiang"/>,
document.getElementById("em1")
);
//定义一个 Button 组件
var Button = React.createClass({
getInitialState:function () {
return {data:0}
},
setNewNumber:function () {
this.setState({data:this.state.data+1})
},
render:function () {
return (
<div>
<button onClick={this.setNewNumber}>Increment</button>
<Content myNumber={this.state.data}></Content>
</div>
)
}
});
//定义一个 Content 组件
var Content = React.createClass({
componentWillMount:function () {
console.log("component Will Mount");
},
componentDidMount:function () {
console.log("component Did Mount");
},
componentWillReceiveProps:function(newProps) {
console.log('Component WILL RECIEVE PROPS!')
},
shouldComponentUpdate:function(newProps, newState) {
return true;
},
componentWillUpdate:function(nextProps, nextState) {
console.log('Component WILL UPDATE!');
},
componentDidUpdate:function(prevProps, prevState) {
console.log('Component DID UPDATE!')
},
componentWillUnmount:function() {
console.log('Component WILL UNMOUNT!')
},
render: function () {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
});
ReactDOM.render(
<div>
<Button />
</div>,
document.getElementById('em2')
);
/**
* 首先会展示前两条:
* component Will Mount
* component Did Mount
* 当点击之后会显示以下三条
* Component WILL RECIEVE PROPS!
* Component WILL UPDATE!
* Component DID UPDATE!
*/
</script>
</body>
八、React AJAX:
- React 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据库可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI。
- 当使用异步加载数据时,在组件卸载前,在 componentWillUnmount 里面取消未完成的请求。
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
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: function() {
this.serverRequest.abort();
},
render: function() {
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("em1")
);
九、React 表单与事件:
<body>
<div id="em1"></div>
<div id="em2"></div>
<div id="em3"></div>
<div id="em4"></div>
<script type="text/babel">
//一、React 表单与事件
//设置输入框 input 值value = {this.state.data}。在输入框值发生变化时我们可以更新 state。
var Yjw_input = React.createClass({
getInitialState:function () {
return {value:"Yijiangwang"}
},
changeValue:function (event) {
this.setState({value:event.target.value})
},
render:function () {
var txt = this.state.value;
return (
<div>
<h3>这里是value的值:{this.state.value}</h3>
<input value={this.state.value} onChange={this.changeValue}/>
</div>
)
}
});
ReactDOM.render(
<Yjw_input></Yjw_input>,
document.getElementById("em1")
);
//在子组件上使用表单。 onChange 方法将触发 state 的更新并将更新的值传递到子组件的输入框的 value 上来重新渲染界面。
//在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp,这里名字可以随意取) 传递到你的子组件上。
//创建一个子组件
var Content = React.createClass({
render:function () {
return <div>
<h4>{this.props.myDataProp}</h4>
<input type="text" value={this.props.myDataProp} onChange={this.props.updateStateProp} />
</div>;
}
});
//创建一个父组件
var HelloMessage = React.createClass({
getInitialState: function() {
return {value: 'Hello Yijiang!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
var value = this.state.value;
return <div>
<Content myDataProp = {value}
updateStateProp = {this.handleChange}></Content>
</div>;
}
});
ReactDOM.render(
<HelloMessage />,
document.getElementById('em2')
);
//二、React 事件
//通过 onClick 事件来修改数据
var Yjw_click = React.createClass({
getInitialState: function() {
return {value: 'Hello Yijiang!'};
},
handleChange: function(event) {
this.setState({value: 'Hello YijiangWang!'})
},
render: function() {
var value = this.state.value;
return <div>
<button onClick={this.handleChange}>点我</button>
<h4>{value}</h4>
</div>;
}
});
ReactDOM.render(
<Yjw_click />,
document.getElementById('em3')
);
//当需要从子组件中更新父组件的 state 时,需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到子组件上。
//子组件
var Child_event = React.createClass({
render: function() {
return <div>
<button onClick = {this.props.updateStateProp}>点我</button>
<h4>{this.props.myDataProp}</h4>
</div>
}
});
//父组件
var Father_event = React.createClass({
getInitialState: function() {
return {value: 'Hello Yijiang!'};
},
handleChange: function(event) {
this.setState({value: 'Hello YijiangWang!'})
},
render: function() {
var value = this.state.value;
return <div>
<Child_event myDataProp = {value}
updateStateProp = {this.handleChange}></Child_event>
</div>;
}
});
ReactDOM.render(
<Father_event />,
document.getElementById('em4')
);
</script>
</body>
十、React Refs
- React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。
- 这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。
- 使用方法:
//绑定一个 ref 属性到 render 的返回值上:
<input ref="myInput" />
//在其它代码中,通过 this.refs 获取支撑实例:
var input = this.refs.myInput;
var inputValue = input.value;
var inputRect = input.getBoundingClientRect();
- 具体实例:
<div id="em1"></div>
<script type="text/babel">
//可以通过使用 this 来获取当前 React 组件,或使用 ref 来获取组件的引用
var Yjw_component = React.createClass({
handleClick: function() {
// 使用原生的 DOM API 获取焦点
this.refs.myInput.focus();
},
render: function() {
// 当组件插入到 DOM 后,ref 属性添加一个组件的引用于到 this.refs
return (
<div>
<input type="text" ref="myInput" />
<input
type="button"
value="点我输入框获取焦点"
onClick={this.handleClick}
/>
</div>
);
}
});
ReactDOM.render(
<Yjw_component />,
document.getElementById('em1')
);
</script>
网友评论