React 入門及學習筆記

React 構建用戶界面的JavaScript庫,主要用於構建UI界面。Instagram2013年開源。javascript

特色:

  1. 聲明式的設計
  2. 高效,採用虛擬DOM來實現DOM的渲染,最大限度的減小DOM的操做。
  3. 靈活,跟其餘庫靈活搭配使用。
  4. JSX,俗稱JS裏面寫HTMLJavaScript語法的擴展。
  5. 組件化,模塊化。代碼容易複用,2016年以前大型項目很是喜歡react
  6. 單向數據流。沒有實現數據的雙向綁定。數據-》視圖-》事件-》數據

建立項目

1、經過script引入使用,僅用於學習調試使用css

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

二、經過react的腳手架,建立項目進行開發,部署html

1.	安裝腳手架Create React App。
cnpm install -g create-react-app
2.	建立項目
create-react-app 01reactapp(項目名稱能夠自定義)

React元素渲染

let h1 = <h1>helloworld</h1>;
使用JSX的寫法,能夠建立JS元素對象
注意:JSX元素對象,或者組件對象,必須只有1個根元素(根節點)

案例使用:vue

//實現頁面時刻的顯示

function clock(){
    let time = new Date().toLocaleTimeString()
    let element = (
        <div>
            <h1>如今的時間是{time} </h1>
            <h2>這是副標題</h2>
        </div>
    )
    let root = document.querySelector('#root');
    ReactDOM.render(element,root)
}

clock()

setInterval(clock,1000)

函數式組件渲染java

function Clock(props){
    return (
                <div>
                    <h1>如今的時間是{props.date.toLocaleTimeString()} </h1>
                    <h2>這是函數式組件開發</h2>
                </div>
    )
}

function run(){
    ReactDOM.render(
        <Clock date={new Date()} />,
        document.querySelector('#root')
    )
}

setInterval(run,1000)

React Jsx

優勢:react

  1. JSX執行更快,編譯爲JavaScript代碼時進行優化
  2. 類型更安全,編譯過程若是出錯就不能編譯,及時發現錯誤
  3. JSX編寫模板更加簡單快速。(不要跟VUE比)

注意:es6

  1. JSX必需要有根節點。
  2. 正常的普通HTML元素要小寫。若是是大寫,默認認爲是組件。

JSX表達式

  1. HTML元素構成
  2. 中間若是須要插入變量用{}
  3. {}中間可使用表達式
  4. {}中間表達式中可使用JSX對象
  5. 屬性和html內容同樣都是用{}來插入內容

案例vuex

import React from 'react';
import ReactDOM from 'react-dom';
import './App.css'

let time = new Date().toLocaleTimeString()
let str = '當前時間是:'
let element = (
    <div>
        <h1>helloworld</h1>
        <h2>{str+time}</h2>
    </div>
)

console.log(element)

let man = '發熱';
let element2 = (
    <div>
        <h1>今天是否隔離</h1>
        <h2>{man=="發熱"?<button>隔離</button>:"躺牀上"}</h2>
    </div>
)

//let man = '發熱';
let element4 = (
    <div>
        <span>橫着躺</span>
        <span>豎着躺</span>
    </div>
)
man = '正常'
let element3 = (
    <div>
        <h1>今天是否隔離</h1>
        <h2>{man=="發熱"?<button>隔離</button>:element4}</h2>
    </div>
)

let color = 'bgRed'
let logo = 'https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png'
//HTML的樣式類名要寫className,由於class在js當中是關鍵詞
let element5 = (
    <div className={color}>
        <img src={logo} />
        紅色的背景顏色
    </div>

)

ReactDOM.render(
    element5,
    document.getElementById('root')

)

JSX_style 樣式

  1. Classstyle中,不能夠存在多個class屬性
  2. style樣式中,若是存在多個單詞的屬性組合,第二個單詞開始,首字母大寫。或者用引號引發來,不然會報錯。
