1、react初步了解
1、特点
- 声明式 :我们只需要更新数据就可以了,不用亲自操作dom元素。
- 组件化 :将页面分为一个个的组建,易于编写和维护。
2、高效的原因
- 虚拟dom,不总是直接操作DOM。以前是一个一个修改DOM,虚拟DOM与DOM对象一一对应,更改虚拟DOM并不会直接更改DOM,而是等待都更改完成,批量更改。
- DOM Diff 算法,最小化页面重绘。
3、引入库文件
开源库
react-dom.development.js(提供操作DOM对象的react扩展库)、react.development.js(react核心库)、babel.js(把ES6改为ES5或解析jsx语法为js语法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="test"> </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.js"></script>
<script type="text/babel"> //1、创建虚拟DOM元素对象 var vDom = <h1>Hello React!</h1> //2、将虚拟DOM渲染到页面真是DOM对象中 ReactDOM.render(vDom,document.getElementById('test')) </script>
|
2、了解jsx
1、不使用jsx创建虚拟DOM对象
1
| var element = React.creatElement('h1',{id:'myTitle'},'hello')
|
如果要使用变量中定义的内容,要使用{ }将变量包起来。
再js中可以使用debugger来设置断点。
在React组件的构造函数中设置this.state来初始化state。
2、自定义组件
1、定义组件
方式一、工厂函数组件
function MyComponent(){
return
}
方式二、es6类组件
class MyComponent2 extends React.Component{
render(){
return
}
}
2、渲染组件标签
ReactDOM.render(,document.getElementById(‘example1’))
3、组件的三打属性
①state
是一个对象,如果用它则必须使用类组件的方式。在constructor()方法中定义。可以使用setState({xxx = xxx})方式来更新数据,用这种方式更新数据,所有的用到该数据的地方都会进行更新。
②props
是一个对象,用来将数据从组件外传入到组件内部。
指定默认值
1 2 3 4 5
| Person.defaultProps = { sex: '男', age:18 }
|
props验证
React.PropTypes 在 React v15.5 版本后已经移到了 prop-types 库。
1
| <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
|
1 2 3 4 5
| Person.propTypes = { name:PropTypes.string.isRequired, age:PropTypes.number }
|
③refs
作用: React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。
这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保
在任何时间总是拿到正确的实例。
1 2 3
| <input ref = ‘content'></input>
const input = this.refs.content
|
外边的大括号代表进行书写js文件,里面的括号代表这是一个对象。
react ajax
react本身没有提供ajax相关的代码。
解决方法:
1、jQuery:比较重,不建议使用
2、axios:轻量级,建议使用
- 封装XmlHttpRequest对象的ajax
- promise风格
- 可以用在浏览器端和node服务器端
3、fetch:原生函数,但老版本浏览器不支持
- 不再使用XmlHttpRequest对象提交的ajax请求
- 为了兼容低版本的浏览器,可以引入兼容库fetch.js
兄弟组件之间传递信息
组件:pubsub-js
1 2 3 4 5 6 7 8
| import PubSub from 'pubsub-js'
PubSub.publish('name',data)
PubSub.subscribe('name',(name,data)=>{ hanshu
})
|
如何编写路由效果
- 编写路由组件
- 在父路由组件中指定
Redux
1.安装redex
npm install –save redux
2.API
3.对象
- store
- 作用:redux库最核心的管理对象
- 内部属性
- state 公共状态
- reducer 改变状态的函数
- 方法
- getState()
- dispatch(action)
- subscribe(listener)
- 编码
- store.getState() //获取状态数据
- store.dispatch({type:’INCREMENT’,number}) //进行状态数据更改
- store.subscribe(render) //状态数据更改后要重新执行渲染
4.核心概念
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| import {INCREMENT,DECREMENT} from "./action-type";
export function counter(state = 0,action) { console.log('counter()',state,action) switch (action.type) { case INCREMENT: return state + action.data break case DECREMENT: return state - action.data break default: return state } }
import {createStore} from "redux"; import {counter} from "./reducers"; const store = createStore(counter)
function render() { ReactDOM.render(<App store={store}/>,document.getElementById('root')) }
render()
store.subscribe( render() )
import {INCREMENT,DECREMENT} from "./action-type"; export const increment = (number)=>({type:INCREMENT,data:number}) export const decrement = (number)=>({type:INCREMENT,data:number})
import React,{Component} from "react"; import {INCREMENT,DECREMENT} from "../action-type"; import * as actions from "../actions" export default class App extends Component{ increment = ()=>{ const number = this.select.value*1 this.props.store.dispatch(actions.increment(number)) }
decrement = ()=>{ const number = this.select.value*1 this.props.store.dispatch(actions.decrement(number)) }
incrementIfOdd = ()=>{ const number = this.select.value*1 const count = this.props.store.getState() if (count%2==1){ this.props.store.dispatch(actions.increment(number)) } }
incrementAsync = ()=>{ const number = this.select.value*1 const count = this.props.store.getState() setTimeout(()=>{ this.props.store.dispatch(actions.increment(number)) },1000) }
render() { const count = this.props.store.getState() return( <div> <p>click {count} times</p> <div> <select ref={select=>this.select = select}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>increment if odd</button> <button onClick={this.incrementAsync}>increment async</button> </div> </div> ) } }
|
使用react-redux简化(就是使用传参的方式传递state和改变state函数)
- 引入
npm install --save react-redux
- 在index中 用Provider包装组件
1 2 3 4 5 6
| import {Provider} from 'react-redux' ReactDOM.render( <Provider store = {store}> <App/> </Provider> )
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import PropTypes from 'prop-types' import {connect} from 'react-redux' import {increment,decrement} from "../actions"; class App extents React.Component{ static propTypes = { count:PropTypes.number.isRequired, incrememt:PropTypes.func.isRequired, decrement:PropTypes.func.isRequired } .... incrementIfOdd = ()=>{ const number = this.select.value*1 const count = this.props.count if (count%2==1){ this.props.incrememt(number) } } .... } export default connect( state=>({count:state}), {increment,decrement} )(<App/>)
|
- react-redux分为component和container
- component不包含redux内容的部分
- container是包含redux内容的部分
redux异步编程
下载redux插件(异步编程中间件)
npm install --save redux-thunk
在store.js中添加applyMiddleware和thunk
1 2 3 4 5 6
| import {createStore,applyMiddleware} from "redux"; import {counter} from "./reducers"; import thunk from 'redux-thunk'
const store = createStore(counter,applyMiddleware(thunk)) export default store
|
在插件中异步函数使用this.props.incrementAsync()函数
1 2 3 4 5
| incrementAsync = ()=>{ const number = this.select.value*1 this.props.incrementAsync(number) }
|
- 在container中app.js中(也就是绑定参数的函数的js文件)添加incrementAsync函数
1 2 3 4 5 6 7 8
| import React from "react"; import {connect} from "react-redux"; import {decrement, increment,incrementAsync} from "../actions"; import Counter from "../components/counter"; export default connect( state =>({count:state}), {increment,decrement,incrementAsync} )(Counter)
|
- 在actions文件中添加函数(注意异步函数返回的是一个函数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
import {INCREMENT,DECREMENT} from "./action-type"; import {number} from "prop-types";
export const increment = (number)=>({type:INCREMENT,data:number})
export const decrement = (number)=>({type:DECREMENT,data:number})
export const incrementAsync = (number)=>{ return dispatch=>{ setTimeout(()=>{ dispatch(increment(number)) },1000) } }
|