一、初识react
1、Angular组件复杂,不利于重用。
2、React不是一个完整的MVC、MVVM框架
3、React跟Web Components 不冲突
4、Ract的特点就是“轻”
facebook 独立、小巧、快速、创新
5、组件化的开发思路(高度可重用)
二、React应用场景
1、复杂场景下的高性能
2、重用组件库,组件组合
3、“懒”——少做无用功
三、前置知识
1、JS、CSS基础
2、Sass、Compass
3、YEOman、Grunt、Webpack
4、CommonJS,NodeJS
5、Git,GitHub
四、React-JSX-Style
1、进React 官网 进reactJSFiddle
2、JSX 其中X是xml 语法糖,糖衣语法——对功能无影响
为了起作用,需要解析js,引入react.js和JSXTransformer.js
在script标签中,type="text/jsx"
react Compoents 自定义标签
定义自定义标签:
var Hello=React.creareClass({
render:function(){
var styleObj={
color:'red',
fontSize:'44px'
};
return <div className="alert-text">Hello {this.props.title}{this.props.name}</div>;
}
});
呈现到页面:调用React.render(<Hello name="world" title="MR"/>,
document.getElementById('container') //呈现到哪里
)
this:当前react Components(组件的意思)实例
props:在使用react Componemts时,在其上面添加的属性的集合
样式编写:
1、为标签添加class,但是不能直接写class,应写className(并在css文件中写相应样式)
2、直接内联样式,但不能写成style=“color:red;”应该写成style={color:‘red’} red要写成字符串形式
五、React-Components-Lifecycle(从创建到消失生命周期)
1、React-Components在浏览器中存在的生命周期三个状态
1)Mounted(安装):React Components 被render解析生成对应的DOM节点并被插入浏览器的DOM结构的一个过程
2)update(更新) :一个mounred的React Components被重新render(中文意思为使成为)的过程
3)unmounted (卸载):一个mounted的React Components对应的DOM节点被从DoM结构中移除的这样一个过程。
每一个状态React都封装了对应的hook函数
var Hello=React.creareClass({
getInitialState:function(){
alert(init);
return {
opacity:1.0,
fontSize:'12px',
};
},
render:function(){
return <div style={{opacity:this.state.opacity,fontSize:this.state.fontSize}}>Hello {this.props.title}{this.props.name}</div>;
},
componentWillMount:function(){
alert('will');
},
componentDidMount:function(){
alert('did');
var_self=this; //留住this 或者用bind(this)——bind是ES5才有的
window.setTimeout(function(){
_self.setState({
opacity:0.5,
fontSize:'44px'
});
},1000);
}};
Mounting可以调用的函数:getDefaultProps()、getInitialState()、componentWillMount
render、componentDidmount
Updating可以调用的函数:componentWillReceivePropos、shouldComponentUpdate、
componentWillUpdate、render、componentDidUpdate
Unmounting可以调用的函数:componentWillUnmount
六、React-Event-listener
React Components 事件绑定与处理;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/jsx">
var TestClickComponent=React.createClass({
handleClick:function(event){
var tipE=React.findDOMNode(this.refs.tip);
if(tipE.style.display==='none'){
tipE.style.display='inline';
}else{
tipE.style.display='none';
}
event.stopPropagation();
event.preventDefault();
},
render:function(){
return (
<div>
<button onClick={this.handleClick}>显示|隐藏</button><span ref="tip">测试点击</span>
</div>
);
}
});
var TestInputComponent=React.createClass({
getInitialState:function(){
return {
inputContent:''
}
},
changeHandler:function(event){
this.setState({
inputContent:event.target.value
});
event.stopPropagation();
event.preventDefault();
},
render:function(){
return (
<div>
<input type="text" onChange={this.changeHandler}/><span>{this.state.inputContent}</span>
</div>
);
}
});
React.render(
<div>
<TestClickComponent/>
<TestInputComponent/>
</div>,
document.getElementById('container')
);
</script>
</body>
</html>
七、react 的基础学习
1、React 简介
React 是一个用于构建用户界面的JAVASCRIPT库
React 主要用于构建UI,很多人认为React是MVC中的v(视图)
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已经开始关注和使用它
(1)React特点
1)声明式设计 ——React采用声明范式,可以轻松描述应用
2)高效——React 通过对 DOM的模拟,最大限度减少与DOM的交互
3) 灵活 ——React 可以与已知的库或框架很好地配合
4) JSX——JSX 是JavaScript 语法的扩展。React 开发不一定使用JSX,但我们建议使用它
5) 组件 ——通过React 构建组件,使得代码更加容易得到服用,能够很好的应用在大项目的开发中
6) React 实现了单向响应的数据流,从而减少了重复代码,这也是它比传统数据绑定更简单。
(2)React第一个实例
<div id="example"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world!</h1>,
document.getElementById('example') ); </script>
解析:我们引入了三个库:react.min.js、react-dom.min.js 和 babel.min.js
如果我们需要使用JSX,则<script>标签的type属性需要设置为text/babel
react.min.js ——React 的核心库
react-dom.min.js——提供与DOM相关的功能
babel —— Babel 可以将ES6 代码转为 ES5代码,这样我们就能在目前不支持ES6浏览器上执行React代码,
Babel 中内嵌了对JSX的支持。通过将Babel 和 babel-sublime 包一同使用可以让源码的语法渲染
上升到一个全新的水平。
2、基于npm的React开发环境搭建
第一步、安装全局包
$ npm install babel -g
$ npm install webpack -g
$ npm install webpack-dev-server -g
第二步、创建根目录
创建一个根目录,目录名为:reactApp,再使用 npm init 初始化,生成 package.json 文件:
$ mkdir reactApp
$ cd reactApp/
$ npm init
name: (reactApp) runoob-react-test
version: (1.0.0)
description: cllgeek
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/tianqixin/www/reactApp/package.json:
{
"name": "react-runoob",
"version": "1.0.0",
"description": "cllgeek test",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --hot"
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "^0.14.8",
"react-dom": "^0.14.8"
}
}
Is this ok? (yes)
第三步、添加越来包及插件
因为我们要使用 React, 所以我们需要先安装它,–save 命令用于将包添加至 package.json 文件。
$ npm install react --save
$ npm install react-dom --save
同时我们也要安装一些 babel 插件
$ npm install babel-core
$ npm install babel-loader
$ npm install babel-preset-react
$ npm install babel-preset-es2015
第四步、创建文件
接下来我们创建一些必要文件:
$ touch index.html
$ touch App.jsx
$ touch main.js
$ touch webpack.config.js
第五步、设置编译器,服务器,载入器
打开 webpack.config.js 文件添加以下代码:
var config = {
entry: './main.js',
output: {
path:'./',
filename: 'index.js',
},
devServer: {
inline: true,
port: 7777
},
module: {
loaders: [ {
test: /.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}]
}
}
module.exports = config;
entry: 指定打包的入口文件 main.js。
output:配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称。
devServer:设置服务器端口号为 7777,端口后你可以自己设定 。
module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。
现在打开 package.json 文件,找到 “scripts” 中的 “test” “echo ”Error: no test specified” && exit 1″ 使用以下代码替换:
"start": "webpack-dev-server --hot"
替换后的 package.json 文件 内容如下:
$ cat package.json
{
"name": "runoob-react-test",
"version": "1.0.0",
"description": "cllgeek test",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --hot"
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "^0.14.7",
"react-dom": "^0.14.7"
}
}
现在我们可以使用 npm start 命令来启动服务。–hot 命令会在文件变化后重新载入,这样我们就不需要在代码修改后重新刷新浏览器就能看到变化。
3、React JSX
React 使用 JSX 来替代常规的 JavaScript。
JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。
我们不需要一定使用 JSX,但它有以下优点:
- JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
- 它是类型安全的,在编译过程中就能发现错误。
- 使用 JSX 编写模板更加简单快速。
1)使用JSX
JSX 看起来类似 HTML ,我们可以看下实例:
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );
我们可以在以上代码中嵌套多个 HTML 标签,需要使用一个 div 元素包裹它,实例中的 p 元素添加了自定义属性 data-myattribute,添加自定义属性需要使用 data- 前缀。
ReactDOM.render( <div> <h1>菜鸟教程</h1> <h2>欢迎学习 React</h2> <p data-myattribute = "somevalue">这是一个很不错的 JavaScript 库!</p> </div> , document.getElementById('example') );
2)独立文件
你的 React JSX 代码可以放在一个独立文件上,例如我们创建一个 helloworld_react.js
文件,代码如下:
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );
然后在 HTML 文件中引入该 JS 文件:
<body> <div id="example"></div> <script type="text/babel" src="helloworld_react.js"></script> </body>
3)JavaScript 表达式
我们可以在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中。实例如下:
ReactDOM.render( <div> <h1>{1+1}</h1> </div> , document.getElementById('example')
在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。以下实例中如果变量 i 等于 1 浏览器将输出 true, 如果修改 i 的值,则会输出 false.
ReactDOM.render(
<div>
<h1>react的学习</h1>
<h2>{i ===1 ? 'true': 'false'}</h2>
<p data-myattribute = "somevalue">{4*5}</p>
</div>,
document.getElementById('example')
);
4)样式
React 推荐使用内联样式。我们可以使用 camelCase 语法来设置内联样式. React 会在指定元素数字后自动添加 px 。以下实例演示了为 h1 元素添加 myStyle 内联样式:
var myStyle = {
fontSize:100,
color:'#e4393c'
};
var i=1;
ReactDOM.render(
<div>
<h1 style = {myStyle}>小薇薇的学习</h1>
<h2>{i ===1 ? 'true': 'false'}</h2>
<p data-myattribute = "somevalue">{4*5}</p>
</div>,
document.getElementById('example')
);
5)注释
注释需要写在花括号中,实例如下:
ReactDOM.render( <div> <h1>菜鸟教程</h1> {/*注释...*/} </div>, document.getElementById('example') );
6)数组
JSX 允许在模板中插入数组,数组会自动展开所有成员:
var arr = [ <h1>菜鸟教程</h1>, <h2>学的不仅是技术,更是梦想!</h2>, ]; ReactDOM.render( <div>{arr}</div>, document.getElementById('example') );
7) html 标签 vs React 组件
React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。
要渲染 HTML 标签,只需在 JSX 里使用小写字母的标签名。
var myDivElement = <div className="foo">你好</div>;
ReactDOM.render(myDivElement, document.getElementById('example'));
要渲染 React 组件,只需创建一个大写字母开头的本地变量。
var MyComponent =React.createClass({
render: function() {
return <h1>Hello World!</h1>;
}
});
var myElement = <MyComponent/>;
ReactDOM.render(myElement, document.getElementById('example'));
//或者去掉变量myElement,直接写入 下面
ReactDOM.render(<MyComponent/>, document.getElementById('example'));
React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签。
注意:
由于 JSX 就是 JavaScript,一些标识符像
class
和for
不建议作为 XML 属性名。作为替代,React DOM 使用className
和htmlFor
来做对应的属性。
需要注意的问题:
关于React注释的问题:
1、在标签内部的注释需要花括号
2、在标签外的的注释不能使用花括号
关于React入门容易出错的地方:
如同上面说的,代码中嵌套多个 HTML 标签,需要使用一个标签元素包裹它
4、React 组件
本章节我们将讨论如何使用组件使得我们的应用更容易来管理。
接下来我们封装一个输出 "Hello World!" 的组件,组件名为 HelloMessage:
var HelloMessage = React.createClass({ render: function() { return <h1>Hello World!</h1>; } }); ReactDOM.render( <HelloMessage />, document.getElementById('example') );
React.createClass 方法用于生成一个组件类 HelloMessage。
<HelloMessage /> 实例组件类并输出信息。
注意,原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。
如果我们需要向组件传递参数,可以使用 this.props 对象,实例如下:
var MyComponent =React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(<MyComponent name="mary"/>,
document.getElementById('example'));
以上实例中 name 属性通过 this.props.name 来获取。
注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
复合组件
我们可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。
以下实例我们实现了输出网站名字和网址的组件:
var WebSite = React.createClass({
render: function() {
return (
<div>
<Name name={this.props.name} />
<Link site={this.props.site} />
</div>
);
}
});
var Name = React.createClass({
render: function() {
return (
<h1>{this.props.name}</h1>
);
}
});
var Link = React.createClass({
render: function() {
return (
<a href={this.props.site}>
{this.props.site}
</a>
);
}
});
ReactDOM.render(
<WebSite name="菜鸟教程" site=" http://www.runoob.com" />,
document.getElementById('example')
);
5、React State(状态)
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
以下实例中创建了 LikeButton 组件,getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件
var LikeButton = React.createClass({
/*初始化liked的值*/
getInitialState:function(){
return {liked:false};
},
/*改变liked的状态值*/
handleClick:function(event){
this.setState ({liked:!this.state.liked})
},
render:function(){
var text = this.state.liked ? '喜欢':'不喜欢';
return (
<p onClick = {this.handleClick}>
你<b>{text}</b> 我。点我切换状态。
</p>
);
}
});
ReactDOM.render(
<LikeButton/>,
document.getElementById("example")
);
6、React Props
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
以下实例演示了如何在组件中使用 props:
var HelloMessage = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; } }); ReactDOM.render( <HelloMessage name="Runoob" />, document.getElementById('example')
实例中 name 属性通过 this.props.name 来获取。
1)默认props
你可以通过 getDefaultProps() 方法为 props 设置默认值,实例如下:
var HelloWorld = React.createClass({
getDefaultProps:function(){
return {
name:"marry"
}
},
render:function(){
return <h1>hello {this.props.name}</h1>
}
});
ReactDOM.render(<HelloWorld name={"Bob"}/>,
document.getElementById("example")
);
//当 <HelloWorld />中有name值时,显示此值,没有时,就显示默认的props的name值,即显示 marry
2)state 和 Props
以下实例演示了如何在应用中组合使用 state 和 props 。我们可以在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据。
var WebSite = React.createClass({
getInitialState:function(){
return {
name:"marry",
site:"http:www.baidu.com"
};
},
render:function(){
return (
<div>
<Name name={this.state.name}/>
<Link site={this.state.site}/>
</div>
);
}
});
var Name = React.createClass({
render:function(){
return (
<h1>{this.props.name}</h1>
);
}
});
var Link = React.createClass({
render:function(){
return (
<a href={this.props.site}>
{this.props.site}
</a>
);
}
});
ReactDOM.render(
<WebSite />,
document.getElementById("example")
);
3) Props 验证
Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。
以下实例创建一个 Mytitle 组件,属性 title 是必须的且是字符串,非字符串类型会自动转换为字符串 (无法转为字符串类型时就会报错):
var title = "菜鸟教程";
// var title = 123;
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle title={title} />,
document.getElementById('example')
);
更多验证器说明如下:
React.createClass({ propTypes: { // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的 optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, // 可以被渲染的对象 numbers, strings, elements 或 array optionalNode: React.PropTypes.node, // React 元素 optionalElement: React.PropTypes.element, // 用 JS 的 instanceof 操作符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message), // 用 enum 来限制 prop 只接受指定的值。 optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // 可以是多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // 特定 shape 参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // 任意类型加上 `isRequired` 来使 prop 不可空。 requiredFunc: React.PropTypes.func.isRequired,