使用webpack+npm进行React开发

写在前面

这一期的知识我早就想写了,因为在学习React之初,心里面就有很多疑问,当然其中一个就是:我能不能不把所有的Component写在一个文件中,当然后面没有关注这样的问题,直到前些日子学习Flux才重视起来,恰逢周六,在这里写一篇,关于如何使用webpack+npm进行React开发。

webpack–脚手架工具而已

在这里我并不打算详细介绍webpack如何使用,webpack只是一个前端脚手架工具而已,在进行React开发的时候,我们只是使用babel转换ES6的代码而已,但是webpack也是一个好用而简单的打包工具,想了解更多关于webpack的知识,点击这里
好吧,正式开始吧!
首先我们需要安装node 和 npm, 因为webpack也是依赖node的,安装好node和npm后我们就可以开始安装webpack了,首先安装webpack:

1
npm install -g webpack

当然这里你也可以不全局安装,使用npm init初始化一个package.json文件,使用npm install --save webpack安装。

这里我将会跳过使用命令进行打包,直接进到使用配置管理文件就好了,如果想更深层次的了解webpack,点击上面的介绍咯(真的很详细)。

首先介绍一下这个配置文件,默认命名为webpack.config.js,其是一个node的文件,就像如下的这个样子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	
module.exports = {
entry: './base.jsx',
output: {
filename: './output.js'
},
module: {
loaders:[
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['es2015','react']
}
}
]
}
}

好吧,介绍一下上面的这个文件到底描述了些什么,首先我们输出了一个配置对象,entry定义了要引入的文件,当然如果需要引入多个文件的话可以使用一个数组。output顾名思义定义要输出的文件名,这里可以把它理解为打包好存放的文件。
最后,下面的这个module属性用于定义加载器,比如我们需要使用babel来吧jsx转为普通的js代码,test属性表示给所有匹配的jsx执行解析,
exclude表示将会不解析node模块和通过bower安装的模块。loader表示使用解析工具,query则表示的扩展参数,这里表示应用es6和react的解析规则。
好了,对示例文件的简单介绍就告一段路,当然还有一个属性plugins,用于使用插件,有关插件的使用请移至官方文档。

搭建react的开发环境

细心的童鞋可以发现了,上面我演示的配置文件就是一个用于开发react的基本配置文件。好吧,直接开始,首先安装react,

1
2
npm install --save react
npm install --save react-dom

接着安装babel用于解析jsx和es6,

1
npm install --save babel-loader

最后安装一些解析规则

1
2
3
npm install babel-plugin-transform-es2015-arrow-functions --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react

到这里,我们就安装完了开发react所需要的模块了,好吧,直接进入最后一步,在这里我将写一个和小很小的例子

一个栗子

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

import React from 'react';
import {render} from 'react-dom';
class InputComp extends React.Component{
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
value: ''
}
}
handleChange(e){
var newvalue = e.target.value.trim();
this.setState({value: newvalue})
}
render() {
return (
<div>
<input ref="name" type="text" defaultValue={this.props.tag} onChange={this.handleChange}/>
<p>{this.state.value}</p>
</div>
)
}
}
InputComp.propTypes = {
tag: React.PropTypes.string.isRequired
}
InputComp.defaultProps = {
tag: '输入点什么东西吧!'
}
const tag = '请输入';
render(<InputComp />,document.getElementById('app'));

上面的小例子来源于react首页上面的一个例子,这里使用react的写法,对es6不是很了解的童鞋可以点这里,关于适用ES5开发react和使用es6开发有什么区别,可以看我的上一篇博客,这里就不做过多的介绍,
接下来,使用webpack进行打包就好了,使用上面举例的config文件,运行命令webpack就可以了,然后将输出文件引入到html文件中就可以看到效果了,当然如果你不想每一次修改都运行一遍命令的话那就使用监听更新模式,运行

1
webpack --progress --watch

当你修改完文件后,其会监听到文件的改变而做出增量的修改打包(当然第一次还是得手动打包)

尾巴

写到这里,这篇文章就算完了,当你一步步完成上面的步骤,你就搭建了一个十分简陋的React开发环境,这里所说的的是简陋,我并没有加载对css文件的打包,这里大家可以根据自己的需求添加不同的loader来完成。作为一个React的初学者,感觉React这一个体系是十分庞大的,庞大到学习React一个多月仍然觉得力不从心,作为一个大三孩纸,每天被上不完的专业课实验课所压着,抽出来学习的时间并不多,再有自身比较懒惰所以…
好吧,不多说了,好好努力吧,毕竟路都是自己选的。

