一、在开始学习React之前,需要了解两个东西
1、ES6新版本:ES6相对于ES3、ES5做了很大的改动;具体参考:
http://es6.ruanyifeng.com/#docs/intro
2、Babel:Babel其实就是一个转码器;在React中使用了很多ES6的新语法,目前很多浏览器不是很支持
所以需要把写的js转化为ES5或ES3
使用得先安装一下
npm install -g babel 或利用 淘宝镜像命令 cnpm install -g babel
babel的配置文件:.babelrc
开发项目时,把其配置文件放置项目的根目录下即可:
该文件是用来设置转码规则和插件的;格式如下:
{
"presets": [],
"plugins": []
}
presets字段时设定转码规则的;转什么码需要安装什么规则:
# ES2015转码规则
$ npm install --save-dev babel-preset-es2015
# react转码规则
$ npm install --save-dev babel-preset-react
# ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3
然后,把这些规则加入到配置文件
.babelrc中
{
"presets": [
"es2015",
"react",
"stage-2"
],
"plugins": []
}
命令行转码babel-cli
Babel提供
babel-cli工具,用于命令行转码
使用得需要安装一下,安装命令:
$ npm install --global babel-cli
其本用法:
# 转码结果输出到标准输出
$ babel example.js
# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ babel example.js --out-file compiled.js
# 或者
$ babel example.js -o compiled.js
# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ babel src --out-dir lib
# 或者
$ babel src -d lib
# -s 参数生成source map文件
$ babel src -d lib -s
上面的代码是在全局环境下进行转码;这就说明项目要运行,需要在全局环境下必须要有Babel,这就说明了项目产生了对环境的依赖。这样一来就无法支持不同项目使用不同的版本。
下面提供一个一个解决方法。将babel-cli安装在项目中。
# 安装
$ npm install --save-dev babel-cli
然后,改写package.json文件
{
// ...
"devDependencies": {
"babel-cli": "^6.0.0"
},
"scripts": {
"build": "babel src -d lib"
},
}
转码的时候,就执行下面的命令
$ npm run build
babel就简单介绍到这。参照:
http://es6.ruanyifeng.com/#docs/intro
二、React正式入门
1、react的安装
npm install react
npm install rect
-dom
主要用到其中的 react.js 和 react-dom.js
<
script
src=
"node_modules/react/dist/react.js"></
script>
< script src= "node_modules/react-dom/dist/react-dom.js"></ script>
< script src= "node_modules/react-dom/dist/react-dom.js"></ script>
项目根目录下配置.babelrc文件
{
"presets": [
"react"] }
编写js文件的时候,因为react有自己的一套语法,需要babel转码
在终端可以使用babel命令自动监听转码
babel js
-
d dist
-
w
上面的代码意思是:把js文件夹下的reactjs文件自动转化为ES5的js文件放于dist文件夹中,-w是自动监听的意思
2、React的JSX语法
const
element
= <
h1>
Hello, world!</
h1>;
这个有趣的既不是一个字符串,也不是HTML标记语法。它叫做JSX,这是一个语法扩展JavaScript;形象的用来描述UI的样子;可以抽象的理解为虚拟DOM树;
class HelloMessage
extends React.
Component {
render() {
return < div> Hello { this. props.name}</ div>;
}
}
var mountNode = document. querySelector( '#root');
ReactDOM. render(< HelloMessage name ="张三" />, mountNode);
render() {
return < div> Hello { this. props.name}</ div>;
}
}
var mountNode = document. querySelector( '#root');
ReactDOM. render(< HelloMessage name ="张三" />, mountNode);
上面的代码,构建了类HelloMessage(组件),它继承于React.Component,ReactDOM.render();直接把组件返回的虚拟dom,渲染到mountNode中。
jsx里面可以通过{}内嵌表达式;可以把其理解为和js语法的表达式一样,就是可以把js于html一块写
里面很多运用ES6的新语法
function formatName( user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName : '小东',
lastName : '小明'
};
const ele = (
// <h1>
// Hello, {formatName(user)}
// </h1>
getGreeting( user)
);
function getGreeting( user) {
if( user){
return < h1> Hi,{ formatName( user)}</ h1>;
}
return < h1> Hi,Stranger.</ h1>;
}
const ele1 = (
< div>
< h1> Hi</ h1>
< h2>{ formatName( user)}</ h2>
</ div>
);
const ele2 = < div> Hello</ div>;
const ele3 = (
< h1 className ="hh">
你好,小胖子。
</ h1>
);
var root = document. querySelector( '#root');
ReactDOM. render( ele3, root);
//react-dom包提供了DOM操作的具体方法,如:组件渲染、节点找查等。
// 你可以在程序的最顶层使用它,除了必要的DOM操作,大多数组件不需要使用这个模块。
/**
ReactComponent render(
ReactElement element,
DOMElement container,
[function callback]
)
渲染一个ReactElement到DOM中
element,要渲染的的ReactElement
container,渲染结果在DOM中插入的位置
callback,回调函数,可选。传入该值时,会在组件渲染完或更新完成后调用
返回值:React组件
例子如上面的事例
*/
3、元素的渲染
const
ele1
= <
h1>
Hi,你好</
h1>;
function tick() {
const element = (
< div>
< h1> Hi,你好.</ h1>
< h2> It is { new Date(). toLocaleTimeString()}</ h2>
</ div>
);
var root = document. querySelector( '#root');
ReactDOM. render(element,root);
}
setInterval( tick, 1000);
function tick() {
const element = (
< div>
< h1> Hi,你好.</ h1>
< h2> It is { new Date(). toLocaleTimeString()}</ h2>
</ div>
);
var root = document. querySelector( '#root');
ReactDOM. render(element,root);
}
setInterval( tick, 1000);
4、React组件与Props
组件的概念:1.可重用 2.相互隔离
React组件:React组件与函数类似,接受固定的输入,返回固定的输出。
props:props是组件的输入,当react运行的时候,react会自动的组件上面的属性,合并到props对象中,传递给组件
props是不能被修改的(只读):带props的函数不能被修改,通常称为纯函数。
纯函数:
1.固定的输入,只返回固定的输出
2.不能对输入进行修改
3.里面不能有副作用的方法(date.now(),里面不能有网咯请求)
声明组件的方法有两种:1.函数式声明,2.class类继承式声明
//函数式声明
function ComponentExample( props) {
return < h1> Hi,{ props.name}</ h1>
}
//class类继承式声明
class ComponentExample2 extends React. Component{
render(){
return < h1> Hi,{ this. props.name}</ h1>
}
}
//组件可以引用其它组件的输出
function App() {
return (
< div>
< ComponentExample name ="小栋"/>
< ComponentExample name ="小白"/>
< ComponentExample name ="小明"/>
</ div>
);
}
var root = document. querySelector( '#root');
// ReactDOM.render(<ComponentExample2 name="小胖子"/>,root);
ReactDOM. render(< App />, root);
function ComponentExample( props) {
return < h1> Hi,{ props.name}</ h1>
}
//class类继承式声明
class ComponentExample2 extends React. Component{
render(){
return < h1> Hi,{ this. props.name}</ h1>
}
}
//组件可以引用其它组件的输出
function App() {
return (
< div>
< ComponentExample name ="小栋"/>
< ComponentExample name ="小白"/>
< ComponentExample name ="小明"/>
</ div>
);
}
var root = document. querySelector( '#root');
// ReactDOM.render(<ComponentExample2 name="小胖子"/>,root);
ReactDOM. render(< App />, root);
5、状态和生命周期
state的确定原则:
1.是否从父级传递下来
2.是否随时间改变
3.是否不能通过其它的组件state或props计算出来
/**
* state:保持私有属性;只能通过setState修改它的值
*
* componentDidMount: 组件声明周期钩子,这些方法被称为“生命周期钩”
*
* 单向数据流: 数据只能从父组件通过props往下流动;数据是单向的。
*
*/
class Clock extends React. Component{
constructor( props){
super( props);
this.state = {date : new Date()};
}
componentDidMount(){
this.timer = setInterval(() => this. tick(), 1000);
}
componentWillUnmount(){
clearInterval( this.timer);
}
tick(){
this. setState({
date : new Date()
});
}
//用this.state取代this.props,
render(){
return (
< div>
< h1> Hi,你好</ h1>
< h2> 现在是 { this.state.date. toLocaleTimeString()}</ h2>
</ div>
);
}
}
var root = document. querySelector( '#root');
ReactDOM. render(< Clock />, root);
* state:保持私有属性;只能通过setState修改它的值
*
* componentDidMount: 组件声明周期钩子,这些方法被称为“生命周期钩”
*
* 单向数据流: 数据只能从父组件通过props往下流动;数据是单向的。
*
*/
class Clock extends React. Component{
constructor( props){
super( props);
this.state = {date : new Date()};
}
componentDidMount(){
this.timer = setInterval(() => this. tick(), 1000);
}
componentWillUnmount(){
clearInterval( this.timer);
}
tick(){
this. setState({
date : new Date()
});
}
//用this.state取代this.props,
render(){
return (
< div>
< h1> Hi,你好</ h1>
< h2> 现在是 { this.state.date. toLocaleTimeString()}</ h2>
</ div>
);
}
}
var root = document. querySelector( '#root');
ReactDOM. render(< Clock />, root);
6、React事件处理
事件名必须使用驼峰命名法;事件的句柄,是函数的变量名
function ActionLink() {
function handleClick( e) {
e. preventDefault();
console.log( e);
}
return (
< a href ="#" onClick ={ handleClick}> 点击</ a>
);
}
var root = document. querySelector( '#root');
ReactDOM. render(< ActionLink />, root);
7、有条件的呈现
可能希望一个组件隐藏本身,尽管它是由另一个组件呈现。为此返回null代替其渲染输出。在下面的示例中,
function WarningBanner( props) {
//如果为假,返回null
if ( ! props.warn) {
return null;
}
//否则返回元素渲染
return (
< div className ="warning">
Warning!
</ div>
);
}
class Page extends React. Component {
constructor( props) {
super( props);
this.state = {showWarning : true}
this. handleToggleClick = this. handleToggleClick. bind( this);
}
//点击改变true或false
handleToggleClick() {
this. setState( prevState => ({
showWarning : ! prevState.showWarning
}));
}
render() {
return (
< div>
< WarningBanner warn ={ this.state.showWarning} />
< button onClick ={ this. handleToggleClick}>
{ this.state.showWarning ? 'Hide' : 'Show'}
</ button>
</ div>
);
}
}
ReactDOM. render(
< Page />,
document. getElementById( 'root')
);