let exampleStyle = {
    background:"skyblue",
    borderBottom:"4px solid red",
    'background-image':"url(https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png)"
}

3.多個類共存的操做npm

let element2 = (
    <div>
        <h1 className={"abc "+classStr}>helloworld</h1>
    </div>
)


let classStr2 = ['abc2','redBg2'].join(" ")
let element3 = (
    <div>
        {/* 這裏寫註釋 */}
        <h1 className={classStr2} style={exampleStyle}>helloworld</h1>
    </div>
)

4.註釋json

必須在括號的表達式內書寫,不然報錯:{/* 這裏寫註釋 */}

React組件

函數式組件與類組件的區別和使用,函數式比較簡單,通常用於靜態沒有交互事件內容的組件頁面。類組件,通常又稱爲動態組件,那麼通常會有交互或者數據修改的操做。

  1. 函數式組件
//函數式組件
function Childcom(props){
    console.log(props)

    let title = <h2>我是副標題</h2>
    let weather = props.weather
    //條件判斷 
    let isGo = weather=='下雨' ?"不出門":"出門"

    return (
        <div>
            <h1>函數式組件helloworld</h1>
            {title}

            <div>
                是否出門?
                <span>{isGo}</span>
            </div>
        </div>
    )
}

2.類組件

//類組件定義
class HelloWorld extends React.Component{
    render(){
        console.log(this)
        return (
            <div>
                <h1>類組件定義HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }
}

3.複合組件:組件中又有其餘的組件,複合組件中既能夠有類組件又能夠有函數組件。

import React from 'react';
import ReactDOM from 'react-dom';
import './04style.css';
//函數式組件
function Childcom(props){
    console.log(props)

    let title = <h2>我是副標題</h2>
    let weather = props.weather
    //條件判斷 
    let isGo = weather=='下雨' ?"不出門":"出門"

    return (
        <div>
            <h1>函數式組件helloworld</h1>
            {title}

            <div>
                是否出門?
                <span>{isGo}</span>
            </div>
        </div>
    )
}

//類組件定義
class HelloWorld extends React.Component{
    render(){
        console.log(this)
//返回的都是JSX對象
        return (
            <div>
                <h1>類組件定義HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }


}


// ReactDOM.render(
//     <Childcom weather="出太陽" />,
//     document.querySelector('#root')
// )

ReactDOM.render(
    <HelloWorld name="老陳" weather="下雨" />,
    document.querySelector('#root')
)

React State

至關於VUEDATA,可是使用方式跟VUE不一致。

Props

父傳遞給子組件數據,單向流動,不能子傳遞給父。

props的傳值,能夠是任意的類型。

Props能夠設置默認值

HelloMessage.defaultProps = {  name:」老陳msg:「helloworld  }

注意:props能夠傳遞函數,props能夠傳遞父元素的函數,就能夠去修改父元素的state,從而達到傳遞數據給父元素。

父傳參給子

//在父元素中使用state去控制子元素props的從而達到父元素數據傳遞給子元素
class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isActive:true
        }
        //綁定事件
        this.changeShow = this.changeShow.bind(this)
    }
    render(){
        return (
            <div>
                <button onClick={this.changeShow}>控制子元素顯示</button>
                <ChildCom isActive={this.state.isActive} />
            </div>
        )
    }
    changeShow(){
        this.setState({
            isActive:!this.state.isActive
        })
    }
}

class ChildCom extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        let strClass = null;
        if(this.props.isActive){
            strClass = ' active'
        }else{
            strClass = ""
        }
        strClass = this.props.isActive?" active":"";

        return (
            <div className={"content"+strClass}>
                <h1>我是子元素</h1>
            </div>
        )
    }
}

子傳參給父

class Parent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            childData: null
        }
    }
    render() {
        return ( 
          <div>
            <h1>子元素傳遞給父元素的數據:{this.state.childData}</h1>
            {/* 將設置參數的方法經過props傳給子元素 */}
            <Child setChildData={this.setChildData}/>
          </div>
        )
    }
    setChildData=(data)=>{
      this.setState({
        childData:data
      })
    }
}