分享到 评论

使用ES6语法写React

写在前面

最近在学习Redux,不可避免使用npm + webpack的方式来写React Component,由于不是很熟悉ES6踩了很多坑,在这里作为笔记写下来,供以后回顾。

例子

惯例,先写一个例子吧

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
	import React, { Component } from 'react';
import { PropTypes } from 'prop-types';

class InputComp extends Component{
constructor(props){
super(props);
this.state = {
name: ''
}
}
handleChange = (e) =>{
var newvalue = e.target.value.trim();
this.setState({[e.target.name]: newvalue})
}
render() {
const { value } = this.state;
return (
<div>
<input name="name" type="text" value={value} defaultValue={this.props.tag} onChange={this.handleChange}/>
<p>{value}</p>
</div>
)
}
}
InputComp.propTypes = {
tag: PropTypes.string.isRequired
}
InputComp.defaultProps = {
tag: '输入点什么东西吧!'
}

上面是使用ES6语法写的一个简单的Component,有过ES6基础的同学对class, ‘extends’关键字等不会陌生,简单来说,这算是js的语法糖了吧。
组件是一个自定义的js对象,在es5中使用React.createClass();在es6中必须继承React.component。

上面的小例子没什么特别的,我们只需要注意两点就好了:
对于props,我们不能使用getDefaultProps()来添加默认的props,在ES6中有一个属性defalutProps,同理属性校验器propTypes,我们也必须写在外面,内容都和以前一样。也可以把这两个属性都写在’类’里面,使用static关键字申明.
对于state,我们不能使用getInitialState()来设置state的初始值,转而在构造器中使用state属性设置值即可。
对于事件而言,this指向的是当前创建的Component对象,所以需要手动绑定。
还有一些其他的差别,比如es6支持解构等
好吧,简单的就写在这里了

好忙好忙,语言都没办法组织了!
加油!

分享到 评论

JS定时器知多少

在JavaScript中,定时器是一个经常被误用且不被大家所熟识的特性。但在构建应用时其却非常有用。
定时器提供了一种让一段代码在一定的时间之后运行的能力。由于JS的单线程特性,其同一时间只能执行一处代码,而定时器跳出了这一性质,以其特有的方式来执行代码。

在浏览器环境当中,window对象下有两组方法,setTimeOut()/clearTimeOut()以及setInterval()/clearInterval()分别用于设置定时器让其在一段时间后执行/让其停止和每隔一段时间就会执行一次/清除该定时器。
比如下面的代码:

1
2
3
4
5
6
setTimeOut(function(){
// do somethign
}, 1000);
setInterval(function(){
// do this code every 1s
}, 1000);

上面的代码分别创建了一个一次执行定时器和循环执行的定时器,每隔一秒钟,function就会被执行一遍

咋一看,setInterval就像周期性执行setTimeout一样,但是他们有很多不同之处。
举个栗子:

1
2
3
4
5
6
setTimeOut(function repect(){
setTimeOut(repect, 100);
}, 100);
setInterval(function(){
// do some thing
}, 100)

上面两段代码的功能几乎是一样的,但是实际上却不是。setTimeOut()代码中执行前一个回调结束后100毫秒甚至更多,才会执行下一个回调
而setInterval()不一样,每隔100毫秒就会尝试执行,不会受到前面回调的影响。那为什么执行一个setTimeOut()执行回调的时间会更长呢?因为js单线程的特性,当计时时间到,回调函数会被放入执行队列排队,并且执行回调是需要时间的,所以执行时间只会大于设置的时间。setInterval()也一样,但有一点,由于其不关注前一个回调执行的情况,如果一直被延迟,那么setInterval()在可用后会无延迟执行。

好吧,写个栗子证明一下上面的结论:

1
2
3
4
5

console.time('测试setTimeOut执行的时间')
setTimeOut(function(){
console.timeEnd('测试setTimeOut执行的时间');
},1000);

执行结果为:
测试setTimeOut执行的时间: 1004.673ms

关于setInterval()的演示和清除定时器的演示这里就不做了。

分享到 评论

浅谈JS闭包

变量的作用域

了解JS的人都知道,在ES6之前JavaScript中只有函数作用域和全局作用域,而没有块级作用域(try…catch是一个例外)。该怎么理解这句话呢?我们先来看一个例子:

