react课程概要
什么是React
开发背景
facebook推出的,需要解决的问题
构建数据不断变化的大型应用
数据变化-->大量dom操作
-->逻辑变化
简单
声明式
React的核心是组建,组建的设计目的是提高代码复用率,降低测试难度和代码复杂度
提高代码复用率:组建将数据和逻辑封装,类似面向对象中的类。
降低测试难度:组建搞内聚低耦合,很容易对单个组建进行测试。
降低代码的复杂度:直观的语法,提高代码的可阅读性。
React Native 构件移动端应用
React开发环境搭建
下载Facebook官方的基础代码
https://github.com/facebook/react/releases
常用的编辑器及插件的配置
CodeKit、Sublime Text 2/3、、、
推荐Sublime Text 3
插件:Emmet、HTML-CSS-JS Prettify,Spacegray模板
环境:nodejs
Emmet语法介绍
子代: >
div>ul>li
兄弟: +
div+p+bq
父代: ^
div+div>p>span+em^bq
重复: *
ul>li*5
成组: ()
(div>dl>(dt+dd)*3)+footer>p
id : #
div#header+div.page
class:.
属性: []
div[title="Hello" colspan="3"]
demo
```
(div+p#test1>span.test2.test3)*5+p[name="hello"]>div.test4^a*5
```
编写第一个React程序
React程序结构
HTML+CSS+(JS+JSX)
html:5
修改代码
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello World</p>
}
});
React.render(<Hello></Hello>,document.body);
</script>
</body>
</html>
#注意
元素名字首字母必须大写,否则会jsx当作html自带元素
查看改动效果
用浏览器打开即可
#最新版没有jsx?
jsx语法及特点介绍 - 课程概要
什么是jsx
jsx的发展历程
JSX = JavaScript XML
此JSX非彼JSX
基于ECMAScript的一种新特性
一种定义带属性树结构的语法
JSX不是XML或HTML 也不是一种限制
使用react.js不必须使用jsx
优点
类XML语法,容易接受
增强JS语义
结构清晰
抽象程度高(屏蔽掉所有的手动DOM操作)core
代码模块化
如何使用jsx
jsx语法
本质上是js,但是可以直接写html标签
首字母大小写
嵌套
求值表达式(js本身的特性)
驼峰命名
html-->htmlFor和class-->className
注释
// 或/**/
css
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello World</p>
}
});
React.render(<Hello></Hello>,document.body);
var style ={
font-color:'red',
border:1px
}
<div style={style}> //嵌套Hello嵌套到了一个div中
<Hello>
</Hello>
</div>
嵌套
条件判断的四种写法
1 三元表达式
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello {this.props.name ? this.props.name : "World"}</p>
}
});
2 直接使用变量
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
getName: function(){
if(this.props.name)
return this.props.name
else
return "world";
}
render: function(){
var name = this.getName();
return <p>Hello {name}</p>
}
});
3 直接使用函数调用
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
getName: function(){
if(this.props.name)
return this.props.name
else
return "world";
}
render: function(){
return <p>Hello {this.getName()}</p>
}
});
4 或运算符
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello {this.props.name || "World"}</p>
}
});
万能的函数表达式
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello {
(function(obj){
if(obj.props.name)
return obj.props.name
else
return "World"
})(this)
}</p>
}
});
jsx语法实例
非dom属性介绍
为什么要有非DOM属性
dangerouslySetInnerHTML、ref、key
dangerouslySetInnerHTML:在JSX中直接插入HTML代码
ref:父组建引用子组建
key:提高渲染性能
react diff算法流程图
key标识每个节点
启示:类似的节点写成一个的组件
使用类似列表展示元素时元素尽量加上唯一的key,不同组件之间的key可以一样
如何使用非DOM属性
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
render: function(){
return <p>Hello World</p>
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var rawHTML = {
__html: "<h1>I'm inner HTML</h1>"
};
React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>/*<div>这里不能有文字?</div>*/,document.body);
</script>
如何使用ref
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
render: function(){
return <p ref="childp">Hello World</p>
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var rawHTML = {
__html: "<h1>I'm inner HTML</h1>"
};
React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>/*<div>这里不能有文字?</div>*/,document.body);
</script>
key
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
//this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
render: function(){
return <ul>
<li key="1">1</li> //注意key="1",需要双引号
<li key="2">2</li>
<li key="3">3</li>
</ul>
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var rawHTML = {
__html: "<h1>I'm inner HTML</h1>"
};
React.render(<div style={style}><Hello></Hello></div>,document.body);
</script>
jsx解释器架构介绍
阅读源代码
从执行顺序入手
适当忽略细节
重视烂笔头
反复阅读
理解解释器架构
组件生命周期详解
什么是生命周期
组件的生命周期
组件本质上是状态机,输入确定,输出一定确定。
状态发生转换时会出发不同的钩子函数,从而让开发者有机会做出响应
可以用事件的思路来理解状态
不同生命周期内可以自定义的函数
初始化
钩子函数
getDefaultProps //获取实例的默认属性组件的第一个实例装载之后才调用,第二个实例开始并不调用
getInitialState //获取实例的初始化状态
componentWillMount //组件即将被渲染到页面上
render //生成虚拟dom节点,由react渲染成真正的DOM节点
componentDidMount //组件真正装载之后调用,组件已经被渲染到了页面
运行中
componentWillReceivProps //组件可能要接收到属性
shouldComponentUpdate //组件接收到新属性,返回false则不会调用render函数(diff 算法)
componentWillUpdate //在render调用之前调用
render //组件真正装载之后调用,组件已经被渲染到了页面
componentDidUpdate //react渲染成真正的DOM节点之后调用
销毁
componentWillUnmount //销毁操作之前调用
初始化阶段介绍
getDefaultProps
只调用一次,实例之间共享引用
getInitialState
初始化每个实例特有的状态
componentWillMount
render之前最后一次修改状态的机会
render
只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidMount
成功render并渲染完成真实DOM之后触发,可以修改DOM
demo
调用顺序:
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
//this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
getDefaultProps:function(){
console.log('getDefaultProps,1');
return null;
},
getInitialState: function(){
console.log('getInitialState,2');
return null;
},
componentWillMount: function(){
console.log('componentWillMount,3');
},
render: function(){
console.log('render,4');
return <ul>
<li key="1">1</li>
<li key="2">2</li>
<li key="3">3</li>
</ul>
},
componentDidMount:function(){
console.log('componentDidMount,5');
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var rawHTML = {
__html: "<h1>I'm inner HTML</h1>"
};
React.render(<div style={style}><Hello></Hello></div>,document.body);
</script>
各函数用法:
<script type="text/jsx">
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
//this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
getDefaultProps:function(){
console.log('getDefaultProps,1');
return {name:'Ray'};
},
getInitialState: function(){
console.log('getInitialState,2');
return {count:count++,
ready:false
};
},
componentWillMount: function(){
console.log('componentWillMount,3');
this.setState({ready:true});
},
render: function(){
console.log('render,4');
return <p>Hello {this.props.name?this.props.name:"World"}<br/>{this.state.ready + " "} {this.state.count}</p>
},
componentDidMount:function(){
console.log('componentDidMount,5');
React.findDOMNode(this).innerText += ' well';
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var count = 0;
React.render(<div style={style}><Hello></Hello><br/><Hello></Hello><br/><Hello></Hello><br/><Hello></Hello><br/><Hello></Hello></div>,document.body);
</script>
运行中阶段介绍
componentWillReceiveProps
父组件修改属性触发,可以修改新属性、修改状态
shouldComponentUpdate
返回false会阻止render调用
componentWillUpdate
不能修改属性和状态
render
只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidUpdate
可以修改DOM
demo
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script src="./jquery-3.1.1.min.js"></script>
<script type="text/jsx">
$(document).ready(
function(){
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
//this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
componentWillReceiveProps:function(newProps){
// to do...
console.log('componentWillReceiveProps,1');
console.log(newProps);
},
shouldComponentUpdate: function(){
console.log('shouldComponentUpdate,2');
return true; //true表示组建需要更新,必须返回一个值,如果返回false,则下面的几个方法不会调用
//这个方法一般不用
},
componentWillUpdate: function(){
// to do...
console.log('componentWillUpdate,3');
//这个方法一般也不用
},
render: function(){
console.log('render,4');
return <p>Hello {this.props.name?this.props.name:"World"}<br/></p>
},
componentDidUpdate:function(){
// to do...
console.log('componentDidUpdate,5');
$(React.findDOMNode(this)).append("suprise!");
}
});
var World = React.createClass({
getInitialState:function(){
return {name:''};
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
return <div>
<Hello name={this.state.name}></Hello>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var count = 0;
React.render(<div style={style}><World></World></div>,document.body);
}
);
</script>
销毁阶段介绍
componentWillUmount
在删除组件之前进行清理操作,比如计时器和事件监听
demo
<script src="./react.js"></script>
<script src="./JSXTransformer.js"></script>
<script src="./jquery-3.1.1.min.js"></script>
<script type="text/jsx">
$(document).ready(
function(){
var Hello = React.createClass({ //注意,首字母必须大写,否则会jsx当作html自带元素
//this.refs.childp.text //不是真正的DOM节点(不能进行操作),而是react展示的DOM
componentWillReceiveProps:function(newProps){
// to do...
console.log('componentWillReceiveProps,1');
console.log(newProps);
},
shouldComponentUpdate: function(){
console.log('shouldComponentUpdate,2');
return true; //true表示组建需要更新,必须返回一个值,如果返回false,则下面的几个方法不会调用
//这个方法一般不用
},
componentWillUpdate: function(){
// to do...
console.log('componentWillUpdate,3');
//这个方法一般也不用
},
render: function(){
console.log('render,4');
return <p>Hello {this.props.name?this.props.name:"World"}<br/></p>
},
componentDidUpdate:function(){
// to do...
console.log('componentDidUpdate,5');
$(React.findDOMNode(this)).append("suprise!");
},
componentWillUnmount:function(){
console.log("BOOOOOOOOOOOOOOOOOOOM!");
}
});
var World = React.createClass({
getInitialState:function(){
return {name:''};
},
handleChange:function(event){
if(event.target.value == '321'){
React.unmountComponentAtNode(document.getElementsByTagName("body")[0]);
return;//没有return会继续调用render
}
//way 2:使用React.unmountComponentAtNode显式调用
this.setState({name:event.target.value});
},
render:function(){
if(this.state.name == '123'){
return <div>123</div>
}
//way 1:在render中直接返回性的div
return <div>
<Hello name={this.state.name}></Hello>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
}
});
var style ={
color:'red',
border:'1px #000 solid'
};
var count = 0;
React.render(<div style={style}><World></World></div>,document.body);
}
);