class Child extends React.Component{
  constructor(props){
    super(props)
    this.state={
      msg:"helloworld"
    }
  }
  render(){
    return(
      <div>
        <button onClick={this.senData}>傳參給父元素</button>
       //使用ES6,能夠直接在按鈕的事件中寫箭頭函數傳參
        <button onClick={()=>{this.props.setChildData("666")}}>傳參給父元素</button>
        //不使用ES6,
        <button onClick={function(e){this.props.setChildData("666")}.bind(this)}>傳參給父元素</button>
      </div>
    )
  }
  //不綁定事件能夠直接使用箭頭函數
  senData=()=>{
    從父元素傳過來的props裏面的方法傳遞參數
    this.props.setChildData(this.state.msg)
  }
}

事件

特色:

一、react事件,綁定事件的命名,駝峯命名法。

二、{},傳入1個函數,而不是字符串

<button onClick={this.sendData}>傳遞helloworld給父元素</button>

事件對象:React返回的事件對象是代理的原生的事件對象,若是想要查看事件對象的具體值,必須之間輸出事件對象的屬性。

注意:

原生,阻止默認行爲時,能夠直接返回return false

React中,阻止默認必須e.preventDefault();

React事件傳參數

{/* 使用ES6箭頭函數傳遞多個參數 */}
<button  onClick={(e)=>{this.parentEvent1('msg:helloworld',e)}}>提交</button>
{/* //不使用ES6箭頭函數傳遞多個參數的方式 */}
<button  onClick={function(e){this.parentEvent1('不使用es6,msg:helloworld',e)}.bind(this)}>提交</button>

條件渲染

一、直接經過條件運算返回要渲染的JSX對象

二、經過條件運算得出jsx對象,在將JSX對象渲染到模板中。

案例1

function UserGreet(props){
    return (<h1>歡迎登錄</h1>)
}

function UserLogin(props){
    return (<h1>請先登陸</h1>)
}

class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:true
        }
    }
    render(){
        if(this.state.isLogin){
            return (<UserGreet></UserGreet>)
        }else{
            return (<UserLogin></UserLogin>)
        }
    }
}

案例2

function UserGreet(props){
    return (<h1>歡迎登錄</h1>)
}

function UserLogin(props){
    return (<h1>請先登陸</h1>)
}

class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:false
        }
    }
    render(){
        let element = null;
        if(this.state.isLogin){
            element = <UserGreet></UserGreet>;
        }else{
            element = (<UserLogin></UserLogin>);
        }

        

        return (
            <div>
                <h1>這是頭部</h1>
                {element}
                <h1>這是三元運算符的操做</h1>
                {this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>}
                <h1>這是尾部</h1>
            </div>
        )
    }
}

列表渲染

將列表內容拼裝成數組放置到模板中。將數據拼裝成數組的JSX對象。

使用數組的map方法,對每一項數據按照JSX的形式進行加工,最終獲得1個每一項都是JSX對象的數組,在將數組渲染到模板中。

Key值須要放置到每一項中。

案例1

class Welcome extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            list:[
                {
                    title:"第一節 React事件",
                    content:"事件內容"
                },
                {
                    title:"第二節 React數據傳遞",
                    content:"數據傳遞內容",
                },
                {
                    title:"第三節 條件渲染",
                    content:"條件渲染內容",
                }
            ]
        }
    }

    render(){
        let listArr = [];
        for(let i=0;i<this.state.list.length;i++){
            let item = (
                <li>
                    <h3>{this.state.list[i].title}</h3>
                    <p>{this.state.list[i].content}</p>
                </li>
            )
            listArr.push(item)
        }
        return (
            <div>
                <h1>
                    今天課程內容
                </h1>

                <ul>
                    {listArr}
                    <li>
                        <h3>這是標題</h3>
                        <p>內容</p>
                    </li>
                </ul>

            </div>
        )
    }
}

