-- React的安装与配置
【官网】:http://facebook.github.io/react/
应用场景
在构建web界面时,我们通常要考虑:是否轻易能够描述应用,是否能复用,是否能与现有的库和框架配合使用..通通这些都可以通过React很好的解决。基础资源
node,webpack,create-react-app
使用须知
1
配置步骤
1,安装NODE,
2,安装webpack
1 npm install -g webpack
3,配置淘宝镜像
使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm
1 npm install -g cnpm --registry=https://registry.npm.taobao.org 2 npm config set registry https://registry.npm.taobao.org
4,安装create-react-app
1 cnpm install -g create-react-app
5,创建项目
1 create-react-app my-project//创建项目 2 cd my-project/
6,本地服务启动
1 npm run start//启动本地server用于开发
2.2,项目框架
| |-asserts //用于存放静态资源,打包时会经过 webpack 处理
| |-containers //页面视图
| |-routes //路由 存放需要 connect model 的路由组件
常见问题
快速入门
[从一段示例说起]
ReactDOM.render(
element,
document.getElementById(‘root‘));
[注1]上述elemet可以是dom元素构成,也可以自定义组件构成。
示例1).
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById(‘root‘));
示例2).
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />; //Welcome是组件名, name是组件的参数对象.
ReactDOM.render(
element,
document.getElementById(‘root‘)
);
【Jsx说明 】
1.)React 不强制要求使用 JSX,但是大多数人发现,在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用。它还可以使 React 显示更多有用的错误和警告消息.
2.)输入内容防止xss攻击.
const title = response.potentiallyMaliciousInput;
//直接使用是安全的:
const element = <h1>{title}</h1>;
3.)dom元素的属性值:只能使用引号(对于字符串值)或大括号(对于表达式)中的一个.
const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;
4.)由于Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,几种Render的等效写法:
[形式1]
const element = (
<h1 className="greeting">
Hello, world!
</h1>);
[形式2]
const element = React.createElement(
‘h1‘,
{className: ‘greeting‘},
‘Hello, world!‘);
注:React.createElement() 会预先执行一些检查,以帮助你编写无错代码.
【React组件】
[概念] 组件允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思。本指南旨在介绍组件的相关理念。
[注1]React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome.
[注2]所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
[两种等效的组件]
1) 函数组件.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
2) ES6的class组件.
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
[组件嵌套]
function WelcomList() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
【state和生命周期】
[示例]
//props是外部传入的属性对象,严禁修改.
// state是本对象中的私有成员,可以修改,但只能在构造函数中this.state=,外面只能用this.setState({comment: ‘Hello‘});
class Clock extends React.Component {
//构造函数
constructor(props) {
super(props);
this.state = {date: new Date()};
}
//当 Clock 的输出被插入到 DOM 中后.
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
// Clock 组件从 DOM 中被移除.
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({ date: new Date() }); //this.setState每次调用都会触发render();
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById(‘root‘)
);
[注1]当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state.
[注2]组件可以选择把它的 state 作为 props 向下传递到它的子组件中.
<FormattedDate date={this.state.date} />
【事件处理】
[注1]React 事件的命名采用小驼峰式(camelCase),而不是纯小写.
[注2]使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串.
<button onClick={activateLasers}> Activate Lasers</button>.
[注3] React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault .
function ActionLink() {
function handleClick(e) {
e.preventDefault(); //阻止往下走
console.log(‘The link was clicked.‘);
}
return (
<a href="#" onClick={handleClick}> Click me </a>
);
}
[注4]使用 React 时,你一般不需要使用 addEventListener 为已创建的 DOM 元素添加监听器。事实上,你只需要在该元素初始渲染的时候添加监听器即可.
[示例]
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}> {this.state.isToggleOn ? ‘ON‘ : ‘OFF‘} </button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById(‘root‘)
);
[注5]如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined。
这并不是 React 特有的行为;这其实与 JavaScript 函数工作原理有关。通常情况下,如果你没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 this。
[注6]向事件处理程序中传递参数。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
【条件渲染】
[示例]
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById(‘root‘)
);
【列表&Key】
[渲染多个组件]
const numbers = [1, 2, 3, 4, 5];
const numbers_v2 = numbers.map((number) => number * 2);//所有值变更为2倍
const listItems =numbers_v2 .map((number) =>
<li key={number.toString()}>{number}</li> //循环每个元素
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById(‘root‘)
);
[注1]如果没有上述key则会提示异常”a key should be provided for list items”,key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识.
【表单】
[注1]传统的 HTML 表单行为,即在用户提交表单后浏览到新页面。如果你在 React 中执行相同的代码,它依然有效,例如:
<form>
<label>
名字:
<input type="text" name="name" />
</label>
<input type="submit" value="提交" />
</form>
[注2]使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
[注3]由于在表单元素上设置了 value 属性,因此显示的值将始终为 this.state.value,这使得 React 的 state 成为唯一数据源。由于 handlechange 在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。
[示例]
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === ‘checkbox‘ ? target.checked : target.value; const name = target.name;
this.setState({ [name]: value });
}
handleSubmit(event) {
alert(‘你喜欢的风味是: ‘ + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
参与: <input name="isGoing" type="checkbox" checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
来宾人数: <input name="numberOfGuests" type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
【状态提升】
[注1]在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。
[注2]如果以计算温度的示例来说:Calculator 为整体组件,TemperatureInput为不同标准的温度的输入框:回顾一下 TemperatureInput 组件的变化。我们移除组件自身的 state,通过使用 this.props.temperature 替代 this.state.temperature 来读取温度数据。当我们想要响应数据改变时,我们需要调用 Calculator 组件提供的 this.props.onTemperatureChange(),而不再使用 this.setState():
class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value); //替代this.setState()
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature} onChange={this.handleChange} />
</fieldset>
);
}
}
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: ‘‘, scale: ‘c‘};
}
handleCelsiusChange(temperature) { this.setState({scale: ‘c‘, temperature}); }
handleFahrenheitChange(temperature) { this.setState({scale: ‘f‘, temperature}); }
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === ‘f‘ ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === ‘c‘ ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c" temperature={celsius} onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f" temperature={fahrenheit} onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict celsius={parseFloat(celsius)} />
</div>
);
}
}
【组合和继承】
[组合示例1:利用children prop实现组合]
function FancyBorder(props) {
return (
<div className={‘FancyBorder FancyBorder-‘ + props.color}> {props.children} </div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
[组合示例2:利用自己约定的占位符]
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);}
function App() {
return (
<SplitPane
left={ <Contacts /> }
right={ <Chat /> }
/>
);
}