天天看點

React知識點總結1、安裝2、建立項目:3、目錄結構分析4、代碼編寫

1、安裝

1、必須安裝nodejs穩定版本,exe直接安裝即可,安裝完既有npm;

2、安裝cnpm/yarn淘寶鏡像:

npm install -g cnpm --registry=https://registry.npm.taobao.org
 cnpm install -g yarn           

3、安裝vscode;

2、建立項目:

1、安裝腳手架:

cnpm install -g create-react-app           

2、cd進入想要建立項目的目錄,建立項目:

create-react-app reactdemo           

3、運作項目:

cnpm start /yarn start           

4、生成項目: 

cnpm run build  /  yarn build           

3、目錄結構分析

1、node_modules:安裝子產品目錄

2、public:公共目錄,一般無需修改,裡面有index.html入口檔案;

3、重點關注src目錄!

 3.1、index.js:react入口檔案,React是react核心庫,ReactDOM是提供與DOM相關的功能;

 3.2、index.css:react項目公共css,可以删掉;

 3.3、registerServiceWorker.js  加快react運作速度的js檔案;

 3.3、App.js 組建

4、項目配置檔案:package.json

5、yarn.lock yarn臨時檔案,不用管;

預設生成的結構比較亂,可手動整理目錄結構:

1、建立components組建檔案夾,用于存放組建,組建名稱首字母大寫!

2、建立assets檔案夾,用于存放靜态檔案;

  2.1、建立assets/image檔案夾,放圖檔;

  2.2、建立assets/css檔案夾,放靜态檔案;

4、代碼編寫

1、引入組建,無需寫字尾名js:

import Home from './components/Home'           

快速建構組建架構代碼:

1、在vscode應用商店中安裝插件 :

     React-Native/React/Redux snippets for es6/es7

2、在vscode中輸入cccs,按enter即可;

2、資料定義,寫在構造函數裡面:

import React from 'react'
 class Home extends React.Component{
  constructor(props){
   super(props);  //固定寫法,用于父子組建傳值;
   this.state={
    name:"111",
    age:'20'
   }
  }
  render(){
   return(
    <div>
     name:{this.state.name}  //引用資料;
    </div>
   )
  }
 }           

3、綁定css屬性用

   class--->className

   for---->htmlFor

   style屬性和以前的寫法有些不一樣:

<div style={{'color':'blue'}}>{this.state.title}</div>
<div style={{'color':this.state.color}}>{this.state.title}</div>           

4、引入圖檔,要用子產品化方式

    法1:

import image1 from '../assets/image/1.jpg'
 <img src={image1}/>           

 法2:

<img src = {require('../assets/image/1.jpg')}/>           

引入遠端圖檔,直接src寫位址即可;

5、寫事件

run=()=> {
     alert(this.state.name)
   }
 <button onClick={this.run}>按鈕</button>
 事件傳值:
  <button onClick={this.setName.bind(this,'張三')}>執行方法傳值</button>
 
  setName=(str)=>{
        this.setState({
            username:str
        })
    }           

6、事件對象

<button aid="123" onClick={this.run}>事件對象</button>
  run=(event)=>{
        event.target.style.background='red';
        alert(event.target.getAttribute('aid'))//擷取dom的屬性
    }           

7、表單事件

 法1:

{/* 擷取表單的值   
    1、監聽表單的改變事件                        onChange
   2、在改變的事件裡面擷取表單輸入的值           事件對象
   3、把表單輸入的值指派給username              this.setState({})
   4、點選按鈕的時候擷取 state裡面的username     this.state.username
 */}
  <input onChange={this.inputChange}/>
  <button onClick={this.getInput}>擷取input的值</button>
  
  inputChange=(e)=>{
   this.setState({
    username:e.target.value
   })
  }

 getInput=()=>{
   alert(this.state.username);
  }


           

  法2:

