react 2013 單向數(shù)據(jù)流
和vue區(qū)別
內(nèi)存的改變影響頁面的改變,不管頁面的改變, 影響內(nèi)存的改變
自己處理頁面的改變, 影響內(nèi)存, 通過事件, 調(diào)用函數(shù), 通知根據(jù)內(nèi)存對象改變頁面
沒有指令
安裝React腳手架: npm install -g create-react-app
創(chuàng)建腳手架: create-react-app myApp
產(chǎn)看版本: create-react-app --version
安裝react-router: cnpm i react-router -S
安裝react-router-dom: cnpm i react-router-dom -S
安裝redux: cnpm i redux
展示配置文件: npm run eject
使用sass: npm i node-sass
有變化的屬性
className
htmlFor
style={{ fontSize: '12px' }}
this.state: 讀取狀態(tài)
this.setState: 更新組件的狀態(tài)
import React, { Component } from 'react' //創(chuàng)建組件麸拄、虛擬DOM元素, 生命周期
import ReactDOM from 'react-dom' //把創(chuàng)建好的 組件 和 虛擬DOM放到頁面上面展示
創(chuàng)建虛擬DOM元素
// 參數(shù)1: 創(chuàng)建的元素的類型, 字符串, 表示元素的名稱
// 參數(shù)2: 是一個(gè)對象或 null, 表示 當(dāng)前這個(gè) DOM 元素的屬性
// 參數(shù)3: 子節(jié)點(diǎn) (包括 其他 虛擬DOM 獲取 文本子節(jié)點(diǎn))
// 參數(shù)n: 其它子節(jié)點(diǎn)
const myh1 = React.createElement('h1',{title:"this is a h1", id: "myh1"},'這是一個(gè)標(biāo)題H1')
使用 ReactDOM 把虛擬 DOM 渲染到頁面上
// 參數(shù)1: 要渲染的那個(gè)虛擬DOM元素
// 參數(shù)2: 指定頁面上一個(gè)容器
ReactDOM.render(myh1, document.getElementById("app"))
class關(guān)鍵字創(chuàng)建組件
class Movie extends React.Component{
//render 函數(shù)的作用, 是 渲染 當(dāng)前組件所對應(yīng)的 虛擬DOM元素
render() {
return (
<div>這是Movie組件</div>
)
}
}
##const Footer = ()=>{
return (
)
}
Ref選取dom元素
<input type="text" ref="id"/> ref ==> this.refs.id.value
<input type="text" ref="id=>this.id = id" /> this.id.value
限定接收props類型
TodoList.propTypes = {
title: PropTypes.number.isRequired //必須傳遞此屬性
}
array ==> bool ==> func ==> number ==> object ==> string ==> symbol
指定屬性默認(rèn)值
Person.defaultProps = {
sex: '男',
age: 18
}
父傳子:
組件接收屬性值的傳遞:
this.props屬性名
例如:
<Header title="留言"> <div>這是我的children</div> </Header>
constructor(props){
super(props)
render(){
return(
{this.props.title}
{this.props.children}
)
}
}
子傳父:
在父組件中定義一個(gè)設(shè)置state的方法, 然后把這個(gè)方法通過屬性傳遞給子組件
在子組件中調(diào)用這個(gè)方法惰聂。 把值傳入就可以了。
路由react-router-dom: exact精確匹配
安裝: cnpm i react-router-dom -S
引入: import { BrowserRouter,HashRouter, Route, Link, NavLink, Switch, Redirect, useParams } from 'react-router-dom';
代碼:
<Router>
<div>
<switch> //匹配到第一個(gè)終止匹配
<Route exact path="/home" component={Home} />
<Route exact path="/kind" component={Kind} />
<Route exact path="/user" component={User} />
<Redirect from="/" to="/home" /> //跟目錄跳轉(zhuǎn)home頁面
<Route exact path="/404" component={404}> //配置404頁面
<Redirect from="/*" to="/" /> //重定向404頁面
</switch>
</div>
</Router>
react路由懶加載
yarn add react-loadable
import Loadable from 'react-loadable';
編程跳轉(zhuǎn)
指定前進(jìn)后退: this.props.history.go()
后退: this.props.history.goBack()
前進(jìn): this.props.history.goForward()
this.props.history.push('/Home');
query傳參
this.props.history.push({ pathName:'/Home', search:'id=id&name=name' })
params動態(tài)路由傳參:
跳轉(zhuǎn)傳參: <NavLink to="/detail/paramName" activeClassName="navActive"></NavLink>
路由配置: <Route path="/detail/:paramName" component={Detail} />
組件參數(shù)接收: this.props.match.params.paramName
query動態(tài)路由傳參:
跳轉(zhuǎn)傳參: <NavLink to={{pathName:"/detail",search:"?id=123&name=tian"}} activeClassName="navActive"></NavLink>
路由配置: <Route path="/detail" component={Detail} />
組件參數(shù)接收: this.props.location.search
① 此時(shí)拿到是一個(gè)字符串 'id=1&name=2'
需要安裝
npm i query-string
使用
import queryString from 'query-string';
queryString.parse( this.props.location.search )
redux
安裝 npm i redux
配置
index.js文件下
import { createStore } from 'redux';
import reducer from './reducer.js'
const store = createStore(reducer);
export default store;
reducer.js文件下
const defaultState = {
list: [1,2,3,4,5]
}
export default (state=defaultState, action) => {
return state
}
獲取state:
import store from './store.js'
store.getState().list;
訂閱state改變: //每次派發(fā)action的時(shí)候重新獲取數(shù)據(jù)
store.subscribe(this.handleSubScribe)
觸發(fā)對應(yīng)事件改變state
handleSubScribe = ()=>{
this.setState({
initState = store.getState().initState;
})
}
更新state:
const action = {
type: "CHANGE_VALUE",
value: '新的value'
};
store.dispatch(action)
在reducer.js文件下
export default (state=defaultState, action) => {
if(action.type == 'CHANGE_VALUE'){
const initState = {...state};
initState.value = action.value;
return initState;
}
return state
}
模塊化:
reducer.js文件下
import {combineReducers} from 'redux';
import homeReducer from './modules/homeReducer'
import userReducer from './modules/userReducer'
let reducer = combineReducers({
home: homeReducer,
user: userReducer
})
export default reducer
homeReducer.js文件下 || userReducer.js文件下
const defaultState = {
list: [1,2,3,4,5]
}
export default (state=defaultState, action) => {
return state
}
獲取:
store.getState().home.value
訂閱:
store.subscribe(this.handleSubScribe);
handleSubScribe = () => {
this.setState({
value: store.getState().home.value
})
}
更新state:
const action = {
type: "CHANGE_VALUE",
value: '新的value'
};
store.dispatch(action)
在homeReducer.js文件下
export default (state=defaultState, action) => {
if(action.type == 'CHANGE_VALUE'){
const initState = {...state};
initState.value = action.value;
return initState;
}
return state
}
react-redux
安裝:
cnpm i react-redux
APP.js文件內(nèi)
import store from './store/index.js'
所有組件使用 ** 包裹
<Provider store={store}></Provider>
頁面內(nèi)使用:
const mapStateToProps = state => {
return {
name: state.home.name
}
}
const mapDispatchToProps = dispatch => {
return {
changeName(){
dispatch({
type:'CHANGE_NAME',
value:'田國元'
})
}
}
}
export default connect(reduxState, reduxAction)(Home);
redux-thunk
安裝:
cnpm i redux-thunk
store文件下index.js
import { createStore,compose,applyMiddleware } from 'redux';
import reducer from './reducer.js'
import thunk from 'redux-thunk'
const store = createStore(reducer,compose(applyMiddleware(thunk)));
export default store;
頁面內(nèi): ## redux-thunk異步請求解決了redux的action只能是對象, 可以讓對象形式改成為異步函數(shù),異步函數(shù)接收dispatch
const reduxAction = dispatch => {
return {
changeName(){
dispatch(dispatchs => {
fetch('./data.json').then(res=>res.json()).then(data=>{
console.log(data);
dispatchs({
type:'CHANGE_NAME',
value: data.id
})
})
})
}
}
}
React生命周期
getDefaultProps 初始化prop屬性 (es6的寫法中被刪除)
getInitialState 初始化當(dāng)前狀態(tài) (es6的寫法中被刪除)
**componentWillMount 組件初始化前 (即將進(jìn)入dom)
**componentDidMount 組件初始化DOM插入完后 (已經(jīng)進(jìn)入dom)
**render 觸發(fā)state改變UI
componentWillReceiveProps 父組件傳遞調(diào)用方法
shouldComponentUpdata 是否要更新 return false 就不會更新
componentWillUpdate 組件更新之前
componentDidUpdate 組件更新之后
componentWillUnmount 組件銷毀前
componentDidUnmount 組件銷毀后
注意點(diǎn):
1. XML 基本語法
定義標(biāo)簽是, 只允許被一個(gè)標(biāo)簽包裹
標(biāo)簽一定要閉合
2. 元素類型
小寫首字母對應(yīng) DOM 元素屬性
大寫首字母對應(yīng)組件元素
注釋使用 js 注釋方法
3. 元素屬性
class 屬性改為 className
for 屬性改為 htmlFor
Boolean 屬性: 省略 Boolean 屬性值會導(dǎo)致 JSX 認(rèn)為 bool 值設(shè)為了 true
4. JavaScript 屬性表達(dá)式
屬性只要使用表達(dá)式, 只要用 {} 替換 "" 即可
<input type="text" value={ val ? val : "" } />
5. HTML 轉(zhuǎn)義
React會將所有要顯示到 DOM 的字符串轉(zhuǎn)義, 放置 XSS.
后臺傳過來的數(shù)據(jù)帶頁面標(biāo)簽的是不能直接轉(zhuǎn)義的, 集體轉(zhuǎn)移的寫法如下:
var content= ' <strong> content </strong> ';
React.render(
<div dangerouslySetInnerHTML = {{__html: content}}> </div>,
document.body
)
動畫: ReactCSSTransitionGroup
1. 引入組件
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
2.使用ReactCSSTransitionGroup 標(biāo)簽包裹動畫標(biāo)簽
<ReactCSSTransitionGroup
transitionName='example'
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
>
</ReactCSSTransitionGroup>
注意:
生成{items}的時(shí)候, 里面沒一個(gè)元素必須包含KEY屬性再菊。 因?yàn)閞eact 要判斷哪個(gè)元素進(jìn)入, 停留, 移除
css: {
.example-enter // 進(jìn)入動畫的起點(diǎn)
.example-enter-active // 進(jìn)入動畫的終點(diǎn)
.example-leave // 離開動畫的起點(diǎn)
.example-leave-active // 離開動畫的終點(diǎn)
.example-enter{ margin-left: -200px; transform:rotate(0deg); transition-duration:500ms; }
.example-enter-active{ margin-left: 0px; transform:rotate(3600deg); }
.example-leave{ margin-left:0px; opacity:1; transition-duration:300ms; }
.example-leave-active{ margin-left:600px; opacity:0; }
}