1
2
3
4
for(var i=0; i<5; i++){
console.log(`i=${i}`)
}
console.log(i) // 4

当运行完一个for循环后,i=4。由于JS中不存在块级作用域,所以这里在for循环中申明的变量i是一个全局变量,因此可以在外部访问到。
现在我们来看下一个例子:

1
2
3
4
5
6
7
8
9
function init(){
var name = 'limoer';
function sayHello(){
console.log(`hello ${name}`)
}
sayHello();
}
init(); // hello limoer
console.log(name); // undefined

这里我们定义了一个函数,函数中申明了一个局部变量name,并且在函数内部定义了一个内部函数sayHello,这个函数只能在函数init内使用,然而sayHello并没有自己的局部变量,但是其可以访问到函数外部的变量,即其父级函数的name变量

通过上面的两个例子可以清楚的知道,变量的作用域完全是由它在源代码中的位置决定的,并且嵌套的函数也可以访问其外层作用域中的变量。

闭包

闭包和变量的作用域息息相关。现在我们来修改上面的这个例子

1
2
3
4
5
6
7
8
9
function init(){
var name = 'limoer';
function sayHello(){
console.log(`hello ${name}`)
}
return sayHello
}
var sayHelloFunc = init();
sayHello(); // hello limoer

注意修改的地方,我们这次是直接返回这个内部函数,然后在外部执行这个函数。
但是,通常来说,当函数一旦运行完成,其局部变量就不可用了,在这里是当执行了var sayHelloFunc = init();后name应该不可用了。但是实际运行情况是成功访问到了name这个属性。

原因是因为这里sayHelloFunc已经成为了一个闭包。它由两部分组成,返回的函数本身以及创建该函数的环境。
而所谓的环境是由闭包在创建时其作用域内的变量组成的。对于上面的这个例子,这里的变量就是指的name

再看一个闭包的例子

1
2
3
4
5
6
7
8
9
function addSome(num){
return function(y){
console.log(num + y)
}
}
var add10 = addSome(10);
var add1 = addSome(1);
add10(1); // 11
add1(10); // 11

对于上面的这个例子,addSome()做为一个函数工厂产生了两个闭包,它们共享了函数的定义,但是却又保存了不同的环境。

闭包的应用

通过上面的描述,知道闭包其实就是将函数和其作用环境相互关联起来,达到保存变量的目的。

把上面的例子稍微改一下,我们可以把它用到实践中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id="toBlue">切换背景为蓝色</button>
<button id="toYello">切换背景为黄色</button>
<button id="toGreen">切换背景成绿色</button>
<script type="text/javascript">
function changeBgColorTo(type){
return function(){
document.body.style.backgroundColor = type;
}
};
var toBlue = changeBgColorTo('blue');
var toYellow = changeBgColorTo('yellow');
var toGreen = changeBgColorTo('green');
document.getElementsById('toBlue').addEventListener('click', toBlue);
document.getElementsById('toYellow').addEventListener('click', toYello);
document.getElementsById('toGreen').addEventListener('click', toGreen);
</script>
</body>
</html>

上面的例子展示了如何使用闭包来定义公共函数,来减少代码的冗余。

一个常见的错误,使用闭包来解决

直接贴代码吧:
html:

1
2
3
4
<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>

js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}

function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];

for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
}
setupHelp();

上面的代码是我们实际开发过程中非常常见的错误。我们使用循环来给每一个输入框绑定一个事件,从而实现当聚焦到不同的输入框是产生不同的输出。
但是,上面的代码显然不能完成这样的工作,因为当循环完成后,此时item已经指向了helpText的最后一项,而给onfocus绑定的是一个匿名函数,当聚焦到某一个输入框时,执行showHelp(item.help)而item早已是helpText中的最后一项了,所以造成了错误.

知道错误后,我们就知道改怎样修改了。我们需要保存运行时的环境,返回一个闭包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];

for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = (function(help) {
return function(){
showHelp(help)
}
})(item.help);
}
}

好了,简单的对于闭包的介绍就到这里了!
想更系统的学习JS点击这里

分享到 评论

踩过React表单的坑后有感

如题所示,最近捣鼓React表单踩坑了,才捣鼓没多少时日,心就变浮躁了,开始看不下去文档,也不谷歌百度直接开码,然后就是各种报错,越报错心越急越得不到解决心情越差,好不容易静下心来搜集资料准备搞定表单,这里先记下来,以备不时只需!

