ReactNative入门-React基础
本节包含内容有
React背景及特点
创建React应用
开始第一个简单程序 - 运行Hello World
JSX语法入门
组件
Props
state
组件的生命周期
React背景及特点
-
React背景介绍
在Web应用开发的早期,构建Web应用的唯一方式就是向服务器发送请求,然后服务器响应请求并返回一个完整的页面。从开发角度上讲这种方式非常简单,但是这种开发方式会造成很不好的用户体验,用户的很多行为都需要向服务器请求,等待服务器的反应。因此,开发者开始开发各种类库,使用JavaScript在浏览器端渲染应用。
React起源于Facebook公司,期初用于Instagram网站开发。React是一个用于构建用户界面的JavaScript库,不是一个MVC框架,提出了一种新的开发模式和理念,它强调的是“用户界面”。
-
React特点
1.作为UI
React可以作为MVC中的View层进行使用,并且在已有项目中很容易使用React开发新功能。
2.虚拟DOM虚拟DOM是React最重要的特性,实现了优化视图的渲染和刷新。以前没有Ajax技术的时候,Web页面从服务器端整体渲染出HTML,输出到浏览器端进行渲染,同样的,用户的一个改变页面的操作也会刷新整个页面来完成。知道Ajax的出现,实现页面局部刷新,带来的高效和分离让Web开发者们惊叹不已。但随之而来的问题是复杂的用户交互及展现需要通过大量的DOM操作来完成,这让页面的性能以及开发的效率又出现了新的瓶颈。如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标。
时至今日,谈到前端性能优化,减少DOM元素,减少reflow和repaint,编码过程尽量减少DOM的查询等手段是大家耳熟能详的。而页面任何UI的变化都是通过整体刷新来完成的。而React之所以快,是因为它不直接操作DOM,而是引进虚拟DOM的实现来解决这个问题。
3.组件化
虚拟DOM(virtual-dom)不仅带来了简单UI开发逻辑,同时也带来了组件化开发的思想。所谓组件,即封装起来的具有独立功能的UI部件。React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义出呢个组件,然后将小的组件通过组合或者嵌套的方式构成的大的组件,最终完成整体UI的构建。
如果说MVC的思想让你做到视图-数据-控制器的分离。那么组件化的思考方式则是带来了UI功能模块之间的分离。
对于React而言,开发者从功能的角度出发,将UI分成不同的组件,每个组件都独立封装。在React中,你按照界面模块自然划分的方式来组织和编写你的代码。每个组件只关心自己部分的逻辑,彼此独立。React组件应该具有如下特征:可组合、可重用、可维护
4.数据流
React实现了单向的数据流,相对于传统的数据绑定,React更加灵活、便捷。
-
React学习准备
1、前端基础知识:HTML,CSS,JavaScript
2、JSX语法
3、ES6相关知识
4、React中文网站:http://www.css88.com/react/index.html -
React和ReactNative的关系
React用于Web用用开发。ReactNative采用React方式进行移动应用开发。
ReactNative采用React语法,用于进行JavaScript跨终端应用开发,既拥有原生Native的交互体验,又能够保留React自由的开发效率。使用灵活的HTML和CSS布局,使用React语法构建组件,然后同时运行在iOS和Android平台上,“Learn once,write anywhere”
1.创建React应用
使用命令行:
npm install -g create-react-app
create-react-app my-app
在my-app目录下运行npm
cd my-app
npm start
这时候在浏览器中就会显示运行结果,可以在index.js文件下进行修改
整个文件目录是2.运行Hello World
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
// React的最基本方法,用于将模板转换成HTML语言,渲染DOM并插入指定的DOM节点
/*
三个参数
第一个:模板的渲染内容(HTML形式)
第二个: 这段模板需要插入的DOM节点,本程序中id为root的div节点
第三个:渲染后的回调,一般不用
*/
ReactDOM.render(
<h1>Hello World</h1>
document.getElementById('root')
);
registerServiceWorker();
3.JSX入门
JSX不是一门新的语言,是个语法(语法糖)
- JSX必须借助React环境运行
- JSX标签其实就是HTML标签,只不过我们在JavaScript中书写这些标签的时候,不用使用“”括起来
<h1>Hello World</h1> 这就是JSX语法
- 转换:JSX语法能够让我们更直观的看到组件的DOM结构,不能直接在浏览器上运行,最终会转化成JavaScript代码
// JSX语法书写
ReactDOM.render(
<h1>
Hello React
</h1>,
document.getElementById('root')
);
// JavaScript语法书写
ReactDOM.render(
React.createElement("h1", null, "Hello React"),
document.getElementById('root')
);
两种写法的比较,可以看出来JSX的写法结构很清晰,书写也简单。
- 如何在JSX中运行JavaScript代码,使用{表达式}括起来,如下边的写法
var text = "世界"
ReactDOM.render(
<h1>{text}</h1>,
document.getElementById('root')
);
- JSX语法在属性、设置样式和事件绑定等中的应用
4.组件
(1)定义组件
创建一个组件类,用于输出Hello React
var HelloMessage = React.createClass({
render: function () {
// return <h1>Hello React</h1>;
// 如果想动态输出内容这里使用属性
return <h1>{this.props.helloText}</h1>
}
});
ReactDOM.render(
// 在模板中插入<HelloMessage />会自动生成一个实例
<HelloMessage helloText="Hello React"/>,
document.getElementById('root')
);
- React中创建的组件类以大写字母开头,驼峰命名法
- 在React中使用React.creatClass方法创建一个组件类
- 核心代码:每个组件都必须实现自己的render方法。输出定义好的组件模板。返回值:null,false,组件模板
- 注意:组件类只能包含一个顶层标签
(2)组件的样式
设置组件的样式: 内联样式,对象样式,选择器样式
注意:在React和HTML5中设置样式时的书写格式是由区别的:
1.HTML5以分号;结尾,React以逗号,结尾
2.HTML5中key、value都不加引号,React中属于JavaScript对象,key的名字不能出现分隔符“-”,需要使用驼峰命名法,
如果value为字符串,需要加引号。
3.HTML5中,value如果是数字需要带单位,React中不需要带单位
定义一个组件类,同时使用三种设置组件样式的方式。div使用内联样式:设置背景颜色,边框大小,边框颜色;h1使用对象样式:设置背景颜色,字体颜色;p使用选择器样式:设置字体大小
var ShowMessage = React.createClass({
render: function() {
return (
<div style={{backgroundColor:"yellow", borderWidth: 5, borderColor:"black", borderStyle:"solid"}}>
<h1 style={hStyle}>{this.props.firstRow}</h1>
// 在React中使用选择器样式设置组件样式时,属性名不能使用class,需要使用className替换。同样的还有使用htmlFor替换for
<p className="pStyle">{this.props.secondRow}</p>
</div>
)
}
});
// 创建设置h1样式对象Name
var hStyle = {
backgroundColor: "green",
color: "red"
}
ReactDOM.render(
<ShowMessage firstRow="你好" secondRow="小明"/>,
document.getElementById('root')
);
这里p使用的是选择样式,将样式写在index.css中,在使用的过程中进行导入
import './index.css';
.pStyle {
font-size: 20px;
}
在React中使用选择器样式设置组件样式时,属性名不能使用class,需要使用className替换。同样的还有使用htmlFor替换for
(3)复合组件
复合组件 也称为组合组件,创建多个组件合成一个组件。定义一个组件的WebShow。功能:输出网站的名字和网址,网址是一个可以点击的链接。
分析:定义一个组件WebName负责输出网站名字,定义组件WebLink显示网站的网址,并且可以点击
// 定义WebName组件
var WebName = React.createClass({
render: function() {
return (
<h1>{this.props.webName}</h1>
)
}
});
// 定义WebLink组件
var WebLink = React.createClass({
render: function() {
return (
<a href={this.props.webLink}>{this.props.webLink}</a>
)
}
});
// 组合组件WebShow
var WebShow = React.createClass({
render: function() {
return (
<div>
<WebName webName={this.props.webName}/>
<WebLink webLink={this.props.webLink}/>
</div>
)
}
});
ReactDOM.render(
<WebShow webName="新浪" webLink="http://www.sina.com.cn"/>,
document.getElementById('root')
);
5.props
props是组件自身的属性,一般用于嵌套的内外层组件中,负责传递数据(通常是由父层向子层组件传递)
注意:props对象中的属性与组件的属性一一对应,不要直接直接去修改props中属性的值
...this.props
这个是props提供的语法糖,可以将父组件中的全部属性都复制给子组件
下边定义一个Link组件,Link组件只包含一个<a>
,我们不给<a>
设置任何属性,所有属性全部从父组件复制得到
var Link = React.createClass({
render: function () {
return <a {...this.props}>{this.props.name}</a>
}
});
ReactDOM.render(
<Link href="http://www.baidu.com" name="百度" />,
document.getElementById("root")
)
this.props.children
children组件是一个例外,不是跟组件的属性对应的,它表示组件的所有子节点
下边展示一种列表,在HTML5中有一种标签:<ul> <ol> <li>
。定义一个列表组件,列表项中显示的内容,以及列表项的数量都由外部决定。
var ListComponent = React.createClass({
render: function () {
return (
<ul>
{
// 列表项数量不确定,在创建模板时才能确定,利用this.props.children从父组件获取需要展示的列表项内容
// 获取到列表项内容后,需要遍历children,逐行进行设置
// 使用React.Children.map方法 返回值:数组对象,这里数组中的元素是<li>
React.Children.map(this.props.children, function (child) {
// child是遍历得到的父组件的子节点
return <li>{child}</li>
})
}
</ul>
);
}
});
ReactDOM.render(
(
<ListComponent>
<h1>百度文库</h1>
<a href="http://www.baidu.com">http://www.baidu.com</a>
<h1>百度文库</h1>
<a href="http://www.baidu.com">http://www.baidu.com</a>
<h2>百度文库</h2>
</ListComponent>
),
document.getElementById("root")
);
属性验证
用来验证外部设置的值是否符合组件对属性类型的要求,也是组件类的属性。用来验证组件实例的属性是否符合要求
var ShowTitle = React.createClass({
// 属性验证
propTypes: {
// title 必须为字符串
title: React.PropTypes.string.isRequired
},
render: function () {
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
// 这里如果传入title=1234,运行就会出错,因为属性验证要求组件传入的属性时字符串类型的
<ShowTitle title="1234"/>,
document.getElementById("root")
);
设置组件属性的默认值
通过实现组件的getDefaultProps方法,对属性设置默认值
var ShowTitle = React.createClass({
getDefaultProps: function () {
return {
title: "小明"
}
},
render: function () {
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
// 这里虽然没有传入属性值,但是属性设置了默认值,因此渲染结果是显示出“小明”字样
<ShowTitle />,
document.getElementById("root")
);
6.state
事件处理
定义一个组件,组件中包含一个button,给button绑定onClick事件
var MyButton = React.createClass({
// React中的事件名称,首字母小写,驼峰命名法
handleClick: function () {
alert("点击按钮触发的效果")
},
render: function () {
return <button onClick={this.handleClick}>{this.props.buttonTitle}</button>
}
});
ReactDOM.render(
<MyButton buttonTitle="按钮" />,
document.getElementById("root")
);
state状态
state和props一样,都是组件自身的属性,通过调用this.state
下边创建一个CheckButton组件,包含一个checkbox类型的<input>,复选框在选中和未选中两种状态下会显示不同的文字,即根据状态渲染
var CheckButton = React.createClass({
// 定义初始状态
getInitialState: function () {
return {
// 在这个对象中设置的属性,将会存储在state中
isCheck: false
}
},
// 定义事件绑定的方法
handleChange: function () {
// 修改状态值,通过this.state读取设置的状态值
this.setState({
isCheck: !this.state.isCheck
});
},
render: function () {
// 根据状态值,设置显示的文字
// 注意: 在JSX中不能直接使用if, 如果需要条件判断需要在外边写个方法将结果传进来就行,可以使用三目运算符
var text = this.state.isCheck ? "已选中" : "未选中";
return (
// 返回结果只能有一个根节点
<div>
<input type="checkbox" onChange={this.handleChange} />
{text}
</div>
);
}
});
ReactDOM.render(
<CheckButton />,
document.getElementById("root")
);
注意:
当state发生变化时,会调用组件内部的render方法
表单的基本使用
定义一个组件,将用户在输入框内输入的内容进行实时显示。组件在于用户的交互过程中,存在状态的变化,即输入框的值
var Input = React.createClass({
getInitialState: function () {
return {
value: "请输入"
};
},
// 输入框的输入回传进来一个参数event
handeleChange: function (event) {
// 通过event.target.value读取用户输入的值
this.setState({
value: event.target.value
});
},
render: function () {
var value = this.state.value;
return(
<div>
<input type="text" value={value} onChange={this.handeleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(
<Input />,
document.getElementById("root")
);
7.组件的生命周期
生命周期介绍
组件的生命周期可分成三个状态:
- Mounting:组件挂载,已插入真实的DOM
- Updating:组件更新,正在被重新渲染
- Unmounting: 组件移出,已移出真实DOM
组件的生命周期可分成四个阶段:创建、实例化、更新、销毁
每种状态对应的方法:
-
Mounting/组件挂在相关:
- componentWillMount:组件将要挂载。在render方法之前执行,但仅执行一次,即使多次重复渲染该组件,或者改变了组件的state
- componentDidMount:组件已经挂在。在render之后执行,同一个组件重复渲染只执行一次
-
Updating/组件更新相关:
- componentWillReceiveProps(object nextProps):已加载组件收到新的props之前调用,注意组件初始化渲染时不会执行
- shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用。该接口实际是在组件接收到了新的props或者新的state的时候会立即调用。返回一个Bool值。默认情况下是ture,这就是为什么在前文中说只要调用this.setState方法,就会重新渲染。当返回结果为true时会立即调用下边另外两个方法,如果返回false,则不会进行更新。
- componentWillUpdate(object nextProps, object nextState):组件将要更新
- componentDidUpdate(object prevProps, object prevState):组件已经更新
-
Unmounting/组件移除相关:
- componentWillUnmount:在组件要被移除之前的时间点触发,可以利用该方法来执行一些必要的清理组件相关的工作
-
生命周期中与props和state相关:
- getDefaultProps 设置props属性默认值
- getInitialState 设置state属性初始值
生命周期各阶段介绍
- 一、创建阶段流程:
- 只调用getDefaultProps方法
- 二、实例化阶段流程:
- getInitialState
- componentWillMount
- render
- componentDidMount
- 三、更新阶段流程:
- componentWillReceiveProps
- shouldComponentUpdate 如果返回值是false,后三个方法不执行
- componentWillUpdate
- render
- componentDidUpdate
- 四、销毁阶段流程:
- 流程:componentWillUnmount
var Demo = React.createClass({
/*
一、创建阶段
流程:只调用getDefaultProps方法
*/
getDefaultProps: function () {
// 正在创建类的时候被调用,设置this.props的默认值
console.log("getDefaultProps");
return {};
},
/*
二、实例化阶段
流程: getInitialState
componentWillMount
render
componentDidMount
*/
getInitialState: function () {
// 设置this.state的默认值
console.log("getInitialState");
return null;
},
componentWillMount: function () {
// 在render之前调用
console.log("componentWillMount");
},
render: function () {
// 渲染并返回一个虚拟的DOM
console.log("render");
return <div>Hello React</div>
},
componentDidMount: function () {
// 在render之后调用 在该方法中,React会使用render方法返回的虚拟DOM对象创建真实的DOM结构
// 可以在这个方法中读取DOM节点
console.log("componentDidMount");
},
/*
三、更新阶段
流程:componentWillReceiveProps
shouldComponentUpdate 如果返回值是false,后三个方法不执行
componentWillUpdate
render
componentDidUpdate
*/
componentWillReceiveProps: function () {
console.log("componentWillReceiveProps");
},
shouldComponentUpdate: function () {
console.log("shouldComponentUpdate");
return true;
},
componentWillUpdate: function () {
console.log("componentWillUpdate");
},
componentDidUpdate: function () {
console.log("componentDidUpdate");
},
/*
四、销毁阶段
流程:componentWillUnmount
*/
componentWillUnmount: function () {
console.log("componentWillUnmount");
}
});
// 第一次创建并加载组件
ReactDOM.render(
<Demo />,
document.getElementById("root")
);
/*
上边结果返回的是:
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount
*/
// 更新渲染组件
ReactDOM.render(
<Demo />,
document.getElementById("root")
);
/*
更新渲染后的结果:
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
注意如果将shouldComponentUpdate的返回值设置成false,那么该方法以下的步骤将不会再执行
返回结果是:
componentWillReceiveProps
shouldComponentUpdate
*/
// 移出组件
ReactDOM.unmountComponentAtNode(document.getElementById("root"));
/*
移出组件后的结果:
componentWillUnmount
*/