{/* 擷取表單的值   
    1、監聽表單的改變事件                        onChange
   2、在改變的事件裡面擷取表單輸入的值            ref擷取
   3、把表單輸入的值指派給username              this.setState({})
   4、點選按鈕的時候擷取 state裡面的username     this.state.username
    */}
   <input ref="username" onChange={this.inputChange}/>
   <button onClick={this.getInput}>擷取input的值</button>
   
   
    inputChange=()=>{
    let val=this.refs.username.value;
    this.setState({
     username:val
    })
   }
   getInput=()=>{
    alert(this.state.username);
   }
   
           

8、鍵盤事件

<input onKeyUp={this.inputKeyUp}/>
 //鍵盤事件
    inputKeyUp=(e)=>{
        if(e.keyCode==13){
            alert(e.target.value);
        }
    }           

9、限制性和非限制性元件

限制性和非限制性元件:

非限制性元件:

<input type="text" defaultValue="a" />   這個 defaultValue 其實就是原生DOM中的 value 屬性。

 這樣寫出的來的元件,其value值就是使用者輸入的内容,React完全不管理輸入的過程。

限制性元件:

<input value={this.state.username} type="text" onChange={this.handleUsername}  />

   這裡,value屬性不再是一個寫死的值,他是 this.state.username, this.state.username 是由 this.handleChange 負責管理的。

   這個時候實際上 input 的 value 根本不是使用者輸入的内容。而是onChange 事件觸發之後,由于 this.setState 導緻了一次重新渲染。不過React會優化這個渲染過程。看上去有點類似雙向資料綁定

10、資料持久化

//執行緩存資料
localStorage.setItem('todolist',JSON.stringify(tempList));


//擷取緩存的資料

var todolist=JSON.parse(localStorage.getItem('todolist'));   /*字元串*/
           

11、React的子產品化封裝Storage

建立檔案夾model,存放自定義子產品,建立model/storage.js子產品:

var storage={


    set(key,value){

        localStorage.setItem(key,JSON.stringify(value));
    },
    get(key){

        return JSON.parse(localStorage.getItem(key));

    },remove(key){

        localStorage.removeItem(key)
    }
};

export default storage;
           

引用:

//引入自定義子產品
import storage from '../model/storage';

 //執行緩存資料           
storage.set('todolist',tempList);


 //擷取緩存的資料
var todolist=storage.get('todolist');  
           

11、React中父子組建傳值

React中的元件: 解決html 标簽建構應用的不足。

使用元件的好處:把公共的功能單獨抽離成一個檔案作為一個元件,哪裡裡使用哪裡引入。

父子元件:元件的互相調用中,我們把調用者稱為父元件,被調用者稱為子元件

父元件給子元件傳值

      1.在調用子元件的時候定義一個屬性  <Header msg='首頁'></Header>

      2.子元件裡面 this.props.msg         

說明:父元件不僅可以給子元件傳值,還可以給子元件傳方法,以及把整個父元件傳給子元件。

父元件主動擷取子元件的資料

        1、調用子元件的時候指定ref的值   <Header ref='header'></Header>     

        2、通過this.refs.header  擷取整個子元件執行個體

12、預設值和類型檢驗

defaultProps:父子元件傳值中,如果父元件調用子元件的時候不給子元件傳值,可以在子元件中使用defaultProps定義的預設值

    propTypes:驗證父元件傳值的類型合法性

            1、引入import PropTypes from 'prop-types';

            2、類.propTypes = {

                name: PropTypes.string

            };

都是定義在子元件裡面

//defaultProps   如果父元件調用子元件的時候不給子元件傳值,可以在子元件中使用defaultProps定義的預設值
Header.defaultProps={

    title:'标題'
}

//同行propTypes定義父元件給子元件傳值的類型

Header.propTypes={

    num:PropTypes.number
}           

13、擷取資料

react擷取伺服器APi接口的資料:

react中沒有提供專門的請求資料的子產品。但是我們可以使用任何第三方請求資料子產品實作請求資料