踩过的坑…

直接开写吧:

input标签忘记闭合导致报错

1
2
3
4
5
6
var SimpleComp = React.createClass({
render(){
return <input type="text" placeholder="随便输入点什么吧!">
}
});
ReactDOM.render(<SimpleComp />, document.body)

运行上面的这段代码,发现并页面渲染异常,打开浏览器console一看,下面的出现了错误,并且是下面这样的:

报错图片

清清楚楚明明白白,标签并没有闭合,并且直指9行行最后渲染出了问题,然后我就一直找一直找,没错误啊,可始终还是报错
最后经过各种尝试才知道,input标签要强制闭合的,不然就会转换错误
知道真相的我眼泪掉下来,原来是这么回事啊,平时html写得飞起,细节这些什么的,都没注意哎!
再有,控制台上打印的异常和错误可千万别轻信,以前已经在这个被坑过了

受控与不受控

有过React基础的童鞋都知道,React内部通过props和state来传递属性和状态,其中属性经由组件外属性传入,作用于组件后无法改变
state 产生于组件内部, 通过setState()来改变状态,每一次改变状态,组件将会被重绘
对于表单来说,props和state用得都很频繁,所以在这里提及一下

先来看非受控组件吧,顾名思义就是组件的状态不受控制,从代码上体现出来的就是,一个input不含有value属性

1
2
3
4
5
6
var NotControlComp = React.createClass({
render() {
return <input type="text" defaultValue={this.props.placeholder}/>
}
});
ReactDOM.render(<NotControlComp placeholder='随便输入点什么吧!' />, document.body)

上面的一段代码定义了一个非受控的input,接受用户的输入而改变状态
注意:这里使用到的defaultValue属性作用类似于placeholder属性

好吧,事实上我们使用非受控组件的情况比较多,我们会监听input的onChange时间,通过state来更新状态
下面是一个简单的获取用户输入的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var ExampleComp = React.createClass({
getDefaultProps(){
return{placeholder: '输入吧'}
},
getInitialState(){
return{
val: ''
}
},
handleChange(e){
this.setState({val: e.target.value})
},
render(){
return(
<div>
<input type="text" defaultValue={this.props.val} onChange={this.handleChange}/>
<p>你输入了:{this.state.val}</p>
</div>
)
}
});
ReactDOM.render(<ExampleComp placeholder='随便输入点什么吧!' />, document.body)

那么受控组件就很显而易见了,受控的input定义了一个value属性,并且value部位null

1
2
3
4
5
6
var ControlComp = React.createClass({
render(){
return <input type="text" value="不要尝试修改这个值啦!" />
}
});
ReactDOM.render(<ControlComp />, document.getElementById('app'))

好了,最简单的受控组件就写好了,当你尝试去修改表单中的值的时候,发现根本无法修改
这点明显和我们平时写html不一样,同样的input标签在html中就可以修改但是到了react中就没办法修改了,想过原因吗?
官方文档中给出了答案: 不比HTML,React组件必须在任何时间点呈现视图的状态而不仅仅是在初始化的时候, 好好理解!

其他

  1. 不要通过添加子节点的方式给<textarea>添加内容,应该使用defaultValue或者value属性,避免产生歧义,因为JSX本身就是javascript

  2. 你可以通过selected属性来选中一个下拉栏, 但是为了组件的可操作性,请使用value 或者 defaultValue来代替就像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var SelectComp = React.createClass({
    render(){
    return(
    <select value='B'>
    <option value='A'>A</option>
    <option value='B'>A</option>
    <option value='C'>A</option>
    </select>
    )
    }
    });
    ReactDOM.render(<SelectComp />, document.body)

    想要非受控组件的话,就使用defaultValue属性好了
    当然了,可以通过传入一个数组来达到多选的目的, 前提是给select添加multiple={true}就可以了

看到这里,也许有人心里还有疑问,受控的组件既然不能修改那到底该怎么用?
对于这个问题,请看下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var ControlComp = React.createClass({
getInitialState(){
return{value: 0}
},
handleClick(e){

this.setState({value: this.state.value + 1})
},
render(){
return (
<div>
<input type="text" value={this.state.value} />
<button onClick={this.handleClick}>+</button>
</div>
)
}
});
ReactDOM.render(<ControlComp />, document.body)