案例2

function ListItem(props){
    return (
        <li>
            <h3>{props.index+1}:listItem:{props.data.title}</h3>
            <p>{props.data.content}</p>
        </li>
    )
}

class ListItem2 extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        return (
            <li onClick={(event)=>{this.clickEvent(
                this.props.index,
                this.props.data.title,
                event
                )}}>
                <h3>{this.props.index+1}:listItem:{this.props.data.title}</h3>
                <p>{this.props.data.content}</p>
            </li>
        )
    }
    clickEvent=(index,title,event)=>{
        alert((index+1)+"-"+title)
    }
}


class Welcome extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            list:[
                {
                    title:"第一節 React事件",
                    content:"事件內容"
                },
                {
                    title:"第二節 React數據傳遞",
                    content:"數據傳遞內容",
                },
                {
                    title:"第三節 條件渲染",
                    content:"條件渲染內容",
                }
            ]
        }
    }

    render(){
        let listArr = this.state.list.map((item,index)=>{
            return (
                <ListItem2 key={index} data={item} index={index}></ListItem2>
                
            )
        })
        
        return (
            <div>
                <h1>
                    今天課程內容
                </h1>

                <ul>
                    {listArr}
                    <li>
                        <h3>這是標題</h3>
                        <p>內容</p>
                    </li>
                </ul>

                <h1>複雜沒有用組件完成列表</h1>
                <ul>
                {
                    this.state.list.map((item,index)=>{
                        return (
                            <li key={index} onClick={(event)=>{this.clickFn(index,item.title,event)}}>
                                <h3>{index+1}-複雜-{item.title}</h3>
                                <p>{item.content}</p>
                            </li>
                        )
                    })
                }
                </ul>

            </div>
        )
    }

    clickFn=(index,title,event)=>{
        alert((index+1)+"-clickFn-"+title)
    }
}

生命週期

生命週期便是組件從實例化到渲染到最終從頁面中銷燬,整個過程就是生命週期,在這生命週期中,咱們有許多能夠調用的事件,也俗稱爲鉤子函數

生命週期的3個狀態:

Mounting:將組件插入到DOM

Updating:將數據更新到DOM

Unmounting:將組件移除DOM

生命週期中的鉤子函數(方法,事件)

CompontWillMount :組件將要渲染,AJAX,添加動畫前的類

CompontDidMount:組件渲染完畢,添加動畫

compontWillReceiveProps:組件將要接受props數據,查看接收props的數據什麼

ShouldComponentUpdate:組件接收到新的state或者props,判斷是否更新。返回布爾值

CompontWillUpdate:組件將要更新

ComponentDidUpdate:組件已經更新

ComponentwillUnmount:組件將要卸載

React插槽

組建中寫入內容,這些內容能夠被識別和控制。React須要本身開發支持插槽功能。

原理:

組件中寫入的HTML,能夠傳入到props中。

組件中的HTML內容直接所有插入

組件中的HTML內容直接所有插入

class ParentCom extends React.Component{
    
    render(){
        console.log(this.props)
        return (
            <div>
                <h1>組件插槽</h1>
                {this.props.children}
            </div>
        )
    }
}

組件中根據HTML內容的不一樣,插入的位置不一樣。

import React from 'react';
import ReactDOM from 'react-dom';

class ParentCom extends React.Component{
    
    render(){
        console.log(this.props)
        return (
            <div>
                <h1>組件插槽</h1>
                {this.props.children}
                <ChildCom>
                    <h1 data-position="header">這是放置到頭部的內容</h1>
                    <h1 data-position="main">這是放置到主要的內容</h1>
                    <h1 data-position="footer">這是放置到尾部的內容</h1>
                </ChildCom>
            </div>
        )
    }
}