1、axios          https://github.com/axios/axios  

 axios的作者覺得jsonp不太友好,推薦用CORS方式更為幹淨(後端運作跨域)

 1、安裝axios子產品npm install axios  --save   /  npm install axios  --save

 2、在哪裡使用就在哪裡引入import axios from 'axios'

 3、看文檔使用

var api='http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20';

            axios.get(api)

            .then(function (response) {

                console.log(response);

            })

            .catch(function (error) {

                console.log(error);

            });

import React, { Component } from 'react';


import axios from 'axios';

class Axios extends Component {
    constructor(props) {
        super(props);
        this.state = { 

            list:[]
         };
    }

    getData=()=>{


        //通過axios擷取伺服器資料

        var api='http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20';   //接口背景允許了跨域

        axios.get(api)
        .then((response)=> {
            console.log(response.data.result);

            //用到this要注意this指向
            this.setState({

                list:response.data.result

            })
        })
        .catch(function (error) {
            console.log(error);
        });


    }
    render() {
        return (

            <div>
                <h2>axios擷取伺服器資料</h2>
                <button onClick={this.getData}>擷取伺服器api接口資料</button>
                <hr />
                <ul>
                    {
                        this.state.list.map((value,key)=>{
                            return <li key={key}>{value.title}</li>
                        })
                    }   
                </ul>
            </div>
        );
    }
}

export default Axios;           

2、fetch-jsonp    https://github.com/camsong/fetch-jsonp

1、安裝 npm install fetch-jsonp  --save

2、import fetchJsonp from 'fetch-jsonp'

3、看文檔使用

            fetchJsonp('/users.jsonp')

            .then(function(response) {

              return response.json()

            }).then(function(json) {

              console.log('parsed json', json)

            }).catch(function(ex) {

              console.log('parsing failed', ex)

            })

import React, { Component } from 'react';
import fetchJsonp from 'fetch-jsonp';

class FetchJsonp extends Component {
    constructor(props) {
        super(props);
        this.state = {

            list:[]
        };
    }

    getData=()=>{

         //擷取資料

        var api="http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20";
        fetchJsonp(api)
        .then(function(response) {
            return response.json()
        }).then((json)=> {
            // console.log(json);
            
            this.setState({

                list:json.result
            })

        }).catch(function(ex) {
            console.log('parsing failed', ex)
        })
    }
    render() {
        return (
            <div>
                <h2>FetchJsonp 擷取伺服器jsonp接口的資料</h2>
                <button onClick={this.getData}>擷取伺服器api接口資料</button>
                <hr />
                <ul>
                    {
                        this.state.list.map((value,key)=>{
                            return <li key={key}>{value.title}</li>
                        })
                    }                       
                </ul>
            </div>  
        );
    }
}

export default FetchJsonp;           

3、其他請求資料的方法也可以...自己封裝子產品用原生js實作資料請求也可以...

14、生命周期函數

React生命周期函數:

    元件加載之前,元件加載完成,以及元件更新資料,元件銷毀。

    觸發的一系列的方法 ,這就是元件的生命周期函數

元件加載的時候觸發的函數:

    constructor 、componentWillMount、 render 、componentDidMount

元件資料更新的時候觸發的生命周期函數:

    shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate

你在父元件裡面改變props傳值的時候觸發的:

    componentWillReceiveProps

元件銷毀的時候觸發的:

    componentWillUnmount

必須記住的生命周期函數:

   *加載的時候:componentWillMount、 render 、componentDidMount(dom操作)

    更新的時候:componentWillUpdate、render、componentDidUpdate

    *銷毀的時候: componentWillUnmount

15、路由配置