好了,我们添加了一个button来控制受控组件的值,当然还有很多方式,比如我们可以给受控组件添加一个onChange事件监听

好了,React表单的基本知识就说到这里,感谢那些曾经让我烦躁无比的坑!

分享到 评论

在React中使用mixin

mixin到底为何方神圣?

mixin被理解为‘混入’的意思,
我们知道,如果你经常使用某一段相同的代码的时候,你会把它进行抽象,封装成类或者function,
‘混入’也一样,它可以解决代码段重复的问题。

jade中的Mixins

jade(pug)是一个高性能的模版引擎,它使用javascript实现,并提供给Node使用.
我在使用Jade模版引擎接触到了Mixin, 下面给出一个例子理解下

1
2
3
4
5
6
7
8
9
10
mixin box(styles)
.conponent
-each style in styles
.squire
-var x = styles.indexOf(style) + 1;
a(href='/users/' + x + '/list') #{style}
.container
mixin(['lin', 'limoer'])
.links
mixin(['parents', 'classmates', 'others'])

你可以无视jade的语法,如果你想学习jade,点这里

首先我使用mixin 关键字申明了一个带参数mixin结构,然后依据传入的参数生成了很多url
这个mixin 结构可以在这个模版文件中使用,通过不同的参数来生成url
从上面可以看出,mixin的确可以解决代码重复的问题

React中的Mixin

首先来写一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var TimerComp = React.createClass({
getInitialState: function() {
return {secondsElapsed: 0}
},
tick: function() {
this.stateState({secondsElapsed: this.state.secondsElapsed + 1})
},
componentDidMount: function() {
this.interval = setInterval(this.tick, 1000)
},
componentWillUnmount: function() {
clearInterval(this.interval)
},
render: function(){
return (
<div>
<p>Seconds Elapse {this.state.secondsElapsed}</p>
</div>
)
}
});

简单的说一下,这里定义了一个定时器组件,会随着时间的增加来自动计时
但是一个应用需要多个计时器呢?我们第一时间想到了组件的嵌套,但是组件的嵌套不但会增加组件的复杂程度
而且,想要修改计时器也是比较困难的
好了,解决代码复用的问题,我们可以使用Mixin, 让其混入进其他组件就好了

码起,还是计时器的例子!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var MixinTimerComp = React.createClass({
mixins: [MixinInterval(1000)],
getInitialState: function() {
return {secondsElapsed: 0}
},
onTick: function(){
this.setState({secondsElapsed: this.state.secondsElapsed + 1})
},
render: function(){
return (
<div>
<p>Seconds Elapse {this.state.secondsElapsed}</p>
</div>
)
}
});

这里我们使用了mixins属性,把自定义的MixinInterval对象混入了Timer组件

来看看MixinInterval的实现:

1
2
3
4
5
6
7
8
9
10
var MixinInterval: function(interval) {
return {
componentDidMount() {
this.__interval = setInterval(this.onTick, interval)
},
componentWillUnmount() {
clearInterval(this.__interval)
}
}
};

就这样实现了一个最简单的问题,和最前面的例子做对比,我们发现,只是把组件中一些代码独立出来成为一个mixin对象
但这样做无疑是解决了代码重用的问题,当我们想定义另一个计时器时候,我们只需混入这个mixin代码
而不必关心混入的计时处理对象是怎么实现的

mixin 实现起来非常简单,React也支持多个mixin的混入(在mixins赋值为一个mixin对象数组)
但有一个问题需要注意,在mixin中尝试覆盖state中定义的键的话,React会抛出错误

1
2
3
4
5
6
7
8
9
10
11
React.createClass({
mixins: [{
getInitialState(){
return {cover: 1}
}
}],
getInitialState(){
return {cover: 2}
}
})
// 错误,尝试覆盖cover属性
分享到 评论

React学习之JSX

什么是JSX?

简单点说,JSX是对javascript的扩展,语法类似于XML,但JSX不是一门新的语言,
确切来说只是语法糖,每一个XML都会被响应的转换工具转换成纯的javascript代码。
在使用React时,你没有必要使用JSX来构建组件,但是推荐使用JSX,因为这样可以让组件的结构
和组件之间的关系看起来更清晰。

好了,开始使用JSX吧!

首先我们分别使用JSX和纯js来渲染一个组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// 使用JSX
ReactDOM.render(
<div>
<h2>使用了JSX语法糖</h2>
</div>,
document.body
)
// 不使用jsx
ReactDOM.render(
React.createElement('div', null,
React.createElement('h1', null, '不使用jsx')
),
document.body
)