class ChildCom extends React.Component{
    render(){
        let headerCom,mainCom,footerCom;
        this.props.children.forEach((item,index)=>{
           if(item.props['data-position']==='header'){
            headerCom = item
           }else if(item.props['data-position']==='main'){
               mainCom = item
           }else{
               footerCom = item
           }
        })
        return (
            <div>
                <div className="header">
                    {headerCom}
                </div>
                <div className="main">
                    {mainCom}
                </div>
                <div className="footer">
                    {footerCom}
                </div>
            </div>
        )
    }
}

class RootCom extends React.Component{
    constructor(props){
        super(props)
        //console.log(props)
        this.state = {
            arr:[1,2,3]
        }
    }
    render(){
        return (
            <ParentCom>
                <h2 data-name="a" data-index={this.state.arr[0]}>子組件1</h2>
                <h2 data-name="b" data-index={this.state.arr[1]}>子組件2</h2>
                <h2 data-name="c" data-index={this.state.arr[2]}>子組件3</h2>
            </ParentCom>
        )
    }
}

ReactDOM.render(
    <RootCom></RootCom>
    ,
    document.querySelector("#root")
)

React 路由

根據不一樣的路徑,顯示不一樣的組件(內容);React使用的庫react-router-dom;

安裝

Cnpm install react-router-dom --save

ReactRouter三大組件:

Router:全部路由組件的根組件(底層組件),包裹路由規則的最外層容器。

屬性:basename->設置跟此路由根路徑,router能夠在1個組件中寫多個。

Route:路由規則匹配組件,顯示當前規則對應的組件

Link:路由跳轉的組件

注意:若是要精確匹配,那麼能夠在route上設置exact屬性。

Router使用案例

import React from 'react';
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/後端匹配使用
import {BrowserRouter as Router,Link,Route} from 'react-router-dom'

function Home(){
    return (
        <div>
            <h1>admini首頁</h1>
        </div>
    )
}

function Me(){
    return (
        <div>
            <h1>admin我的中心</h1>
        </div>
    )
}

function Product(){
    return (
        <div>
            <h1>admin產品頁面</h1>
        </div>
    )
}

class App extends React.Component{
    
    render(){
        return (
            <div id="app">
                {/* <div>全部頁面普通內容</div> */}
                <Router>
                    <Route path="/" exact component={()=>(<div>首頁</div>)}></Route>
                    <Route path="/me" component={()=>(<div>me</div>)}></Route>
                    <Route path="/product" component={()=>(<div>product</div>)}></Route>
                </Router>

                <Router>
                    {/* <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to="/me">我的中心</Link>
                    </div> */}
                    <Route path="/admin/" exact component={Home}></Route>
                    <Route path="/admin/product" component={Product}></Route>
                    <Route path="/admin/me" exact component={Me}></Route>
                </Router>
            </div>
        )
    }
}

export default App

Link組件能夠設置to屬性來進行頁面的跳轉,to屬性能夠直接寫路徑的字符串,也能夠經過1個對象,進行路徑的設置,如

render(){
        let meObj = {
            pathname:"/me",//跳轉的路徑
            search:"?username=admin",//get請求參數
            hash:"#abc",//設置的HASH值
            state:{msg:'helloworld'}//傳入組件的數據
        };
        return (
            <div id="app">
                

                <Router>
                    <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to={ meObj }>我的中心</Link>
                    </div>
                    <Route path="/" exact component={Home}></Route>
                    <Route path="/product" component={Product}></Route>
                    <Route path="/me" exact component={Me}></Route>
                </Router>
            </div>
        )
    }

Linkreplace屬性:點擊連接後,將新地址替換成歷史訪問記錄的原地址。

動態路由實現:

import React from 'react';
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/後端匹配使用
import {BrowserRouter as Router,Link,Route} from 'react-router-dom'

function Home(){
    return (
        <div>
            <h1>admini首頁</h1>
        </div>
    )
}

function Me(props){
    console.log(props)
    return (
        <div>
            <h1>admin我的中心</h1>
        </div>
    )
}