/*
  react路由的配置:
    1、找到官方文檔 https://reacttraining.com/react-router/web/example/basic

    2、安裝  cnpm install react-router-dom --save


    3、找到項目的根元件引入react-router-dom

       import { BrowserRouter as Router, Route, Link } from "react-router-dom";

    4、複制官網文檔根元件裡面的内容進行修改  (加載的元件要提前引入)


         <Router>

                <Link to="/">首頁</Link>

                <Link to="/news">新聞</Link>

                <Link to="/product">商品</Link>


               <Route exact path="/" component={Home} />
               <Route path="/news" component={News} />    
               <Route path="/product" component={Product} />   
         </Router>


         exact表示嚴格比對


react動态路由傳值

      1、動态路由配置

          <Route path="/content/:aid" component={Content} />   

      2、對應的動态路由加載的元件裡面擷取傳值

            this.props.match.params.aid


      跳轉:<Link to={`/content/${value.aid}`}>{value.title}</Link>

react get傳值  
    
      1、路由配置
            <Route path="/productcontent" component={ProductContent} />
      
      2、擷取 this.props.location.search,其值為: ?aid=4

         然後使用url子產品解析字元串,安裝  cnpm install url --save
            import url from 'url'
            var aid = url.parse(this.props.location.search,true).query.aid

      跳轉:<Link to={`/productcontent/?aid=${value.aid}`}>{value.title}</Link>
         
*/

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

import './assets/css/index.css'

import Home from './components/Home';
import News from './components/News';
import Product from './components/Product';
import Content from './components/Content';

import ProductContent from './components/ProductContent';

class App extends Component {

  render() {
    return (
        <Router>
          <div>           

              <header className="title">
              
                <Link to="/">首頁</Link>

                <Link to="/news">新聞</Link>

                <Link to={`/productcontent/?aid=${value.aid}`}>{value.title}</Link>

              </header>


               <br />
               <hr />
      
               <br />
      
      
              <Route exact path="/" component={Home} />
              <Route path="/news" component={News} />    
              <Route path="/product" component={Product} /> 
              <Route path="/productcontent" component={ProductContent} />

              <Route path="/content/:aid" component={Content} />                 
          </div>
      </Router>
    );
  }
}

export default App;
           

16、react-router4.x中使用js跳轉路由

/*

實作js跳轉路由:https://reacttraining.com/react-router/web/example/auth-workflow

1、要引入Redirect

    import {
    BrowserRouter as Router,
    Route,
    Link,
    Redirect,
    withRouter
    } from "react-router-dom";

2、定義一個flag
        this.state = { 
                loginFlag:false            
        };

3、render裡面判斷flag 來決定是否跳轉

        if(this.state.loginFlag){

            return <Redirect to={{ pathname: "/" }} />;
        }

4、要執行js跳轉

        通過js改變loginFlag的狀态

        改變以後從新render 就可以通過Redirect自己來跳轉


*/

import React, { Component } from 'react';

import {Redirect} from "react-router-dom";


class Login extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            loginFlag:false            
        };
    }

    doLogin=(e)=>{

        e.preventDefault();
        

        let username=this.refs.username.value;

        let password=this.refs.password.value;


        console.log(username,password)

        if(username=='admin' && password=='123456'){

            //登入成功   跳轉到首頁

            this.setState({

                loginFlag:true
            })



        }else{

            alert('登入失敗')
        }

    }
    render() {


        if(this.state.loginFlag){

            // return <Redirect to={{ pathname: "/" }} />;

            return <Redirect to='/' />;
        }
        return (    


            <div>
                 <br /> <br /> <br />

                <form onSubmit={this.doLogin}>

                        <input type="text"  ref="username" />  <br /> <br />

                        <input type="password"  ref="password" /> <br /> <br />

                         <input type="submit"  value="執行登入"/>

                </form>

               

            </div>
            
        );
    }
}

export default Login;           

17、路由的嵌套

import React, { Component } from 'react';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";


import Info from './User/Info';
import Main from './User/Main';

class User extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            msg:'我是一個User元件'
         };
    }    
    render() {
        return (
            <div className="user">
               

               <div className="content">


                   <div className="left">

                        <Link to="/user/">個人中心</Link>

                        <br />
                        <br />

                        <Link to="/user/info">使用者資訊</Link>


                    </div>

                    <div className="right">

                            
                            <Route exact path="/user/" component={Main} />

                            <Route  path="/user/info" component={Info} />

                    </div>


               </div>


            </div>
        );
    }
}

