react入门
介绍:
中文入门介绍:
babel可以把es6
转为es5
https://kangax.github.io/compat-table/es6/查看浏览器对es6的支持情况
使用npm配置React环境
基于React15.3.2
步骤:
1.项目npm init
2.安装$ npm install --save react react-dom babelify babel-preset-react
3.支持es2015要安装$ npm install babel-preset-es2015 --save
webpack
热加载配置
先全局安装webpack
$ npm install -g webpack
全局安装webpack-dev-server
npm install -g webpack-dev-server
在项目目录中安装
npm install -save webpack-dev-server
npm install -save webpack
新建webpack.config.js
文件,内容如下:
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: __dirname + '/src',
entry: "./js/index.js",
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015'],
}
}
]
},
output: {
path: __dirname + '/src/',
filename: "bundle.js"
},
};
然后使用$ webpack
命令,可生产bundle.js
文件,在对应的html
中导入这个bundle.js
文件即可
可能的错误:
现在有一个问题就是,假设你修改了文件,你还要在编译一遍,才能在浏览器中看见效果,可使用webpack --watch
来监听改变
浏览器自动刷新,可运行$ webpack-dev-server
,终端提示:
Project is running at http://localhost:8080/
这样只要一保存,浏览器会自动刷新
注意:在新版本的 webpack-dev-server 中,因为取消了 content-base 参数,所以需要热加载自动刷新的话,直接执行命令
webpack-dev-server --hot --inline
即可。
ChromeRect插件
React Developer Tools
安装后,提示中多了个react
React组件基础
React组件
组件是React的一个主要特性。
注意:组件生成的 HTML 结构只能有一个单一的根节点。
给外部使用的组件定义要使用:export default class ComponentHeader extends React.Component
,注意使用export default
入口的定义:ReactDom.render(<Index/>,document.getElementById('example'))
var React = require('react');
var ReactDom = require('react-dom');
import ComponentHeader from './components/header';
class Index extends React.Component{
render(){
return (
<div>
<ComponentHeader/>
<h2>内欧诺个</h2>
</div>
)
}
}
ReactDom.render(<Index/>,document.getElementById('example'))
React多组件嵌套
例如,我们可以创建多个组件。例如,在components
下,创建3个组件:
1.header.js
组件
import React from 'react';
export default class ComponentHeader extends React.Component{
render(){
return (
<header>
<h1>这里是header</h1>
</header>
)
}
}
2.footer.js
组件
import React from 'react';
export default class ComponentFooter extends React.Component{
render(){
return (
<footer>
<h1>这里是footer,一般放置版权的信息</h1>
</footer>
)
}
}
3.bodyindex.js
组件
import React from 'react';
export default class BodyIndex extends React.Component{
render(){
return (
<div>
<h1>页面主体内容</h1>
</div>
)
}
}
在入口文件index.js
中,使用这三个组件:
var React = require('react');
var ReactDom = require('react-dom');
import ComponentHeader from './components/header';
import ComponentFooter from './components/footer'
import BodyIndex from './components/bodyindex'
class Index extends React.Component{
render(){
return (
<div>
<ComponentHeader/>
<BodyIndex/>
<ComponentFooter/>
</div>
)
}
}
ReactDom.render(<Index/>,document.getElementById('example'))
在浏览器中通过react
插件,如下:
另外,组件也可以通过参数的形式来传递,如下:
class Index extends React.Component{
render(){
var component = <ComponentHeader/>
return (
<div>
{component}
<BodyIndex/>
<ComponentFooter/>
</div>
)
}
}
JSX内置表达式
如何使用三元表达式和布尔值?
render(){
var username = 'Harry';
var boolInput = false
return (
<div>
<h1>页面主体内容</h1>
<p>{username=='' ? '用户还没有登录' : '用户名:'+username}</p>
<p><input type='button' value={username} disabled={boolInput}/></p>
</div>
)
}
可能出现的问题:渲染到页面上乱码
JSX注释
{/*注释*/}
HTML
要显示可以进行Unicode
转码
例如,在html中常用
来表示空格,但如果直接定义一个变量,如下:
var html = 'abc def';
如果使用<p>{html}</p>
直接显示,会发现
并没有被转换为空格
可做Unicode
转码,如:
var html = 'abc\u0020def';
即可在html中正常显示
另一种方式是通过<div dangerouslySetInnerHTML={{__html: html}}></div>
,注意此方法可能会存在XSS
攻击
生命周期
componentWillMount()
页面将要加载
componentDidMount()
页面已经加载完了
参考:
React属性与事件
State属性
React
把组件看成是一个状态机(State Machines
)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React
里,只需更新组件的 state
,然后根据新的 state
重新渲染用户界面(不要操作 DOM
)
State
初始化,如this.state = {username:"Harry"};
初始化可以放在构造函数constructor()
里面:
constructor(){
//调用基类的所有初始化方法
super();
this.state = {username:"Harry"};
}
修改state
:this.setState({username:'imooc'});
state
的作用域只属于当前的类,不污染其它的模块
state
对于模块来说属于自身的属性
按钮事件修改state
的值
changeUserInfo(){
this.setState({age:50});
}
...
<input type="button" value="提交" onClick={this.changeUserInfo.bind(this)}/>
注意onClick={this.changeUserInfo.bind(this)}
使用了bind(this)
,否则的话会出错
还有另一个问题是,想要在changeUserInfo
中传递改变的值,肿么办?
changeUserInfo(age){
this.setState({age:age});
};
<input type="button" value="提交" onClick={this.changeUserInfo.bind(this,99)}/>
注意:
Props属性
Props对于模块来说属于外来属性
例如在index.js
中传递参数<BodyIndex userid={123456} username={"nick"}/>
在bodyindex.js
中使用传递的参数<p>{this.state.username} {this.state.age} {this.props.userid} {this.props.username}</p>
事件与数据的双向绑定
在上面的例子中,父组件可以向子组件传递参数,那么子组件如何向父组件传递参数呢?
在子页面通过调用父页面传递过来的事件props
进行组件间的参数传递
如再定义一个BodyIndex
的子组件BodyChild
,BodyChild
中有一个输入框,输入时修改BodyIndex
中state
属性的age
的值
bodychild.js
import React from 'react';
export default class BodyChild extends React.Component {
render(){
return (
<div>
<p>子页面输入:<input type="text" onChange={this.props.handleChildValueChange}/></p>
</div>
)
}
}
在bodyindex.js
中使用的方式如下:
handleChildValueChange(event){
this.setState({age:event.target.value})
};
......
<p>{this.state.age}</p>
<BodyChild handleChildValueChange={this.handleChildValueChange.bind(this)}/>
效果如下:
可复用组件
在上面的例子中,使用了props
属性来从父页面向子页面传递数据
<p>接收到的父页面的参数:userid:{this.props.userid} username:{this.props.username}</p>
有一种情况是,假设我想要userid
传递的必须是整数,而不是字符串类型,所以如何做验证?
BodyIndex.propTypes = {
userid: PropTypes.number
}
注意:
React.PropTypes
is deprecated as of React v15.5. Please use the prop-types library instead.
可参考老师,React.PropTypes.number这么用,在React v15.5.0以后就有报错了。
isRequired
表示一个必须的参数
BodyIndex.propTypes = {
userid: PropTypes.number.isRequired
}
Default Prop Values
默认的prop值
const defaultProps = {
username: '这是一个默认的用户名'
};
BodyIndex.defaultProps = defaultProps
如何把A组件的父页面的props参数,传递给A的子页面?简便快捷的方法{...this.props}
:
<BodyChild {...this.props} id={4} handleChildValueChange={this.handleChildValueChange.bind(this)}/>
参考:Typechecking With PropTypes
组件的Refs(操作DOM的两种方法)
组件的Refs主要是用来获取一些原生的html节点
例如,如下的input
标签
<input id="submitButton" type="button" value="提交" onClick={this.changeUserInfo.bind(this,99)}/>
第一种方式:
changeUserInfo(age){
this.setState({age:age});
//第一种方式
var mySubmitButton = document.getElementById('submitButton');
ReactDom.findDOMNode(mySubmitButton).style.color = 'red';
};
第二种方式,定义一个ref
<input id="submitButton" ref="submitButton" type="button" value="提交" onClick={this.changeUserInfo.bind(this,99)}/>
//第二种方式
this.refs.submitButton.style.color = 'red';
Refs
是访问到组件内部DOM节点唯一可靠的方法
Refs
会自动销毁对子组件的引用
不要在render
或render
之前对Refs
进行调用,不要滥用Refs
独立组件间共享Mixins
NOTE: 使用 ES6 class 定义的组件已经不支持 mixin 了,因为使用 mixin 的场景都可以用组合组件这种模式来做到,参见 Mixins Are Dead. Long Live Composition
Mixing
在不同的组件之间共用功能,共享代码
如定义一个如下的Mixins.js
,其中有一个log
方法
const MixinLog = {
log(){
console.log('abcdefg...')
}
}
export default MixinLog
使用之前
import ReactMixin from 'react-mixin'
import MixinLog from './mixins';
......
ReactMixin(BodyIndex.prototype, MixinLog);
在对应的地方使用方式如下:
MixinLog.log();