html标签和React组件

ReactDOM.render()可以渲染html标签,也可以渲染React组件,但是这里有一些命名上的规范

html标签使用首字母小写的方式,但使用首字母大写也能够正常加载

1
2
var renderDiv = <div>这是一个标签</div>
ReactDOM.render(renderDiv, document.body)

React组件使用首字母大写的方式

1
2
3
4
5
6
var RenderComp = React.createClass({
render: function(){
return: <div>这是一个组件</div>
}
});
ReactDOM.render(<RenderComp />, document.body)

经过测试,发现如果使用首字母小写的方式,将不会正常渲染组件,也不会报错, 当然你也可以这样写:

1
2
3
4
5
6
7
var RenderComp = React.createClass({
render: function(){
return: <div>这是一个组件</div>
}
});
var renderComp = <RenderComp />
ReactDOM.render(renderComp, document.body)

js表达式

当我们想要在React中使用js变量或者是表达式时候,使用{}来进行包裹,不能够出现””,否则会被当作字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var SampleComp = React.createClass({
getInitialState: function(){
return {
iscls: false;
}
},
render: function(){
return (
// 表达式
<div className={this.state.iscls ? 'cls' : 'no_cls'}>
// 变量
<h2>{this.props.msg}</h2>
</div>
)
}
});
ReactDOM.render(<SampleComp msg='学习搬砖中...' />, document.body)

这里提示一下,在JSX中,标签的class和for属性分别使用className和htmlFor代替了

其它

在给标签添加style属性的时候,应该这样写:

1
style={{display: 'none'}}

也可以把要应用的样式赋值给一个变量,再使用变量

1
2
3
4
5
var style = {
color: red,
display: none
};
<div style={style}></div>

HTML转义,为了防止XSS攻击,React默认是使用转义的,所以当你想使用一些富文本这里就必须注意
为了不让其转义,我们可以这样写:

1
2
3
4
5
6
var mesg = '<h2>这里的字体大小是多少?</h2>'
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: mesg}}>
</div>,
document.body
)

总结

刚开始学习React的时候对JSX是生畏的,以为会很难理解。当慢慢的接触React,踩过一些小坑,
发现使用JSX是那么好掌握, 它仅仅是语法糖而已,并且转换的规则也很简单

分享到 评论

写在正式学习React之前

如果你还不知道大名鼎鼎的ReactJS, 先去这里看看吧

在使用过了诸如BootStrap, Foundation这类的前端框架后,在初识React就被其虚拟DOM和组件化的开发深深的吸引。
然后在接下来的几天,我慢慢的对React产生的恐惧,模式转变得太快,让我很不舒服。
然后又经过几天玩坏了,我才返现React简直是一股清流,开始爱上它了!

好了,开始使用React吧!

安装React

请先安装Node和npm

使用React之前,先来安装一下bower

1
$ npm install -g bower

安装bower后我们来正式的进入React的学习中来

新建一个目录

1
$ mkdir proj

使用以下命令来安装React

1
$ bower install react

安装完后我们在proj目录下会看见一个bower_components目录,目录里面有一个React目录,ok!

1
$ touch index.html

使用文本编辑器打开index.html, 开始码起!

第一个React helloworld

引入react.js和react-dom.js(在head,或者body中引入都可以,但是必须在我们开写地方的上面)

就像这样
引入图片

接着申明一个script标签

1
<script type="text/babel"></script>

注意这里的type是text/babel

1
2
3
4
5
6
7
8
9
10
var HelloWorldComponent = React.createClass({
render: function(){
return (
<div id="app">
<h1>开始学习使用工具搬砖啦!</h1>
</div>
)
}
});
ReactDOM.render(<HelloWorldComponent />, document.body)

好了,不出意外的话,我们将会在浏览器中看到
结果图

好啦,我们的第一个react组件算是开发完成了,这里讲一讲我们到底做了什么
首先我们使用了JSX语法,有关JSX的知识会单独的加深了解,但是最基本的规则就是,遇到{}解析成js,遇到‘<’解析成html
然后使用了React提供的createClass来创建一个组件类,类名一定要大写,实现了其中一个必须要实现的render方法,返回一个h1标签
最后使用ReactDOM.render()渲染到body中去
搞定

分享到 评论