React学习(一)

一、React起步

1.1 bower 的使用

bower是前端界的npm。npm有npm install命令,bower也有bower install命令。用来管理、维护前端开发中的JS库的。

bower只负责前端库,nodejs的东西它不管,比如你bower拿不到mongodb的。

自定义bower的安装目录

在项目根下创建一个名为.bowerrc的文件然后

1
2
3
{
"directory" : "js/lib" //指定bower安装的目录
}

执行bower install react可以看到文件下载到 js 文件夹下的 lib 文件夹中了。

bower初始化

1
2
bower init  
// 在git bash中执行会出错,在windows cmd 中执行此命令

会提示你输入一些基本信息,根据提示按回车或者空格即可,然后会生成一个bower.json文件,用来保存该项目的配置

包的安装

比如要安装一个react,输入如下命令:

1
bower install react --save

然后bower就会从远程下载react最新版本到你的js/lib目录下
其中–save参数是保存配置到你的bower.json,你会发现bower.json文件已经多了一行:

1
2
3
"dependencies": {
"react": "^15.6.1"
}

1.2 认识 babel 和 JSX

bable是一个compiler(编译器),英语原意是噪音的意思,把噪音变为我们能听懂的声音。

bable可以最大限度的让我们的前端界面,现在就可以使用ECMAScript2016甚至今后有更新的语法。bable会把它编译为现在能用的JS语句。

我们现在仅仅需要把babel运行在前端。所以此时仅仅需要用bower去下载即可:

1
bower install babel

下载之后的文件叫做 browser.min.js,表示babel在浏览器端在进行babel语句的编译。

babel和react共同提供了一个语法,叫做jsx。

1.3 Hello,World !

引入三个文件,分别是react、react-dom、browser(是babel文件):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="js/react/react.min.js"></script>
<script type="text/javascript" src="js/react/react-dom.min.js"></script>
<script type="text/javascript" src="js/babel/browser.min.js"></script>
</head>
<body>
<div id="box"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello,React!</h1>,
document.getElementById('box')
);
</script>
</body>
</html>

在一个script标签,这个标签的type是text/babel,此时babel就会在浏览器端进行JSX和ECMAScript2016的翻译工作。

ReactDOM.render()函数表示让一个JSX让它上树,此时接受两个参数,一个JSX语句,一个是盒子。

1
2
3
4
ReactDOM.render(
<h1>Hello,React!</h1>,
document.getElementById('box')
);

此时盒子中的所有内容都将被ReactDOM对象接管。

JSX是一个语法糖,目的就是让HTML拥有JavaScript的作用域,这是一个React突破性的创举。

比如:

1
2
3
4
5
6
7
<script type="text/babel">
var str="Cool";
ReactDOM.render(
<h1>Hello,React!{str}</h1>,
document.getElementById('box')
);
</script>

此时JSX语句,“沐浴”在了JS的作用域下。

JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。

JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员

1
2
3
4
5
6
7
8
9
10
<script type="text/babel">
var arr = [
<h1>Hello world!</h1>,
<h2>React is awesome</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('box')
);
</script>

二、创建组件

2.1 方法一

最简单的创建一个自定义的组件的方法,就是使用一个函数,这个函数必须大写字母开头,如果是小写字母开头就不会渲染为组件。函数返回JSX语句。使用这个组件的时候,用自封闭标签来当做这个组件放置的位置:

1
2
3
4
5
6
7
8
9
10
<script type="text/babel">
function MyComponent(){
return <h1>Welcome !</h1>;
}

ReactDOM.render(
<MyComponent/>,
document.getElementById("box")
);
</script>

2.2 方法二

创建一个自定义组件,就是创建一个类,这个类要继承React.Component对象。这个类必须定义类方法render,这个方法返回一个JSX语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/babel">
//要定义一个组件,实际上就是定义一个类
class MyComponent extends React.Component{
render(){
return <h1>我是一个h1,我买了一个iphone{3+4}</h1>
}
}

//应用这个组件
ReactDOM.render(
<section>
<MyComponent />
<MyComponent />
<MyComponent />
<MyComponent />
</section>
,
document.getElementById("box")
)
</script>

2.3 方法三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script type="text/babel">
var MyComponent = React.createClass({
render : function(){
return <h1>我是一个h1,我是{2 + 4}</h1>
}
});

ReactDOM.render(
<section>
<MyComponent />
<MyComponent />
<MyComponent />
</section>
,
document.getElementById("box")
)
</script>

三、获得组件自定义属性

3.1 this.props

我们创建组件,肯定要设置、使用组件上面的属性。请看下面的程序,在创建组件的时候,JSX中如果出现了this,this一定表示使用这个组件的时候写的那个自定义标签。props就是函数的属性,可以继续打点去枚举任何属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script type="text/babel">
var MyComponent = React.createClass({
render : function(){
return <p>{this.props.a}</p>;
}
});
ReactDOM.render(
<section>
<MyComponent a="11"/>
<MyComponent a="22"/>
<MyComponent a="33"/>
</section>
,
document.querySelector("#box")
);
</script>

