01_HelloWorld
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>01_HelloWorld</title>
</head>
<body>
<!--
1. 相关js库
react.js: React的核心库
react-dom.js: 提供操作DOM的扩展库
babel.min.js: 解析JSX语法代码转为纯JS语法代码的库
2. 在页面中导入js
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
3. 编码
<div id="example"></div>
<script type="text/babel"> //必须用babel
ReactDOM.render(<h1>Hello, React!</h1>,
document.getElementById('example'));
</script>
-->
<div id="demo"></div>
<script type="text/javascript" src="../js/react.js"></script>
<script type="text/javascript" src="../js/react-dom.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//页面中的真实容器元素
var containDiv = document.getElementById('demo');
//react的虚拟DOM对象
var vDom = <div id="demo">Hello, React!</div>; //不是字符串, 不能加引号
//将虚拟DOM对象渲染到页面元素中
ReactDOM.render(vDom, containDiv);
//页面结果: <div id="demo"><div id="demo">Hello, React!</div></div>
</script>
</body>
</html>
02_JSX
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>02_JSX_DEMO</title>
</head>
<body>
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
<hr>
<div id="example1"></div>
<div id="example2"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
功能: 动态展示列表数据
*/
/*
技术点:
1). 使用JSX创建虚拟DOM
2). React能自动遍历显示数组中所有的元素
3). array.map()的使用
*/
var names = ['Tom2', 'Jack2', 'Bob2'];
ReactDOM.render(
<ul>
{
names.map(function (item, index) {
return <li key={index}>{item}</li>;
})
}
</ul>,
document.getElementById('example1')
);
//简化编码(箭头函数)
ReactDOM.render(
<ul>{names.map((item, index)=><li key={index}>{item}</li>)}</ul>,
document.getElementById('example2')
);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>02_JSX</title>
</head>
<body>
<!--
1. 虚拟DOM
1). React提供了一些API来创建一种 `特别` 的一般js对象
* var element = React.createElement('h1', {id:'myTitle'}, 'hello');
* 上面创建的就是一个简单的虚拟DOM对象
2). 虚拟DOM对象最终都会被React转换为真实的DOM
3). 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
2. JSX
1). 全称: JavaScript XML
2). react定义的一种类似于XML的JS扩展语法: XML+JS
3). 作用: 用来创建react虚拟DOM(元素)对象
* var ele = <h1>Hello JSX!</h1>;
* 注意1: 它不是字符串, 也不是HTML/XML标签
* 注意2: 它最终产生的就是一个JS对象
4). 标签名任意: HTML标签或其它标签
5). 标签属性任意: HTML标签属性或其它
6). 基本语法规则
* 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
* 遇到以 { 开头的代码,以JS的语法解析: 标签中的js代码必须用{}包含
7). babel.min.js的作用
* 浏览器的js引擎是不能直接解析JSX语法代码的, 需要babel转译为纯JS的代码才能运行
* 只要用了JSX,都要加上type="text/babel", 声明需要babel来处理
3. 渲染虚拟DOM(元素)
1). 语法: ReactDOM.render(virtualDOM, containerDOM) :
2). 作用: 将虚拟DOM元素渲染到真实容器DOM中显示
3). 参数说明
* 参数一: 纯js或jsx创建的虚拟dom对象
* 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
4. 创建虚拟DOM的2种方式:
1). 纯JS(一般不用):
React.createElement('h1', {id:'myTitle'}, title)
2). JSX:
<h1 id='myTitle'>{title}</h1>
-->
<div id="example1"></div>
<div id="example2"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//初始化动态数据
var title = 'I Love you!';
var myName = 'xfzhang';
//创建虚拟dom : JSX
var vDOM = <h1 id="myTitle" name={myName}>{title}</h1>;
//将虚拟dom渲染中页面元素中
ReactDOM.render(vDOM, document.getElementById('example1'));
</script>
<script type="text/javascript">
var title = 'You Love me!';
var myName = 'zhiyong';
//创建虚拟dom : 纯JS(一般不用)
var vDOM2 = React.createElement('h1', {id: 'myTitle2', name: myName.toUpperCase()}, title.toUpperCase());
//将虚拟dom渲染中页面元素中
ReactDOM.render(vDOM2, document.getElementById('example2'));
</script>
</body>
</html>
03_component_basic
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>03_component_basic</title>
</head>
<body>
<div id="example1"></div>
<div id="example2"></div>
<div id="example3"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 自定义组件(Component) :
1). 定义组件
//方式1: 工厂(无状态)函数(最简洁, 推荐使用)
function MyComponent1() {
return <h1>自定义组件标题11111</h1>
}
//方式2: ES6类语法(复杂组件, 推荐使用)
class MyComponent3 extends React.Component {
render () {
return <h1>自定义组件标题33333</h1>
}
}
//方式3: ES5老语法(不推荐使用了)
var MyComponent2 = React.createClass({
render () {
return <h1>自定义组件标题22222</h1>
}
})
2). 渲染组件标签
ReactDOM.render(<MyComponent/>, document.getElementById('example'));
2. 注意:
1). 返回的组件类必须首字母大写
2). 虚拟DOM元素必须只有一个根元素
3). 虚拟DOM元素必须有结束标签
3. ReactDOM.render()渲染组件标签的基本流程
1). React内部会创建组件实例对象
2). 得到包含的虚拟DOM并解析为真实DOM
3). 插入到指定的页面元素内部
*/
//1. 定义组件
//方式1: 工厂(无状态)函数(简单组件, 推荐使用)
function MyComponent1() {
return <h1>工厂(无状态)函数--->自定义组件标题11111</h1>;
}
//方式2: ES6类语法(复杂组件, 推荐使用)
class MyComponent2 extends React.Component {
render() {
console.log(this, this instanceof MyComponent3);
return <h1>ES6类语法--->自定义组件标题22222</h1>;
}
}
//方式3: ES5老语法(不推荐使用了)
var MyComponent3 = React.createClass({
render() {
return <h1>ES5老语法--->自定义组件标题3333</h1>;
}
});
console.log(typeof MyComponent3);
/************************************************************************/
//2. 渲染组件标签
ReactDOM.render(<MyComponent1/>, document.getElementById('example1'));
ReactDOM.render(<MyComponent2/>, document.getElementById('example2'));
ReactDOM.render(<MyComponent3/>, document.getElementById('example3'));
</script>
</body>
</html>
04_component_props
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>04_component_props</title>
</head>
<body>
<ul>
<li>姓名: 张三</li>
<li>性别: 女</li>
<li>年龄: 23</li>
</ul>
<hr>
<div id="example"></div>
<div id="example2"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
组件实对象3大属性之一: props属性
1. 每个组件对象都会有props(properties的简写)属性
2. 组件标签的所有属性都保存在props中
3. 内部读取某个属性值: this.props.propertyName
4. 作用: 通过标签属性从组件外向组件内传递数据(只读)
5. 对props中的属性值进行类型限制和必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
6. 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
7. 默认属性值
Person.defaultProps = {
name: 'Mary'
};
8. 组件类的构造函数
constructor (props) {
super(props);
console.log(props); // 查看所有属性
}
问题: 为什么要设计对prop会进行约束的语法?
*/
/*
需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
1). 如果性别没有指定, 默认为男
2). 如果年龄没有指定, 默认为18
*/
class Person extends React.Component {
constructor(props) {
super(props);
console.log(props); //查看所有属性
}
render() {
return (
<ul>
<li>姓名: {this.props.name}</li>
<li>性别: {this.props.sex}</li>
<li>年龄: {this.props.age}</li>
</ul>
);
}
}
Person.propTypes = {
name: React.PropTypes.string.isRequired,
sex: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
};
Person.defaultProps = {
sex: '男',
age: 18
};
/************************************************************************/
//初始化数据
let person = {name: 'qicaiyun', sex: '女', age: 3};
// person = { name: 'qicaiyun', sex: '女', age: "3" }; // 会抛出警告age不是number类型的
//根据数据动态渲染组件标签
/*ReactDOM.render(<Person name={person.name} age={person.age} sex={person.sex}/>,
document.getElementById('example'));*/
ReactDOM.render(<Person {...person}/>,
document.getElementById('example'));
const person2 = {name: 'kobe', sex: '女'};
ReactDOM.render(<Person {...person2}/>, document.getElementById('example2'));
</script>
</body>
</html>
05_components_composing
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>05_components_composing</title>
</head>
<body>
<div>
<h2>Welcome A!</h2>
<h2>Welcome B!</h2>
<h2>Welcome C!</h2>
</div>
<hr>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 拆分组件: 拆分界面, 抽取组件
* 单个标题组件: Welcome
* 应用组件: App
2. 分析确定传递数据和数据类型
* Welcome: props.name string
* App: props.names array
*/
//定义内部标题组件
class Welcome extends React.Component {
render() {
return <h2>Welcome {this.props.name}!</h2>;
}
}
Welcome.propTypes = {
name: React.PropTypes.string.isRequired
};
//定义外部应用组件
class App extends React.Component {
render() {
return (
<div>
{
this.props.names.map(
(name, index) => <Welcome name={name} key={index}/>
)
}
</div>
);
}
}
App.propTypes = {
names: React.PropTypes.array.isRequired
};
/**********************************************************/
var names = ['Tom', 'Jack', "Bob"];
ReactDOM.render(<App names={names}/>, document.getElementById('example'));
</script>
</body>
</html>
06_component_refs_event
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>07_component_refs</title>
</head>
<body>
<input type="text">
<button>提示输入数据</button>
<input type="text" placeholder="失去焦点提示数据">
<hr>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 组件实例对象的3大属性之二: refs属性
1). 组件内的标签都可以定义ref属性来标识自己
2). 在组件中可以通过this.refs.refName来得到对应的真实DOM对象
3). 作用: 用于操作指定的ref属性的dom元素对象(表单标签居多)
* <input ref='username' />
* this.refs.username //返回input对象
2. 事件处理
1). 通过onXxx属性指定组件的事件处理函数(注意大小写)
* React使用的是自定义(合成)事件, 而不是使用的DOM事件
* React中的事件是通过委托方式处理的(委托给组件最外层的元素)
2). 通过event.target得到发生事件的DOM元素对象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target //返回input对象
}
3. 强烈注意
1). 组件内置的方法中的this为组件对象
2). 在组件中自定义的方法中的this为null
* 强制绑定this
* 箭头函数(ES6模块化编码时才能使用)
4. 问题: 如何给一个函数强制指定内部的this?
*/
/*
需求: 自定义组件, 功能说明如下:
1. 界面如果页面所示
2. 点击按钮, 提示第一个输入框中的值
3. 当第2个输入框失去焦点时, 提示这个输入框中的值
*/
class RefsTest extends React.Component {
constructor (props) {
super(props);
this.showMsg = this.showMsg.bind(this); // 强制给showMsg()绑定this(组件对象)
this.handleBlur = this.handleBlur.bind(this);
}
showMsg() {
// console.log(this); //this默认是null, 而不组件对象
const input = this.refs.msg;
alert(input.value);
}
handleBlur(event) {
const input = event.target;
alert(input.value);
}
render () {
return (
<div>
<input type="text" ref="msg"/>
<button onClick={this.showMsg}>提示输入数据</button>
<input type="text" placeholder="失去焦点提示数据" onBlur={this.handleBlur}/>
</div>
);
}
}
ReactDOM.render(<RefsTest/>, document.getElementById('example'));
</script>
</body>
</html>
07_component_state
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>07_component_state</title>
</head>
<body>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
组件实例对象3大属性之: state属性
1). 组件被称为"状态机", 通过更新组件的状态值来更新对应的页面显示(重新渲染)
2). 初始化状态:
constructor (props) {
super(props)
this.state = {
stateProp1 : value1,
stateProp2 : value2
}
}
3). 读取某个状态值
this.state.statePropertyName
4). 更新状态---->组件界面更新
this.setState({
stateProp1 : value1,
stateProp2 : value2
})
5). 问题: 请区别一下组件的props和state属性?
*/
/*
需求: 自定义组件, 功能说明如下
1. 显示h2标题, 初始文本为: 你喜欢我
2. 点击标题更新为: 我喜欢你
*/
class LikeMe extends React.Component {
constructor(props) {
super(props)
this.state = {
isLikeMe: false
}
this.switchLikeMe = this.switchLikeMe.bind(this)
}
switchLikeMe() {
let isLikeMe = !this.state.isLikeMe;
this.setState({isLikeMe})
}
render() {
let text = this.state.isLikeMe ? '你喜欢我' : '我喜欢你'
return <h2 onClick={this.switchLikeMe}>{text}</h2>
}
}
ReactDOM.render(<LikeMe/>, document.getElementById('example'))
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>07_state_demo</title>
</head>
<body>
<div>
<h2>Simple TODO List</h2>
<input type="text">
<button>Add #4</button>
<ul>
<li>吃饭</li>
<li>睡觉</li>
<li>打豆豆</li>
</ul>
</div>
<hr>
<div id="example">在此实现页面效果和功能</div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
功能: 组件化实现此功能
1. 界面显示如上所示
2. 输入文本, 点击按钮显示到下面列表的首位, 并清除输入的文本
*/
/*
分解组件:
列表: TodoList
props: todos
应用: App
state: todos, inputTodo
*/
/*
问题: 完善功能
1). 如果没有输入或输入的只是空格, 不添加到列表
2). 如果输入的文本两边有空格, 去掉空格后添加
*/
/*
* 拆分组件:
* 1、添加 todo的组件 AddTodo
* 2、显示todo列表: TodoList
* 3、 应用主组件: App
*
* */
//定义AddTodo组件
class AddTodo extends React.Component{
constructor(props){
super(props);
this.add = this.add.bind(this);
}
add(){
//获取输入的值
let value = this.refs.newTodo.value;
//console.log(typeof value);
//判断输入的内容是否为空格
if(!value.trim()){
return
}
//将输入的值添加到 todoList中
//console.log(value);
this.props.add(value);
this.refs.newTodo.value = '';
}
render(){
return (
<div>
<input ref="newTodo" type="text" />
<button onClick={this.add}>Add #{this.props.length}</button>
</div>
)
}
}
//定义 TodoList 组件
class TodoList extends React.Component{
render(){
let {todoList} = this.props;
return (
<ul>
{
todoList.map(function (item, index) {
return <li key={index}>{item}</li>
})
}
</ul>
)
}
}
class App extends React.Component{
constructor(props){
super(props);
this.state = {
todoList : ['吃饭', '睡觉', '打豆豆', '学习']
};
this.add = this.add.bind(this);
}
add(newTodo){
console.log(newTodo);
let todoList = this.state.todoList;
todoList.unshift(newTodo);
this.setState({todoList})
}
render(){
let {todoList} = this.state;
return (
<div>
<h2>Simple TODO List</h2>
<AddTodo add={this.add} length={this.state.todoList.length}/>
<TodoList todoList={todoList}/>
</div>
)
}
}
//渲染组件
ReactDOM.render(<App />, document.getElementById('example'));
</script>
</body>
</html>
08_component_controlled
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>09_form</title>
</head>
<body>
<input type="text" value="qicaiyun">
<p>qicaiyun</p>
<hr>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
受控组件
1. React是一个单向数据流
2. 但可以自定义双向数据流组件(受控组件)
*/
/*
功能: 自定义组件, 功能如下
1. 界面如页面所示
2. 初始数据显示为qicaiyun
3. 输入数据时, 下面的数据同步变化
*/
class TwoWay extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: 'qicaiyun'
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
let msg = event.target.value
this.setState({msg})
}
render() {
return (
<div>
<input type="text" value={this.state.msg} onChange={this.handleChange}/>
<p>{this.state.msg}</p>
</div>
)
}
}
ReactDOM.render(<TwoWay/>, document.getElementById('example'))
</script>
</body>
</html>
09_component_lifecycle
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>10_ComponentLife</title>
</head>
<body>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 组件的三个生命周期状态:
* Mount:插入真实 DOM
* Update:被重新渲染
* Unmount:被移出真实 DOM
2. React 为每个状态都提供了两种勾子(hook)函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用
* componentWillMount()
* componentDidMount() : 已插入真实DOM, 在render之后才会执行
* componentWillUpdate(object nextProps, object nextState)
* componentDidUpdate(object prevProps, object prevState)
* componentWillUnmount()
3. 生命周期流程:
1). 第一次初始化渲染显示: render()
* constructor(): 创建对象初始化state
* componentWillMount() : 将要插入回调
* render() : 用于插入虚拟DOM回调
* componentDidMount() : 已经插入回调
2). 每次更新state: this.setSate()
* componentWillUpdate() : 将要更新回调
* render() : 更新(重新渲染)
* componentDidUpdate() : 已经更新回调
3). 删除组件
* ReactDOM.unmountComponentAtNode(document.getElementById('example')) : 移除组件
* componentWillUnmount() : 组件将要被移除回调
4.注意:
* 一般会在componentDidMount()中: 开启监听, 发送ajax请求
* 可以在componentWillUnmount()做一些收尾工作: 停止监听
* 生命周期还有一个方法(后面需要时讲): componentWillReceiveProps
*/
class LifeCycle extends React.Component {
constructor(props) {
super(props);
console.log('constructor(): 创建组件对象');
this.state = {
date: new Date().toLocaleString()
};
}
componentWillMount() {
console.log('componentWillMount(): 将要初始挂载');
}
componentDidMount() {
console.log('componentDidMount(): 已经初始挂载');
this.intervalId = setInterval(
() => {
this.setState({date: new Date().toLocaleString()});
},
1000
);
}
componentWillUpdate() {
console.log('componentWillUpdate(): 将要进行state更新');
}
componentDidUpdate() {
console.log('componentDidUpdate(): 已经更新');
}
componentWillUnmount() {
console.log('componentWillUnmount(): 将要被移除');
clearInterval(this.intervalId);
}
removeComp() {
ReactDOM.unmountComponentAtNode(document.getElementById('example'));
}
render() {
console.log('render(): 渲染内部虚拟DOM');
return (
<div>
<h2>{this.props.name}, 当前时间: {this.state.date}</h2>
<button onClick={this.removeComp}>移除组件</button>
</div>
);
}
}
ReactDOM.render(<LifeCycle name="JACK"/>, document.getElementById('example'));
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>10_ComponentLife</title>
</head>
<body>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
自定义组件:
功能描述: 让指定的文本做显示/隐藏的动画
*/
class AnimateMsg extends React.Component {
constructor(props) {
super(props)
this.state = {
opacity: 1.0
}
}
componentDidMount() {
this.intervalId = setInterval(function () {
var opacity = this.state.opacity;
opacity -= 0.05;
if (opacity < 0.05) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
}
componentWillUnmount() {
clearInterval(this.intervalId)
}
render () {
return (
<p style={{opacity: this.state.opacity}}>{this.props.msg}</p>
);
}
}
AnimateMsg.propTypes = {
msg: React.PropTypes.string.isRequired,
}
ReactDOM.render(<AnimateMsg msg="www.qicaiyun.com"/>, document.getElementById('example'));
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>04_component</title>
</head>
<body>
<div id="example"></div>
<br>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
验证:
虚拟DOM+DOM Diff算法: 最小化页面重绘
*/
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date()
};
}
componentDidMount () {
setInterval(() => {
this.setState({
date: new Date()
})
}, 1000)
}
render () {
console.log('render()')
return (
<p>
Hello, <input type="text" placeholder="Your name here"/>!
It is {this.state.date.toTimeString()}
</p>
);
}
}
ReactDOM.render(
<HelloWorld/>,
document.getElementById('example')
);
</script>
</body>
</html>
10_ajax
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>11_ajax</title>
</head>
<body>
<div id="example"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
<script src="//cdn.bootcss.com/fetch/2.0.1/fetch.min.js"></script>
<script type="text/babel">
/*
1. React没有ajax模块
* 集成其它的js库(如jQuery/fetch/axios), 发送ajax请求
2. 使用axios
* https://github.com/mzabriskie/axios
3. 使用fetch:
* https://github.github.io/fetch/
* https://segmentfault.com/a/1190000003810652
4. 测试url:
* https://api.github.com/users/octocat/gists
*/
class UserGist extends React.Component {
constructor(props) {
super(props);
this.state = {
lastGistUrl: null
};
}
componentDidMount() {
const url = `https://api.github.com/users/${this.props.name}/gists`
axios.get(url)
.then((response) => {
console.log(response.data)
var data = response.data;
var lastGist = data[0];
this.setState({
lastGistUrl: lastGist.html_url
});
})
.catch((error) => {
console.log(error.response.data);
});
/*fetch(url).then(
(response) => {
response.json().then((result) => {
console.log(result);
var lastGist = result[0];
this.setState({
lastGistUrl: lastGist.html_url
});
})
},
(error) => {
console.log(error);
}
);*/
}
render() {
if(this.state.lastGistUrl===null) {
return <h2>loading...</h2>
} else {
return (
<div>
{this.props.name}'s last gist is <a href={this.state.lastGistUrl}>here</a>
</div>
);
}
}
}
var name = 'octocat'
ReactDOM.render(<UserGist name={name}/>, document.getElementById('example'));
</script>
</body>
</html>
11_react-server
React服务器端渲染入门
- 理解
- 当服务器端接收到请求时, 在服务器端基于React动态渲染页面, 并返回给浏览器显示
- 相对于浏览器端渲染的好处?
- 服务器端和客户端可以共享某些代码,避免重复定义。
- 首次加载页面的速度加快
- 便于SEO优化。服务器端渲染可以让搜索引擎更容易读取页面的meta信息以及其他SEO相关信息
- 相对于浏览器端渲染的不好?
- 对服务器的压力增大
- 要求服务器使用基于node搭建
- 简单编码实现服务器端渲染
- 应用文件结构
react-node |-- src |-- App.js-----------------主组件js |-- server.js--------------启动服务器监听, 处理请求的js |-- index.js---------入口js |-- .babelrc---------babel配置文件 |-- package.json-----应用包信息文件
- 编码
- package.json
{ "name": "react-node", "version": "1.0.0", "scripts": { "start": "node index" }, "devDependencies": { "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "babel-register": "^6.8.0" }, "dependencies": { "react": "^15.3.1", "react-dom": "^15.3.1" } }
- .babelrc
{ "presets": ["react", "es2015"] }
- App.js
import React, {Component} from 'react' class App extends Component { render() { return ( <div>测试React服务器</div> ) } } export default App
- server.js
import React from 'react'; import { renderToString } from 'react-dom/server'; var http = require('http'); import App from './App'; //创建服务器对象, 并启动监听 http.createServer(function (request, response) { //向浏览器端写头信息 response.writeHead(200, {'Content-Type': 'text/html'}); //渲染组件成标签结构字符串 const appHTML = renderToString(<App />); //向浏览器返回结果 response.end(appHTML); }).listen(8888); // 终端打印提示信息 console.log('Server running at http://127.0.0.1:8888/');
- index.js
require('babel-register'); require('./src/server.js');
- package.json
- 启动服务器运行:
- 命令: npm start
- 访问: http://127.0.0.1:8888
- 应用文件结构
12_key
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Lists and Keys</title>
</head>
<body>
<div id="root"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
为什么列表的key尽量不要用index
http://jsbin.com/wohima/edit?js,output
http://taobaofed.org/blog/2016/08/24/react-key/?utm_source=tuicool&utm_medium=referral
简单来说: 当数组中的数据发生变化时: React 比较更新前后的元素 key 值,
如果相同则更新,如果不同则销毁之前的,重新创建一个元素
*/
function ListItem({id, name, age}) {
return <li>{id}--{name}--{age}---<input type="text"/></li>;
}
class PersonList extends React.Component {
constructor(props) {
super(props);
this.state = {
persons: [
{id: 1, name: 'Tom', age: 12},
{id: 2, name: 'Jack', age: 13}
]
};
this.update = this.update.bind(this);
}
update() {
let persons = this.state.persons;
persons.unshift({id: 3, name: 'Bob', age: 14})
this.setState({persons})
}
render() {
const persons = this.state.persons;
const listItems = persons.map((person, index) =>
<ListItem key={person.id} {...person}/>
);
const listItems2 = persons.map((person, index) =>
<ListItem key={index} {...person}/>
);
return (
<div>
<h2>使用id作为key</h2>
<ul>
{listItems}
</ul>
<h2>使用index作为key</h2>
<ul>
{listItems2}
</ul>
<button onClick={this.update}>首位添加一个人</button>
</div>
);
}
}
ReactDOM.render(
<PersonList/>,
document.getElementById('root')
);
</script>
</body>
</html>