https://note.youdao.com/ynote...css
all in js
单向数据流html
Fragment:占位符,替换最外层DIVreact
事件方法绑定
//方法一
<input value={inputVal} onChange={this.handleInputChange.bind(this)} />
<input value={inputVal}
//方法一-传递下标
onChange={this.handleInputChange.bind(this),index} />ios
//方法2
//this 的绑定放在构造函数里, 这样函数的this 永远指向这个组件
constructor(){git
this.handleInputChange = this.handleInputChange.bind(this)
}github
handleInputChange(){ajax
console.log(this);
}npm
改变状态值-setState
setState 能够接受一个参数preState (和构造函数里state保持一致)
preState: 上一次修改以前数据的状态redux
//方法一
this.setState({axios
xxx:xxx
})
//方法二 ---新版本推荐语法
this.setState(()=>{
return { xxx:xxx }
})
or
this.setState(()=>({ xxx:xxx }))
注释
{/xxxxxxxxxxxxxxxxxxxxx/}
{/xxxxxxxxxxxxxxxxxxxxxxx/}
className代替样式class
<div className='test'>
dangerouslySetInnerHTML
//<h1>hello world </h1> 至关于 v-html
<div dangerouslySetInnerHTML={{_html:item}}>
</div>
子组件修改父组件内容
子组件如何调用父组件方法,修改父组件的数据?
只须要把父组件的方法传给子组件,子组件就能够经过这个方法间接的操做父组件的数据
传递函数给子组件须要强制把做用域绑定在父组件的this
import Child from "./Child"
class Father extends React.Component{
render(){ <div> <Child showFather={this.handleFather.bind(this)}></Child> </div> } handleFather(){ alert('this is Father') }
}
//子组件调用
this.props.showFather()
propTypes和defaultTypes
import React,{Component} from 'react'
import PropTypes from 'prop-types'
class Test extends Component{
}
Test.propTypes={
content:PropTypes.string, deleteItem:PropTypes.func, index:PropTypes.number, test:PropTypes.string.isRequired, test2:onOfType([PropTypes.number,PropTypes.string])//两个类型均可以,这两个类型中的一个 test3:arrayOf(PropTypes.number,PropTypes.string)//数组类型,数组的组成内容能够是数字或者字符
}
Test.defaultProps={
test:"hello world"
}
Props,State和Render的关系
当组件的Props或者state发生改变的时候Render函数就会从新执行
父组件的render执行的时候子组件的render也会被执行
虚拟dom
虚拟dom是一个js对象,用来描述真实DOM
在js里面比较js对象不怎么耗性能,可是比较真实的dom会很耗费性能
用数组来描述第一个参数是标签名称,第二个参数是属性,第三个方法是子元素
['div',{id:"test"},['span',{},'hello']]
state 数据
JSX模板
数据+模板结合生成虚拟dom --原始虚拟DOM
用虚拟dom的结构,来生成真实DOM,在页面显示""
state发生变化
数据+模板结生成新的虚拟dom --新的虚拟dom
比较原始虚拟dom和新生成的虚拟dom的区别,区别出有差别的dom
直接操做dom 改变内容
ref
ref 接受一个箭头函数 (数据驱动,尽可能不要用ref) ref使用放在setState的第二个函数里面执行, 确保正确
<div ref={(testref)=>{
this.testref = testref
}}></div>
声明周期
某一时刻 组件会自动调用执行的函数 生命周期
render:渲染页面
getDerivedStateFromProps:接受两个参数(props,state)
构造函数执行后执行
state和props更新也会被执行
componentWillMount:组件即将被挂载到页面以前的时候执行(尚未被挂载)
componentDidMount:组件被挂载以后制动执行
shouldComponentUpdate:组件是否更新,返回布尔值类型,组件更新以前执行
componentWillUpdate:组件被更新以前自动,shouldComponentUpdate以后执行,若是shouldComponentUpdate返回true才执行,不然不会被执行
componentDidUpdate:组件完成更新以后会被执行
componentWillReceiveProps:执行须要知足一下条件
当组件从父组件接受了参数
若是这个组件第一次存在于父组件中,不会执行
若是以前已经存在于父组件中,才会执行
componentWillUnmount:这个组件即将从页面中剔除的时候执行
生命周期使用场景
shouldComponentUpdate(nextProps,nextState):接受两个参数
nextProps:接下来个人属性要变成什么样子,nextState 同理;避免组件重复渲染
componentDidMount:函数里来执行ajax请求
性能提高
shouldComponentUpdate:避免渲染
函数做用域绑定放在constroctor函数里作,函数做用域绑定只会执行一次,减小子组件的无谓渲染,
setState:异步函数, 能够把屡次性能的改变结合成一次。下降虚拟DOM的比对频率
虚拟dom,同层比对 KEY值比对,提升比对速度
React动画效果
css过渡动画
.show{
opacity:1 transinition:all 1s ease-in;
}
.hide{
opacity:0; transinition:all 1s ease-in;
}
css动画效果
@keyframes hide-iten{
0%{ opacity:1; color:red; } 50%{ opacity:0.5; color:green; } 100%{ opacity:0; color:blue; }
}
//forwards:当动画完成后,保持最后一个属性值(在最后一个关键帧中定义)
animation: hide-item 2s ease-in forwards;
React-transition-group
CSSTransition
<CSSTransition
in={showValidationMessage}
timeout={300}
classNames="message"
unmountOnExit
onExited={() => {
this.setState({ showValidationButton: true, });
}}
/>
//
in={showValidationMessage}
timeout:动画执行时间
classNames:类名前缀(fade)
unmountOnExit:隐藏以后dom被移除
.fade-enter{
opacity:0;
}
.fade-enter-active{
opacity:1; transition:opacity 1s easy-in;
}
.fade-enter-done{
opacity:1;
}
.fade-exit{
opacity:1
}
.fade-exit-active{
opacity:0; transition:opacity 1s easy-in;
}
.fade-done{
opacity:0
}
CSSTransition会自动的给dom添加一些样式,何时添加这个样式由“in”来控制
动画执行会在dom元素挂载css类:.fade-enter,.fade-enter-active,.fade-active.done,.fade-exit, .fade-exit-active, .fade-exit-done
.fade-enter:当动画执行入场动画时,也就是showValidationMessage由flase变成true的时候,在入场动画执行的第一个时刻,组件会给div挂载.fade-enter,刚要入场尚未入场的时候的状态
.fade-enter-active:入场动画执行的第二个时刻,到入场动画执行完成以前。dom上一直会有这个fade-enter-active
.fade-active.done:当整个入场动画执行完成以后,.fade-active.done会被添加到dom元素
React-transition-groupJS实现动画
classNames={{
appear: 'my-appear',
appearActive: 'my-active-appear',
enter: 'my-enter',
enterActive: 'my-active-enter',
enterDone: 'my-done-enter,
exit: 'my-exit',
exitActive: 'my-active-exit',
exitDone: 'my-done-exit,
}}
<CSSTransition
onExited={() => {
this.setState({ showValidationButton: true, });
}}
//钩子函数(和生命周期函数同样,在某一个时刻自动执行的函数)
onEntered={(el)=>{
el.style.color = "red"
}}
onEntered:入场动画执行完成以后执行,该钩子执行,接受一个参数el(CSSTransition内部包裹的元素) el.style.color = "red"
onEnter:入场动画执行第一帧的时候执行
onEntering:入场动画第二帧,到结束以前执行
第一次进入页面加动画
第一次展现也要动画效果 appear=true
<CSSTransition appear={true} />
改功能会在动画执行的第一帧 添加==.fade-appear==
<div class="fade-active fade-appear">
动画第二帧,已经整个动画执行的过程当中 添加.fade-appear-active
TransitionGroup
多个动画
UI组件和容器组件的拆分
UI组件负责容器的渲染-傻瓜组件
容器组件负责页面的逻辑-容器组件
无状态组件
一个组件若是只有render函数的时候,能够改写成无状态组件
性能会更高,由于它就是一个函数,而不是一个类,因此没有生命周期函数
定义UI组件,或者没有逻辑操做 只须要渲染的时候能够定义为无状态组件
const test=(props)=>{
render(){ return ( <div>{props.test}</div> ) }
}
Redux
实例图: 相似于一个图书馆借书流程
React Components:用户
Action Creators:借书的动做(告诉管理员要借什么书)
Store:图书馆管理员负责全部图书的管理(store是惟一的,只有store能改变本身的内容,store拿到reduce返回的数据,再对数据进行更新,reduce只是对数据作处理)
Reducers:记录本,记录全部的数据(必须是一个纯函数--给定固定的输入,就必定会有固定的输出,并且不会有任何反作用)
React Components
Action Creators
Store
Reducers
(1)
(2) dispatch(action)
(3)(previousState,action)
(4) (newState)
(5)(state)
React Components
Action Creators
Store
Reducers
reduce
建立流程
1.建立数据管理仓库
yarn add redux
建立store 文件夹, 建立index.js(store 代码存放位置) index.js
import {createStore} from 'redux';
//第二步建立reducer.js后 引入reducer
import reducer from './reducer.js'
const store = createStore()
export default store
2.建立reducer.js(负责对全局数据的更改)
根据用户派发的action和value来对state作操做,而后返回新的newstate(固定写法)
reducer能够接受state可是绝对不能修改state,因此咱们要定义一个新的newState
//state:存储全部的数据
//设置默认值
const defaultState = {
inputVal:'', list:[],
}
export default (state=defaultState,action)=>{
let newState = JSON.parse(JSON.stringify(state)) switch (action.type) { case 'change_input_value': newState.inputVal = action.value; return newState; break; case 'add_item': newState.list.push(newState.inputVal); newState.inputVal = "" return newState; break; default: return state } return state
}
3.在文件中引入,获取数据
store.getState():获取store数据
store.dispatch(action):设置更改store数据;(action={type:'',val})
import React from 'react'
import store from 'store/index.js'
class text extends React.component{
constructor(props){ super(props) this.state = store.getState() //订阅store状态,发生改变时回调函数自动执行 store.subscribe(()=>{ this.setState(store.getState()) ) } submitSatate(val){ const action ={ type:'change_input_value', value:val } }
}
Redux-thunk中间件
将异步请求或者复杂的逻辑放到action里来执行
https://github.com/reduxjs/re...;
如何引入
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
// Note: this API requires redux@>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
如何使用 普通的action creator返回的是一个对象
export const getTodoList=(data)=>(
{ type:'TODOLIST', data }
)
使用redux-thunk 能够在里面返回一个异步函数
//返回action
export const initListAction =(data)=({
type:"INIT_LIST_ACTION", data,
})
export const getTodoList =()=>{
return (dispacth)=>{ axios.get(url).then((res)=>{ const data = res.data; const action = initListAction(data) dispatch(action) }) }
}
在业务代码中使用
componentDidMount(){
const action = getTodoList(); store.dispatch(action)
}
store.dispatch(action)调用的时候action会自动被执行(此时action是redux-thunk返回的一个函数) redux-thunk
中间件是在 action--store中间作操做
Redux-saga 中间件
https://github.com/redux-saga... 后续补上
React-Redux的使用
第三方模块,能够帮助咱们在React中更加方便的使用Redux
核心API
Provider:链接Store,Provier内部的组件都有能力获取到Store里的内容了
connect:让组件和sotre作链接
安装--首配置
npm install --save react-redux
//更目录下的index 引入 react-redux,store
import { Provider } from 'react-redux'
import store from './store/index'
//将要渲染在更目录下的组件用provider包裹起来(Provider其实就是一个组件)
//将store做为属性值传递给provider,provider内部的组件都有能力获取store
const App = (
<Provider store={store}> <TodoList /> </Provider>
)
//将App做为组件 传递给ReactDOM.render方法
ReactDOM.render(<TodoList />, document.getElementById('root'));
组件内使用,使用Props来获取状态或者派发dispatch
import {connect} from 'react-redux';
class TodoList extends Component{
render(){ return { <div> </div> } }
}
const mapStateToProps = (state) => {
return {
inputVal: state.inputVal, list: state.list
}
}
//将Store的dispatch方法挂载到Props方法上
//自动disPatch(方法能够直接返回{type:xxx,value:xxx})
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue(e) { let inputVal = e.target.value const action = { type: 'change_input_value', inputVal } dispatch(action) },
}
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoList)
请求拦截
//拦截请求
axios.interceptors.request.use(config => {
console.log(config) return config
})
//拦截响应
axios.interceptors.response.use(response => {
console.log(response)
return response
})