3.2 组件的嵌套,属性级级上传

组件的嵌套,属性可以级级上传。this是使用这个自定义组件的时候那个标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script type="text/babel">
var InnerComponent = React.createClass({
render : function(){
return <a href={this.props["data-href"]}>去这个网站</a>;
}
});


var MyComponent = React.createClass({
render : function(){
return (
<div>
<h1>{this.props.info}</h1>
<InnerComponent data-href={this.props["data-href"]} />
</div>
);
}
});

ReactDOM.render(
<section>
<MyComponent info="百度" data-href="http://www.baidu.com/"/>
<MyComponent info="网易" data-href="http://www.163.com/"/>
<MyComponent info="搜狐" data-href="http://www.sohu.cn/"/>
</section>
,
document.querySelector("#box")
);
</script>

四、获得真实的DOM节点

4.1 先说说事件监听

我们现在要给一个组件里面的按钮添加事件监听,此时用onClick、onMoouseenter、onFocus的写法,所有原来的事件名,on之后的字母大写,此时React会帮你用DOM2级绑定到冒泡阶段上。注意大写字母!!

创建一个组件的时候,不仅仅只有Render方法,还可以有其他方法,其他方法都是组件里面的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/babel">
var MyComponent = React.createClass({
sayhello : function(){
alert('Hello')
},
render : function(){
return (
<section>
<h1>Hello</h1>
<input type="button" value="按钮" onClick={this.sayhello}/>
</section>
);
}
});
ReactDOM.render(
<MyComponent />
,
document.querySelector("#box")
)
</script>

4.2 获得DOM元素

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/babel">
var MyComponent = React.createClass({
changeColor : function(){
this.refs.mytext.style.color="red";
},
render : function(){
return (
<section>
<h1 ref="mytext">Hello</h1>
<input type="button" value="按钮" onClick={this.changeColor}/>
</section>
);
}
});
ReactDOM.render(
<MyComponent />
,
document.querySelector("#box")
)
</script>

this.refs.[refName]就会返回这个真实的 DOM 节点。注意设置的时候用ref,引用的使用用refs

五、状态

我们用React创建的每一个component都有自己的状态,实际上定义的时候是状态的模型,实例化每一个component的时候,每一个component都拥有自己的状态。state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

5.1 初始状态和使用状态

我们现在可以给这个组件的实例设置一个状态,状态是一个JSON对象,里面用k-v来维持一个个状态,此时用getInitialState函数来设置初始状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type="text/babel">
var MyComponent = React.createClass({
//创建一个组件类
//得到初始状态函数,这个函数必须返回一个对象
getInitialState : function(){
return {
"a" : 1
}
},
render : function(){
return <h1>{this.state.a}</h1>
}
});

//使用组件
ReactDOM.render(
<MyComponent></MyComponent>
,
document.getElementById("box")
)
</script>

如果创建组件的时候使用的是ES6的class关键字创建的,可以很明显看见state是自己身上的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyComponent extends React.Component{
constructor(props){
super(props); //调用超类

//所谓的状态就是自己身上的属性
this.state = {
"a" : 1
}
}

render(){
return <h1>你好{this.state.a}</h1>
}
}

5.2 设置状态

如果要更改状态, 不能直接用点语法更改状态,一定要使用setState()函数,因为这个函数能够让视图同步刷新。但是是局部刷新,就是所有用到这个状态的地方进行刷新。

案例 - 购物车数量

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script type="text/babel">

var MyComponent = React.createClass({
//创建一个组件类
//得到初始状态函数,这个函数必须返回一个对象
getInitialState : function(){
return {
"a" : 1
}
},
minus : function(){
//让状态改变,setState会引发视图的刷新。并且还是局部刷新。
this.setState({"a" : this.state.a - 1});
},
add : function(){
this.setState({"a" : this.state.a + 1});
},
render : function(){
return (
<div>
<input type="button" value="-" onClick={this.minus} />
<span>{this.state.a}</span>
<input type="button" value="+" onClick={this.add}/>
</div>
)
}
});

//使用组件
ReactDOM.render(
<div>
<MyComponent></MyComponent>
<MyComponent></MyComponent>
<MyComponent></MyComponent>
<MyComponent></MyComponent>
</div>
,
document.getElementById("box")
)
</script>

六、组件的生命周期

在创建一个组件的时候,语法就是

1
2
3
4
5
6
7
React.createClass({
//这里书写下面的方法
componentWillMount : function(){},
componentDidMount : function(){},
...
render: function(){}
});

一个组件有三个状态:Mount上树、update更新、unmount下树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
componentWillMount 在渲染前调用,在客户端也在服务端。

componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.refs来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。

componentWillReceiveProps 在组件接收到一个新的prop时被调用。这个方法在初始化render时不会被调用。

shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。

componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。

componentWillUnmount在组件从 DOM 中移除的时候立刻被调用。
------ 本文结束 ------
0%