function Product(){
    return (
        <div>
            <h1>admin產品頁面</h1>
        </div>
    )
}

function News(props){
    console.log(props)
    return (
        <div>
            新聞頁,新聞id:{props.match.params.id}
        </div>
    )
}

class App extends React.Component{
    
    render(){
        let meObj = {
            pathname:"/me",//跳轉的路徑
            search:"?username=admin",//get請求參數
            hash:"#abc",//設置的HASH值
            state:{msg:'helloworld'}//傳入組件的數據
        };
        return (
            <div id="app">
                

                <Router>
                    <div className="nav">
                        <Link to="/">Home</Link>
                        <Link to="/product">Product</Link>
                        <Link to={ meObj }   replace>我的中心</Link>
                        <Link to="/news/4568789">新聞頁</Link>
                    </div>
                    <Route path="/" exact component={Home}></Route>
                    <Route path="/product" component={Product}></Route>
                    <Route path="/me" exact component={Me}></Route>
                    <Route path="/news/:id" component={News}></Route>
                </Router>
            </div>
        )
    }
}

export default App

重定向組件

若是訪問某個組件時,若是有重定向組件,那麼就會修改頁面路徑,使得頁面內容顯示爲所定向路徑的內容

用例:

function LoginInfo(props){
    //props.loginState = 'success';
    //props.loginState = "fail"
    console.log(props)
    if(props.location.state.loginState === 'success'){
        return <Redirect to="/admin"></Redirect>
    }else{
        return <Redirect to="/login"></Redirect>
    }
}

Switch組件

switch組件內容的route只匹配1個,只要匹配到了,剩餘的路由規則將再也不匹配

class App extends React.Component{
    render(){
        return (
            <div>
                <Router>
                    <Switch>
                        <Route path="/" exact  component={()=>(<h1>首頁</h1>)}></Route>
                        <Route path="/form" exact  component={FormCom}></Route>
                        <Route path="/login" exact  component={()=>(<h1>登陸頁</h1>)}></Route>
                        <Route path="/logininfo" exact component={LoginInfo}></Route>
                        <Route path="/admin" exact component={()=>(<h1>admin頁,登陸成功</h1>)}></Route>
                        <Route path="/abc" exact component={()=>(<h1>abc1頁,登陸成功</h1>)}></Route>
                        <Route path="/abc" exact component={()=>(<h1>abc2頁,登陸成功</h1>)}></Route>
                    </Switch>
                </Router>
            </div>
        )
    }
}

Redux

解決React數據管理(狀態管理),用於中大型,數據比較龐大,組件之間數據交互多的狀況下使用。若是你不知道是否須要使用Redux,那麼你就不須要用它!

* 解決組件的數據通訊。

* 解決數據和交互較多的應用

Redux只是一種狀態管理的解決方案!

Store:數據倉庫,保存數據的地方。

State:state1個對象,數據倉庫裏的全部數據都放到1state裏。

Action:1個動做,觸發數據改變的方法。

Dispatch:將動做觸發成方法

Reducer:1個函數,經過獲取動做,改變數據,生成1個新state。從而改變頁面

安裝

Cnpm install redux --save

初始化數據

//建立倉庫
const store = createStore(reducer)
//用於經過動做,建立新的state
//reduce有2個做用,1初始化數據,第二個就是經過獲取動做,改變數據
const reducer = function(state={num:0},action){
    console.log(action)
    switch(action.type){
        case "add":
            state.num++;
            break;
        case 'decrement':
            state.num--;
            break;
        default:
            break;
    }
    return {...state}//至關於對象的COPY
}

獲取數據

let state = store.getState()

修改數據(經過動做修改數據)

//經過倉庫的方法dispatch進行修改數據
store.dispatch({type:"add",content:{id:1,msg:"helloworld"}})

修改視圖(監聽數據的變化,從新渲染內容)

store.subscribe(()=>{
    ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
})

完整案例

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux'

