01_初入react_react学习笔记
文章目录
JSX
1.简介
- 全称: JavaScript XML
- react定义的一种类似于XML的JS扩展语法: XML+JS
作用
-
用来创建react虚拟DOM(元素)对象
a. var ele = <h1>Hello JSX!</h1>
b. 注意1: 它不是字符串, 也不是HTML/XML标签
c. 注意2: 它最终产生的就是一个JS对象
d. 标签名任意: HTML标签或其它标签
e. 标签属性任意: HTML标签属性或其它
基本语法规则
a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含
babel.js的作用
a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
b. 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理
2.创建虚拟DOM
前置
<div id="test1"></div>
<div id="test2"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
1.纯JS(一般不用)
var element = React.createElement(‘h1’, {id:‘myTitle’},‘hello’)
<script type="text/javascript">
// 1. 创建虚拟DOM
/*方式一: 纯JS(一般不用)创建虚拟DOM元素对象*/
const msg = 'I Like You!'
const myId = 'Atguigu'
const vDOM1 = React.createElement('h2', {id: myId}, msg.toUpperCase())//msg转为大写
// 2. 渲染到真实页面
const domContainer = document.getElementById('test1')
// debugger
ReactDOM.render(vDOM1, domContainer)
</script>
2.JSX创建
<h1 id=‘myTitle’>{title}</h1>
<script type="text/babel">
// 1. 创建虚拟DOM
/*方式二: JSX创建虚拟DOM元素对象*/
const vDOM2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>
// debugger
// 2. 渲染到真实页面
ReactDOM.render(vDOM2, document.getElementById('test2'))
</script>
3.debugger
在代码中写debugger可以起到断点作用进行调试
4.真实DOM和虚拟DOM
//虚拟dom
const vDOM1 = React.createElement('h2', {id: myId}, msg)
//真实dom
cponst rDOM1 = document.getElementById('test1')
前者比较轻,后者比较重,一旦修改页面刷新,前者只有重新渲染的时候才刷新
真实dom属性比虚拟dom多
虚拟DOM对象最终都会被React转换为真实的DOM
我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
5. 渲染虚拟DOM(元素)
-
语法: ReactDOM.render(virtualDOM, containerDOM)
-
作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示
-
参数说明
a. 参数一: 纯js或jsx创建的虚拟dom对象
b. 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
exercise:动态展示列表数据(数据数组–>标签数组)
技术点:
1). 使用JSX创建虚拟DOM
2). React能自动遍历显示数组中所有的元素
3). array.map()的使用
<body>
<h2>前端JS框架列表</h2>
<div id="example1"></div>
<div id="example2"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
</body>
<script type="text/babel">
/*
功能: 动态展示列表数据
*/
// 数据的数组
var names = ['jquery', 'zeptoo', 'angular', 'react全家桶', 'vue全家桶']
// 数据的数组-->标签的数组
//方法1
var lis = []
names.forEach((name, index) => lis.push(<li key={index}>{name}</li>))
// 创建虚拟DOM
const ul = <ul>{lis}</ul>
// 渲染虚拟DOM
ReactDOM.render(ul, document.getElementById('example1'))
//方法2
const ul2 = <ul>{
names.map((name, index) => <li key={index}>{name}</li>)
}</ul>
ReactDOM.render(ul2, document.getElementById('example2'))
</script>
js新函数map()
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组
var array1 = [1, 4, 9, 16];
const map1 = array1.map(x => {
if (x == 4) {
return x * 2;
}
return x;
});
这里注意箭头函数有两种格式:
1.只包含一个表达式,这时花括号和return都省略了。
2.包含多条语句,这时花括号和return都不能省略。
js新函数onblur
onblur 事件会在对象失去焦点时发生。
<html>
<head>
<script type="text/javascript">
function upperCase()
{
var x=document.getElementById("fname").value
document.getElementById("fname").value=x.toUpperCase()
}
</script>
</head>
<body>
输入您的姓名:
<input type="text" id="fname" onblur="upperCase()" />
</body>
</html
面向组件编程
1.步骤
<div id="example1"></div>
<div id="example2"></div>
1.定义组件
- 工厂函数组件(简单组件,没有状态的组件)直接调用方法 有state就不能用工厂模式
function MyComponent () {
return <h2>工厂函数组件(简单组件)</h2>
}
- ES6组件(复杂组件)先创建实例,实例调用render方法
class MyComponent2 extends React.Component {
render () {
console.log(this) // MyComponent2的实例对象
return <h2>ES6类组件(复杂组件)</h2>
}
2.渲染组件标签
ReactDOM.render(<MyComponent />, document.getElementById('example1'))
ReactDOM.render(<MyComponent2 />, document.getElementById('example2'))
3.注意
-
组件名必须首字母大写
-
虚拟DOM元素只能有一个根元素
-
虚拟DOM元素必须有结束标签
4.ReactDOM.render()渲染组件标签的基本流程
- React内部会创建组件实例对象/调用组件函数, 得到虚拟DOM对象
- 将虚拟DOM并解析为真实DOM
- 插入到指定的页面元素内部
2.组件三大属性
2.1 state
理解
-
state是组件对象最重要的属性, 值是对象(可以包含多个数据)
-
组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
编码操作
- 初始化状态:
constructor (props) {
super(props)
this.state = {
stateProp1 : value1,
stateProp2 : value2
}
}
- 读取某个状态值
this.state.statePropertyName
- 更新状态---->组件界面更新
this.setState({
stateProp1 : value1,
stateProp2 : value2
})
例子:
<script type="text/babel">
/*
需求: 自定义组件, 功能说明如下
1. 显示h2标题, 初始文本为: 你喜欢我
2. 点击标题更新为: 我喜欢你
*/
class Like extends React.Component{
constructor(props) {
super(props);
//初始化状态
this.state={
isLikeMe:false
}
//将新增方法的this绑定为组件对象
//bind返回一个新函数,因此要将新函数指向handleclick()
this.handleClick = this.handleClick.bind(this)
}
//新增类方法,this默认是undefined
handleClick(){
//读取状态并取反
const isLikeMe = !this.state.isLikeMe
//更新状态
this.setState({isLikeMe:isLikeMe})
}
render(){
//读取状态
const {isLikeMe}=this.state
return <h2 onClick={this.handleClick}>{isLikeMe? '你喜欢我':'我喜欢你'}</h2>
}
}
ReactDOM.render(<Like/>,document.getElementById('example'))
</script>
2.2 props
理解
-
每个组件对象都会有props(properties的简写)属性
-
组件标签的所有属性都保存在props中
-
class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
-
直接在标签上使用style属性时,要写成style={{}}是两个大括号,外层大括号是告知jsx这里是js语法,和真实DOM不同的是,属性值不能是字符串而必须为对象,需要注意的是属性名同样需要驼峰命名法。即margin-top要写成marginTop。
-
this.props.children 不要children作为把对象的属性名。因为this.props.children获取的该标签下的所有子标签。this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。官方建议使用React.Children.map来遍历子节点,而不用担心数据类型
作用
-
通过标签属性从组件外向组件内传递变化的数据
-
注意: 组件内部不要修改props数据
编码操作
- 内部读取某个属性值
this.props.propertyName
- 对props中的属性值进行类型限制和必要性限制(已过时)
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
新版本需要引入包prop-types.js
- 扩展属性: 将对象的所有属性通过props传递
… 的作用
1.打包
function fn(…as){} fn(1,2,3)
as就是数组类型
2.解包
const arr1 = [1,2,3]
const arr2 =[6,…arr1,9] 相当于替换为[6,1,2,3,9]
<Person {...person}/
- 默认属性值
Person.defaultProps = {
name: 'Mary'
}
- 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}
例子
//1.工厂方法
<script type="text/babel">
/*
需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
1). 如果性别没有指定, 默认为男
2). 如果年龄没有指定, 默认为18
*/
//1.定义组件
function Person(props) {
return (
<ul>
<li>姓名:{props.name}</li>
<li>年龄:{props.age}</li>
<li>性别:{props.sex}</li>
</ul>
)
}
//指定属性默认值
Person.defaultProps = {
sex:'男',
age:18
}
//指定属性的类型和必要性
Person.propTypes = {
name:PropTypes.string.isRequired,
sex: PropTypes.string,
age: PropTypes.number
}
//2.渲染组件标签
const p1={
name:"Tom",
age:18,
sex:'女'
}
const p2 = {
name:"Mary"
}
// ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex}/>, document.getElementById('example1'));
ReactDOM.render(<Person {...p1}/>, document.getElementById('example1'));
ReactDOM.render(<Person name={p2.name}/>, document.getElementById('example2'))
</script>
//2.ES6组件
<script type="text/babel">
/*
需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
1). 如果性别没有指定, 默认为男
2). 如果年龄没有指定, 默认为18
*/
//1. 定义组件类
class Person extends React.Component {
render() {
console.log(this)
return (
<ul>
<li>姓名: {this.props.name}</li>
<li>性别: {this.props.sex}</li>
<li>年龄: {this.props.age}</li>
</ul>
)
}
}
// 对标签属性进行限制
Person.propTypes = {
name: PropTypes.string.isRequired,
sex: PropTypes.string,
age: PropTypes.number
}
// 指定属性的默认值
Person.defaultProps = {
sex: '男',
age: 18
}
//2. 渲染组件标签
const person = {
name: 'Tom',
sex: '女',
age: 18
}
ReactDOM.render(<Person {...person}/>, document.getElementById('example1'))
const person2 = {
myName: 'JACK',
age: 17
}
ReactDOM.render(<Person name={person2.myName} age={person2.age}/>,
document.getElementById('example2'))
</script>
2.3 refs与事件处理
理解
- 组件内的标签都可以定义ref属性来标识自己
a. <input type=“text” ref={input => this.msgInput = input}/>,this.msginput就相当于是这个input标签了
b. 回调函数在组件初始化渲染完或卸载时自动调用
-
在组件中可以通过this.msgInput来得到对应的真实DOM元素
-
作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据
事件处理
- 通过onXxx属性指定组件的事件处理函数(注意大小写)
a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
- 通过event.target得到发生事件的DOM元素对象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target //返回input对象
}
编码操作
<script type="text/babel">
/*
需求: 自定义组件, 功能说明如下:
1. 界面如果页面所示
2. 点击按钮, 提示第一个输入框中的值
3. 当第2个输入框失去焦点时, 提示这个输入框中的值
*/
//定义组件
class MyComponent extends React.Component {
constructor(props) {
super(props) // 调用父类(Component)的构造函数
//console.log(this)
// 将自定义的函数强制绑定为组件对象
this.handleClick = this.handleClick.bind(this) // 将返回函数中的this强制绑定为指定的对象, 并没有改变原来的函数中的this
this.handleblur = this.handleblur.bind(this)
}
// 自定义的方法中的this默认为null
handleClick () {
// alert(this) //this默认是null, 而不是组件对象
// 得到绑定在当前组件对象上的input的值
alert(this.msgInput.value)
}
handleBlur (event) {
alert(event.target.value)
}
render () {
return (
<div>
<input type="text" ref={input => this.msgInput = input}/>{' '}
<button onClick={this.handleClick}>提示输入数据</button>{' '}
<input type="text" placeholder="失去焦点提示数据" onBlur={this.handleBlur}/>
</div>
)
}
}
// 渲染组件标签
ReactDOM.render(<MyComponent />, document.getElementById('example'))
</script>
注意
-
组件内置的方法中的this为组件对象
-
在组件类中自定义的方法中this为null
a. 强制绑定this: 通过函数对象的bind()
b. 箭头函数(ES6模块化编码时才能使用)
3. 组件组合
功能界面的组件化编码流程(无比重要)
-
拆分组件: 拆分界面,抽取组件
-
实现静态组件: 使用组件实现静态页面效果
-
实现动态组件
a. 动态显示初始化数据
b. 交互功能(从绑定事件监听开始)
编码操作
<script type="text/babel">
/*
* 问题:数据保存在哪个组件内?
* 看数据是某个组件需要(给它)还是某些组件需要(给共同的父亲)
* 问题2:需要在子组件中改变父组件的状态?
* 子组件中不能直接改变父组件的状态
* 状态在哪个组件,更新状态的行为(方法)就应该定义在哪个组件
* 解决:父组件定义函数,传递给子组件,子组件调用
* */
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
//初始化状态
todos: ['吃饭', '睡觉', 'code'],
//test:['1','2','3']
}
this.addTodo = this.addTodo.bind(this)
}
addTodo(todo){
const {todos} = this.state //相当于 const todos = this.state.todos {}是解构语法方便取值
todos.unshift(todo)
//更新状态
this.setState({todos})
//不能这么写
// this.state.todos.unshift(todo)
//更新状态
//this.setState(this.state) 不会报错,但是这个相当于把原来的state在传给setState()有副作用
//正确的应该是建立新state传进去
//this.setState({this.state.todos})这种是新state但是就只有todos一个属性了,原state里其他属性就没了
//所以要用解构语法(如下),顺序没要求
//this.setState({todos,...this.state})
}
render(){
return(
<div>
<h1>Simple To Do List</h1>
<Add count={this.state.todos.length} addTodo = {this.addTodo}/>
<List todos={this.state.todos}/>
</div>
)
}
}
class Add extends React.Component{
constructor(props) {
super(props);
this.add = this.add.bind(this)
}
add(addTodo){
// 1.读取输入的数据
const todo = this.todoInput.value.trim()
// 2.检查合法性
if(!todo) {
return
}
// 3.添加
this.props.addTodo(todo)
// 4.清除输入
this.todoInput.value = ''
}
render(){
return(
<div>
<input type="text" ref={ myInput => this.todoInput = myInput}/>
<button onClick={this.add}>add #{this.props.count+1}</button>
</div>
)
}
}
class List extends React.Component{
render(){
return(
<ul>
{
this.props.todos.map((value,index)=><li key={index}>{value}</li>)
//或者this.props.todos.map((value,index)=>{return <li key={index}>{value}</li>})
//为什么加了{}就要用return,因为{}默认是一个函数体
}
</ul>
)
}
}
Add.propTypes = {
count:PropTypes.number.isRequired,
addTodo:PropTypes.func.isRequired
}
List.propTypes = {
todos:PropTypes.array.isRequired
}
ReactDOM.render(<App/>, document.getElementById('example'))
</script>
4. 组件收集表单数据
理解
-
问题: 在react应用中, 如何收集表单输入数据
-
包含表单的组件分类
- 受控组件: 表单项输入数据能自动收集成状态 如下面的name 简单一些
- 非受控组件: 需要时才手动读取表单输入框中的数据 如下面的pwd 自动收集,建议用这个
编码操作
需求: 自定义包含表单的组件
1. 输入用户名密码后, 点击登陆提示输入信息
3. 不提交表单
<script type="text/babel">
/*
需求: 自定义包含表单的组件
1. 界面如下所示
2. 输入用户名密码后, 点击登陆提示输入信息
3. 不提交表单
*/
class LoginFrom extends React.Component{
constructor(props) {
super(props);
//初始化状态
this.state = {
pwd:''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSubmit(event){
const name = this.nameInput.value
//或者 const{value} = this,nameInput
const {pwd} = this.state
alert(`准备提交的用户名为:${name},密码为:${pwd}`)
//阻止事件的默认行为(提交)
event.preventDefault()
}
handleChange(event){
//读取输入的值,
const pwd = event.target.value
//更新pwd状态
//或者this.setState({pwd:event.target.value})
this.setState({pwd})
}
//方法1:用ref 受控组件
//方法2:用value和state以及onChange,原生js中onChange是失去焦点调用, 非受控组件
// 这里我们用的是自定义dom事件,是value一改变就会调用
render(){
return(
<form action="/test" onSubmit={this.handleSubmit}>
用户名: <input type="text" ref={input =>this.nameInput = input }/>
密码: <input type="password" value={this.state.pwd} onChange={this.handleChange}/>
<input type="submit" value="登录"/>
</form>
)
}
}
ReactDOM.render(<LoginFrom/>, document.getElementById('example'))
</script>
5.组件生命周期
理解
-
组件对象从创建到死亡它会经历特定的生命周期阶段
-
React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调
-
我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作
生命周期流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4n8vkl6U-1588255706689)(生命周期.png)]
生命周期详述
1) 组件的三个生命周期状态:
Mount:插入真实 DOM
Update:被重新渲染
Unmount:被移出真实 DOM
2)React 为每个状态都提供了勾子(hook)函数
componentWillMount()
componentDidMount()
componentWillUpdate()
componentDidUpdate()
componentWillUnmount()
3)生命周期流程
a.第一次初始化渲染显示: ReactDOM.render() 1次
constructor(): 创建对象初始化state
componentWillMount() : 将要插入回调
render() : 用于插入虚拟DOM回调
componentDidMount() : 已经插入回调
b.每次更新state: this.setSate() n次
componentWillUpdate() : 将要更新回调
render() : 更新(重新渲染)
componentDidUpdate() : 已经更新回调
c.移除组件: ReactDOM.unmountComponentAtNode(containerDom) 1次
componentWillUnmount() : 组件将要被移除回调
重要的勾子
-
render(): 初始化渲染或更新渲染调用
-
componentDidMount(): 开启监听, 发送ajax请求
-
componentWillUnmount(): 做一些收尾工作, 如: 清理定时器
-
componentWillReceiveProps(): 后面需要时讲
编码操作
需求: 自定义组件
1. 让指定的文本做显示/隐藏的渐变动画
2. 切换持续时间为2S
3. 点击按钮从界面中移除组件界面
<script type="text/babel">
/*
需求: 自定义组件
1. 让指定的文本做显示/隐藏的动画
2. 切换时间为2S
3. 点击按钮从界面中移除组件界面
*/
class Fade extends React.Component {
constructor (props) {
super(props)
console.log('constructor(): 创建组件对象')
this.state = {
opacity: 1
}
this.removeComponent = this.removeComponent.bind(this)
}
componentWillMount () {
console.log('componentWillMount(): 初始化将要挂载')
}
componentDidMount () {// 在此方法中启动定时器/绑定监听/发送ajax请求
console.log('componentDidMount(): 初始化已经挂载')
// 保存到当前组件对象中
this.intervalId = setInterval(function () {
console.log('--------')
// 得到当前opacity
let {opacity} = this.state
// 更新opacity
opacity -= 0.1
if(opacity<=0) {
opacity = 1
}
// 更新状态
this.setState({opacity})
}.bind(this), 200)
}
componentWillUpdate () {
console.log('componentWillUpdate(): 将要更新')
}
componentDidUpdate () {
console.log('componentDidUpdate(): 已经更新')
}
componentWillUnmount () {// 清除定时器/解除监听
console.log('componentWillUnmount(): 将要被移除')
clearInterval(this.intervalId)
}
removeComponent () {
ReactDOM.unmountComponentAtNode(document.getElementById('example'))
}
render() {
console.log('render() 渲染组件')
return (
<div>
<h2 style={{opacity:this.state.opacity}}>{this.props.content}</h2>
<button onClick={this.removeComponent}>不活了</button>
</div>
)
}
}
ReactDOM.render(<Fade content="react学不会, 怎么办?"/>, document.getElementById('example'))
</script>
6.虚拟DOM与DOM Diff算法
检测哪些需要更新哪些不需要更新,提高效率
基本原理图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vuhkQNYt-1588255706695)(虚拟DOM与Diff算法.png)]
编码操作
<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"/>!
<span>It is {this.state.date.toTimeString()}</span>
</p>
)
}
}
ReactDOM.render(
<HelloWorld/>,
document.getElementById('example')
)
</script>
React应用
1. React脚手架
理解
- xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
- 包含了所有需要的配置
- 指定好了所有的依赖
- 可以直接安装/编译/运行一个简单效果
-
react提供了一个用于创建react项目的脚手架库: create-react-app
-
项目的整体技术架构为: react + webpack + es6 + eslint
-
使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
创建并进入
npm install -g create-react-app
create-react-app hello-react
cd hello-react
npm start
npm root -g 查看全局下载的根目录
PS:在文件夹地址栏直接cmd可以直接打开此目录的cmd
react脚手架项目结构
-
在文件package.json中
- "dependencies"是开发(编译打包)依赖的环境配置
- “devDependencies"是运行时依赖的环境配置
-
ReactNews
|–node_modules—第三方依赖模块文件夹
|–public
|–index.html-----------------主页面
|–scripts
|– build.js-------------------build**打包引用配置
|– start.js-------------------start**运行引用配置
|–src------------源码文件夹
|–components-----------------react**组件
|–index.js-------------------应用入口js
|–.gitignore------git版本管制忽略的配置
|–package.json----应用包配置文件:
1.标识:1)name version
2.依赖:运行依赖和开发依赖
3.运行/打包: scripts 通过npm run运行
|–README.md-------应用描述说明的readme文件
-
组件后缀名可以是.js/.jsx,一般是.jsx
-
组件文件名小写,组件名首字母大写
-
所有的组件类都要引入:
2. demo1 实现一个评论管理功能
注意,原src文件可能已经改为src-对应的demo名,需要运行时要改回来
React ajax
1. 理解
1.1 前置说明
-
React本身只关注于界面, 并不包含发送ajax请求的代码
-
前端应用需要通过ajax请求与后台进行交互(json数据)
-
react应用中需要集成第三方ajax库(或自己封装)
1.2 常用的ajax请求库
-
jQuery: 比较重, 如果需要另外引入不建议使用
-
axios: 轻量级, 建议使用
a. 封装XmlHttpRequest对象的ajax
b. promise风格
c. 可以用在浏览器端和node服务器端
- fetch: 原生函数, 但老版本浏览器不支持
a. 不再使用XmlHttpRequest对象提交ajax请求
b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js
1.3 要求实现效果
要先引入axios库
需求:
- 界面效果如下
- 根据指定的关键字在github上搜索匹配的最受关注的库
- 显示库名, 点击链接查看库
- 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
2. axios
2.1 文档
https://github.com/axios/axios
2.2 相关API
2.2.1 get请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
2.2.2 post请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
2.3 axios实现
需求:
1. 界面效果如下
2. 根据指定的关键字在github上搜索匹配的最受关注的库
3. 显示库名, 点击链接查看库
4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script type="text/babel">
/*
需求:
1. 界面效果如下
2. 根据指定的关键字在github上搜索匹配的最受关注的库
3. 显示库名, 点击链接查看库
4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
*/
class MostStarRepo extends React.Component {
state = {
repoName: '',
repoUrl: ""
}
componentDidMount() {
const url = `https://api.github.com/search/repositories?q=r&sort=stars`
//使用axios发送异步请求
axios.get(url)
.then(response=>{
const result = response.data
//console.log(result)
//console.log(response)
//得到数据
const{name,html_url} = result.items[0]
//更新状态
this.setState({repoName:name,repoUrl:html_url})
.catch((error)=>{
alert(error.message)
})
})
}
render() {
const {repoName, repoUrl} = this.state
if (!repoName){
return <h2>Loading......</h2>
}else{
return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>
}
}
}
ReactDOM.render(<MostStarRepo searchWord="r"/>, document.getElementById('example'))
</script>
3. Fetch
3.1 文档
-
https://github.github.io/fetch/
-
https://segmentfault.com/a/1190000003810652
3.2 相关API
3.2.1 get请求
fetch(url).then(function(response) {
return response.json()
}).then(function(data) {
console.log(data)
}).catch(function(e) {
console.log(e)
});
3.2.2 post请求
fetch(url, {
method: "POST",
body: JSON.stringify(data),
}).then(function(data) {
console.log(data)
}).catch(function(e) {
console.log(e)
})
3.3 Fetch实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>11_ajax</title>
</head>
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script type="text/babel">
/*
需求:
1. 界面效果如下
2. 根据指定的关键字在github上搜索匹配的最受关注的库
3. 显示库名, 点击链接查看库
4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
*/
class MostStarRepo extends React.Component {
state = {
repoName: '',
repoUrl: ""
}
componentDidMount() {
const url = `https://api.github.com/search/repositories?q=r&sort=stars`
//使用Fetch发送异步请求
fetch(url)
.then(response => {
return response.json()
})
.then(data => {
//得到数据
const {name, html_url} = data.items[0]
//更新状态
this.setState({repoName: name, repoUrl: html_url})
})
}
render() {
const {repoName, repoUrl} = this.state
if (!repoName) {
return <h2>Loading......</h2>
} else {
return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>
}
}
}
ReactDOM.render(<MostStarRepo searchWord="r"/>, document.getElementById('example'))
</script>
</body>
</html>
4.demo2 实现github用户搜索功能
记得下载包axios npm install --save axios
重要技术总结
1. 组件间通信
1.1 方式一: 通过props传递
-
共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
-
通过props可以传递一般数据和函数数据, 只能一层一层传递
-
一般数据–>父组件传递数据给子组件–>子组件读取数据
-
函数数据–>子组件传递数据给父组件–>子组件调用函数
1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
-
工具库: PubSubJS
-
下载: npm install pubsub-js --save
-
使用:
import PubSub from ‘pubsub-js’ //引入
PubSub.subscribe(‘delete’, function(data){ }); //订阅
PubSub.publish(‘delete’, data) //发布消息
实例 根据demo2改编
兄弟组件 爷孙组件之间通信 用这种方式比较好,不用再通过父组件传递
app.jsx 里面没有state等内容,因为孩子传递数据跟他没关系了
import React from 'react'
import Search from './search'
import Main from './main'
export default class App extends React.Component {
render() {
return (
<div id="app">
<div className="container">
<Search />
<Main />
</div>
</div>
)
}
}
search.jsx
1.3 方式三: redux
2. 事件监听理解
2.1原生DOM事件
- 绑定事件监听
a. 事件名(类型): 只有有限的几个, 不能随便写
b. 回调函数
-
触发事件
a. 用户操作界面
b. 事件名(类型)
c. 数据()
2.2 自定义事件(消息机制)
- 绑定事件监听
a. 事件名(类型): 任意
b. 回调函数: 通过形参接收数据, 在函数体处理事件
- 触发事件(编码)
a. 事件名(类型): 与绑定的事件监听的事件名一致
b. 数据: 会自动传递给回调函数
3. ES6常用新语法
-
定义常量/变量: const/let
-
解构赋值: let {a, b} = this.props import {aa} from ‘xxx’
-
对象的简洁表达: {a, b}
-
箭头函数:
a.常用场景
组件的自定义方法: xxx = () => {}
参数匿名函数
b.优点:
简洁
没有自己的this,使用引用this查找的是外部this
-
扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)
-
类: class/extends/constructor/super
-
工具库: PubSubJS
-
下载: npm install pubsub-js --save
-
使用:
import PubSub from ‘pubsub-js’ //引入
PubSub.subscribe(‘delete’, function(data){ }); //订阅
PubSub.publish(‘delete’, data) //发布消息
实例 根据demo2改编
兄弟组件 爷孙组件之间通信 用这种方式比较好,不用再通过父组件传递
app.jsx 里面没有state等内容,因为孩子传递数据跟他没关系了
import React from 'react'
import Search from './search'
import Main from './main'
export default class App extends React.Component {
render() {
return (
<div id="app">
<div className="container">
<Search />
<Main />
</div>
</div>
)
}
}
search.jsx
1.3 方式三: redux
2. 事件监听理解
2.1原生DOM事件
- 绑定事件监听
a. 事件名(类型): 只有有限的几个, 不能随便写
b. 回调函数
-
触发事件
a. 用户操作界面
b. 事件名(类型)
c. 数据()
2.2 自定义事件(消息机制)
- 绑定事件监听
a. 事件名(类型): 任意
b. 回调函数: 通过形参接收数据, 在函数体处理事件
- 触发事件(编码)
a. 事件名(类型): 与绑定的事件监听的事件名一致
b. 数据: 会自动传递给回调函数
3. ES6常用新语法
-
定义常量/变量: const/let
-
解构赋值: let {a, b} = this.props import {aa} from ‘xxx’
-
对象的简洁表达: {a, b}
-
箭头函数:
a.常用场景
组件的自定义方法: xxx = () => {}
参数匿名函数
b.优点:
简洁
没有自己的this,使用引用this查找的是外部this
-
扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)
-
类: class/extends/constructor/super
-
ES6模块化: export default | import
上一篇: 设备尚未普及 Facebook已等不及要上线VR内容
下一篇: Python学习笔记01_基础语句
推荐阅读
-
牛皮了!7000字MySQL学习笔记,从入到放弃
-
Silverlight3学习笔记(2):Silverlight初接触
-
PHP——函数二_学习笔记 php四舍五入函数 php延时函数 php排序函
-
牛皮了!7000字MySQL学习笔记,从入到放弃
-
PHP——函数二_学习笔记 php四舍五入函数 php延时函数 php排序函
-
初入FCC闯关笔记 #1
-
java 多线程学习-----初入线程池
-
韩顺平_PHP软件工程师玩转算法公开课(第一季)01_算法重要性_五子棋算法_汉诺塔_回溯算法_学习笔记_源代码图解_PPT文档整理
-
SQL学习笔记――SQL初入门,Ubuntu下MySQL的安装_MySQL
-
SQL学习笔记――SQL初入门,Ubuntu下MySQL的安装_MySQL