export default User;
           

18、路由子產品化代碼分離

建立model/router.js檔案:

import Home from '../components/Home';
import User from '../components/User';
import Shop from '../components/Shop';
import News from '../components/News';


let routes = [
    {
      path: "/",
      component: Home,
      exact:true
    },
    {
      path: "/shop",
      component: Shop
    },
    {
      path: "/user",
      component: User
    },
    {
      path: "/news",
      component: News
    }
];

export default routes;           

App.js中聲明路由:

import React, { Component } from 'react';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";


import './assets/css/index.css';

import routes from './model/router.js';

class App extends Component {

  render() {
    return (

      <Router>
        <div>
            <header className="title">

                <Link to="/">首頁元件</Link>
                <Link to="/user">使用者頁面</Link>
                <Link to="/shop">商戶</Link>
                <Link to="/news">新聞</Link>
            </header> 

            {
              routes.map((route,key)=>{

                  if(route.exact){

                    return <Route key={key} exact path={route.path} component={route.component}/>
                  }else{
                    return <Route  key={key}  path={route.path} component={route.component}/>

                  }
              })
            }            
         
        </div>
      </Router>
    );
  }
}

export default App;
           

19、路由子產品化嵌套路由

import Home from '../components/Home';
import User from '../components/User';
    import UserList from '../components/User/UserList';
    import UserAdd from '../components/User/UserAdd';
    import UserEdit from '../components/User/UserEdit';
import Shop from '../components/Shop';
import News from '../components/News';


let routes = [
    {
      path: "/",
      component: Home,
      exact:true
    },
    {
      path: "/shop",
      component: Shop
    },
    {
      path: "/user",
      component: User,  
      routes:[   /*嵌套路由*/
        {
          path: "/user/",
          component: UserList
        },
        {
          path: "/user/add",
          component: UserAdd
        },
        {
          path: "/user/edit",
          component: UserEdit
        }
      ]
    },
    {
      path: "/news",
      component: News
    }
];

export default routes;           

App.js,給嵌套路由傳遞路由參數:

import React, { Component } from 'react';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

import './assets/css/index.css';

import routes from './model/router.js';

class App extends Component {

  render() {
    return (

      <Router>
        <div>
            <header className="title">

                <Link to="/">首頁元件</Link>
                <Link to="/user">使用者頁面</Link>
                <Link to="/shop">商戶</Link>
                <Link to="/news">新聞</Link>
            </header> 


            {
              routes.map((route,key)=>{

                  if(route.exact){

                    return <Route key={key} exact path={route.path}                     

                    // route.component     value.component   <User  {...props}  routes={route.routes} />

                    render={props => (
                      // pass the sub-routes down to keep nesting
                      <route.component {...props} routes={route.routes} />
                    )}

                    />
                  }else{
                    return <Route  key={key}  path={route.path} 
                    render={props => (
                      // pass the sub-routes down to keep nesting
                      <route.component {...props} routes={route.routes} />
                    )}
                    />

                  }
              })
            }            
          
         
        </div>
      </Router>
    );
  }
}

export default App;
           

User.js根據傳遞的路由參數實作路由:

import React, { Component } from 'react';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

class User extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            msg:'我是一個User元件'
         };
    }
    componentWillMount(){

        console.log(this.props.routes);
    }
    render() {
        return (
            <div className="user">               
               
               <div className="content">

                    <div className="left">

                        <Link to="/user/">使用者清單</Link>

                        <br />
                        <br />

                        <Link to="/user/add">增加使用者</Link>


                         <br />
                        <br />

                        <Link to="/user/edit">編輯使用者</Link>

                    </div>

                    <div className="right">
                            {

                                this.props.routes.map((route,key)=>{

                                     return   <Route key={key} exact path={route.path} component={route.component} />
                                })
                            }

                            {/* <Route  path="/user/add" component={UserAdd} /> */}

                    </div>

                    </div>

            </div>
        );
    }
}
export default User;           

繼續閱讀