一个用于构建web界面的js库-React

-- 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,项目框架

|-node_modules             //项目包
|-public             //一般用于存放静态文件,打包时会被直接复制到输出目录(./buidle)
|-src               //项目源代码
|  |-asserts         //用于存放静态资源,打包时会经过 webpack 处理
  |  |-components     //组件 存放 React 组件,一般是该项目公用的无状态组件
|  |-containers          //页面视图
|  |-routes         //路由 存放需要 connect model 的路由组件
  |  |-App.js         //入口文件
  |  |-index         //注册路由与服务
  |  |- serviceWorker        //开发配置
|-package.json      //包管理代码
|-.gitignore //Git忽略文件

常见问题

快速入门


[从一段示例说起]

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) ES6class组件.

   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 />      } 

/>

  );

}

 



参考资料