//用於經過動做,建立新的state
const reducer = function(state={num:0},action){
    console.log(action)
    switch(action.type){
        case "add":
            state.num++;
            break;
        case 'decrement':
            state.num--;
            break;
        default:
            break;
    }
    return {...state}//至關於對象的COPY
}

//建立倉庫
const store = createStore(reducer)
console.log(store)


function add(){
    //經過倉庫的方法dispatch進行修改數據
    store.dispatch({type:"add",content:{id:1,msg:"helloworld"}})
    console.log(store.getState())
}
function decrement(){
    //經過倉庫的方法dispatch進行修改數據
    store.dispatch({type:"decrement"})
    console.log(store.getState())
}
//函數式計數器
const Counter = function(props){
    //console.log(store.getState())
    let state = store.getState()
    return (
        <div>
            <h1>計數數量:{state.num}</h1>

            <button onClick={add}>計數+1</button>
            <button onClick={decrement}>計數-1</button>
        </div>
    )

}

ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
store.subscribe(()=>{
    ReactDOM.render(<Counter></Counter>,document.querySelector("#root"))
})

React-redux

安裝

cnpm install react-redux --save

概念:

Provider組件:自動的將store裏的state和組件進行關聯。

MapStatetoProps:這個函數用於將storestate映射到組件的裏props

mapdispatchToProps:store中的dispatch映射到組件的props裏,實現了方法的共享。

Connect方法:將組件和數據(方法)進行鏈接

使用:

初始化數據,實例化store

function reducer(state={num:0},action){
    switch(action.type){
        case "add":
            state.num++;
            break;
        default:
            break;
    }
    return {...state}
}

const store = createStore(reducer)

數據的獲取,數據的修改

state映射到到組件的props中,將修改數據的方法映射到組件的props

完整案例

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore} from 'redux';
import {connect, Provider} from 'react-redux'

class Counter extends React.Component{
    
    render(){
        console.log(this.props)
        //計數,經過stroe的state傳給props,直接經過props就能夠將state的數據獲取
        const value = this.props.value;
        //將修改數據的事件或者方法傳入到props
        const onAddClick = this.props.onAddClick;
        //等同於vuex的mapMutation mapState
        return (
            <div>
                <h1>計數的數量:{value}</h1>
                <button onClick={onAddClick}>數字+1</button>
                <button onClick={this.props.onAddClick5}>數字+5</button>
            </div>
        )


    }
}



let ActionFnObj={
    add:function(state,action){
        state.num++
        return state
    },
    addNum:function(state,action){
        
        state.num = state.num + action.num;
        return state
    }
}
function reducer(state={num:0},action){
    if(action.type.indexOf('redux')===-1){
        state = ActionFnObj[action.type](state,action)
        return {...state}
    }else{
        return state;
    }
    
    
}

const store = createStore(reducer)

//將state映射到props函數
function mapStateToProps(state){
    return {
        value:state.num
        
    }
}

const addAction = {
    type:'add'
}
//將修改state數據的方法,映射到props,默認會傳入store裏的dispach方法
function mapDispatchToProps(dispatch){
    return {
        onAddClick:()=>{dispatch(addAction)},
        onAddClick5:()=>{dispatch({type:"addNum",num:5})}
    }
}

//將上面的這2個方法,將數據倉庫的state和修改state的方法映射到組件上,造成新的組件。
const App = connect(
    mapStateToProps,
    mapDispatchToProps
)(Counter)

ReactDOM.render(
    <Provider store={store}>
        <App></App>
    </Provider>,
    document.querySelector("#root")
)

Ant 螞蟻框架

npm install antd-mobile --save

按須要導入(自動導入用到的css樣式):

  1. 安裝插件
npm install  babel-plugin-import --save

2.配置

npm run eject

3.Packjson文件

"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["import", { "libraryName": "antd-mobile", "style": "css" }]
    ]
  }

其他參考官網

相關文章
相關標籤/搜索