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
})