天天看點

十六、React 渲染資料注意事項、以及react-router4.x中使用js跳轉路由(登入成功自動跳轉首頁)一、React加載資料流程回顧二、react-router中用js跳轉路由

一、React加載資料流程回顧

先看上一節的産品詳情代碼:https://blog.csdn.net/u010132177/article/details/103184176

【Pcontent.js】

import React, { Component } from 'react';
import axios from 'axios';
import '../css/pcontent.css';
import '../css/basic.css';
import {Link} from 'react-router-dom';

class Pcontent extends Component {
    constructor(props){
        super(props);
        this.state={
          detail_list:[], //此處要注意格式,如果Api是字典,就要設定成 {}
          domain:'http://a.itying.com/'
        }
    }
	
	//【1】此處和上節稍有差別:把接口擷取單獨寫成一個函數
    requestData(id){
        var api=this.state.domain+'api/productcontent?id='+id;
        axios.get(api)
        .then((response)=>{         
             console.log(response);
            this.setState({
               list:response.data.result[0]
            })
        })
        .catch(function (error) {         
          console.log(error);
        })
    }

	//【2】在生命周期函數内調用擷取api接口資料函數
    componentDidMount(){
        //id
        console.log(this.props.match.params.id)
        let id=this.props.match.params.id;
        this.requestData(id);
    }
    
    render() {
      return (
        <div className='pcontent'>
            <div className="back"><Link to='/'>傳回</Link></div>
		
		<div className="p_content">		
			<div className="p_info">				
				<img alt={this.state.detail_list.title} src={`${this.state.domain}${this.state.detail_list.img_url}`}/>				
				<h2>{this.state.detail_list.title}</h2>				
				<p className="price">{this.state.detail_list.price}元</p>
			</div>
			<div className="p_detial">
				<h3>
					商品詳情					
				</h3>
       			 {/*html解析寫法*/}
				<div className="p_content"  dangerouslySetInnerHTML={{__html: this.state.detail_list.content}}>                      
        </div>
			</div>
		</div>
		
		<footer className="pfooter">		
			<div className="cart">				
				<strong>數量:</strong>
				<div className="cart_num">
		          <div className="input_left">-</div>
		          <div className="input_center">
		              <input type="text"  readOnly="readonly" value="1" name="num" id="num" />
		          </div>
		          <div className="input_right">+</div>				      
		        </div>										
			</div>			
			<button className="addcart">加入購物車</button>			
		</footer>
        </div>
      );
    }
  }
  export default Pcontent;
           

控制台:産品詳情頁get 404 undefined錯誤原因

上一節加載詳情時,控制台将發現會報錯:

GET http://a.itying.com/undefined 404 (Not Found) undefined
           

【原因】:

  • 分析源碼發現,隻有圖檔才會發起一個get請求
  • 這涉及到之前講的生命同期函數加載順序問題順序:
    1. 先:componentWillMount(){}
    2. 再:render(){}
    3. 再:componentDidMount(){}
    4. 再:render(){} 一次
  • 原來,我們把擷取Api資料放在第 3 步裡,當第一次render(){}渲染時,Api資料還沒擷取到,是以會出現報錯

    當第2次render之後,資料已擷取,是以就能正常加載圖檔了。

  • 那麼:放在willmount()裡呢,一樣拿不到,原因是,willmount可能會加載非常快

解決:

隻要把圖檔加個判斷,有圖檔,加載,沒——渲染成空,寫成這樣即可:

此處文法三目:條件 ? true :false

為什麼在清單那裡圖檔【home.js】就不會有404呢

原因:

  • 清單頁用的是this.state.list.map函數,它首先會判斷list是否有資料,有才會渲染圖檔
  • 沒資料,不會渲染圖檔,也就不會有get 請求,也不會有404了
this.state.list.map((value,key)=>{
...
<img alt={v.title} src={`${this.state.domain}${v.img_url}`} />
           

二、react-router中用js跳轉路由

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

  1. 要引入Redirect:
  1. 定義一個flag
  1. render裡面判斷flag 來決定是否跳轉:
if(this.state.loginFlag){
    return <Redirect to={{ pathname: "/" }} />;
}
           
  1. 要執行js跳轉:

    - 通過js改變loginFlag的狀态

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

代碼示例

第1步:在首頁加入登入按鈕[home.js]

重點:

import {Link} from 'react-router-dom';
<Link to='Login'>登陸網站</Link>
           

【Home.js】

import React,{Component} from 'react';
import {Link} from 'react-router-dom';
import '../css/index.css';
import axios from 'axios'; //也可寫成:const axios = require('axios');

class Home extends Component{
    constructor(props){
        super(props);
        this.state={
            list:[],
            domain:'http://a.itying.com/'
        }
    }

    //擷取Api接口的資料
    getDataApi=()=>{
        //拼裝得到完整的Api接口連結
        var api=this.state.domain+"api/productlist";
        axios.get(api)
        .then((response)=>{
            console.log(response);
            this.setState({
                list:response.data.result
            })
        })
        .catch(function(error){
            console.log(error);
        })
    }

    //生周函數:頁面渲染完成後加載
    componentDidMount(){
        //調用函數得到api接口資料
        this.getDataApi();
    }
    
    render(){
        return(
        <div>
        	{/*★★★本頁面新加登陸按鈕*/}
            <Link to='Login'>登陸網站</Link>
            <header className="index_header">	
                <div className="hlist">
                    <img alt='熱銷榜' src={require('../images/rexiao.png')} />
                    <p>熱銷榜</p>				
                </div>
                
                <div className="hlist">
                    <img alt='點過的菜' src={require('../images/caidan.png')} />
                    <p>點過的菜</p>				
                </div>
                <div className="hlist">		
                    <img alt='猜你喜歡' src={require('../images/sousuo.png')} />
                    <p>猜你喜歡</p>				
                </div>			
            </header>

            <div className="content">
                {
                this.state.list.map((value,key)=>{
                    return(
                        <div className="item" key={key}>
                        <h3 className="item_cate">{value.title}</h3>
                        <ul className="item_list">
                        {
                        value.list.map((v,k)=>{
                            return(
                                <li key={k}>	
                                <div className="inner">
                                    <Link to={`/Pcontent/${v._id}`}>
                                    <img alt={v.title} src={`${this.state.domain}${v.img_url}`} />
                                    </Link>
                                    <p className="title">{v.title}</p>						
                                    <p className="price">{v.price}元</p>
                                </div>		
                            </li>
                            )
                        })
                        }
                            
                        </ul>
                    </div>
                    )
                })
                }  
            </div>		
            
        </div>
        )
    }
}
export default Home;
           

第2步:login.js

重點:【1-5】

import React, { Component } from 'react';
import {
    BrowserRouter as Router,
    Redirect,  //【1】引入Redirect
    } from "react-router-dom";

class Login extends Component {
    constructor(props){
        super(props);       
        this.state={
          loginFlag:false //【2】設定登入标志
        }
    }

    //【4】登入函數
    login=(e)=>{
        e.preventDefault(); //阻止submit預設有個重新整理的動作
        let username=this.refs.username.value; //擷取使用者登入的使用者名
        let pwd=this.refs.pwd.value; //擷取使用者輸入的密碼
        console.log(username,pwd)
        if(username=='admin' && pwd=='admin'){ //如果使用者名、密碼都正确,把登入标志成 ture。
            this.setState({loginFlag:true})
        }else{alert('登入失敗')}
    }

    render() {
        //【5】判斷登入标志是否是ture,是就跳轉到首頁
        if(this.state.loginFlag){
            return <Redirect to='/' />;
        }
      return (
        <div>
            {/* 【3】登入表單,此處用ref擷取值 */}
            <form onSubmit={this.login}>
                <input type='input' ref='username' /><br/>
                <input type='password' ref='pwd' /><br/>
                <input type='submit' value='登入' />
            </form>
        </div>
      );
    }
  }
  export default Login;
           

第3步:App頁面把login.js加到路由裡

import React from 'react';
//import './App.css';
import { BrowserRouter as Router, Route } from 'react-router-dom'; //引入路由子產品
import Home from './components/Home';
import Pcontent from './components/Pcontent';
import Login from './components/Login';

function App() {
  return (
    <Router>
      <div>           
        <Route exact path="/" component={Home} />
        <Route path="/Pcontent/:_id" component={Pcontent} />
        {/*★★★把登入路由加到此處*/}
        <Route path="/Login" component={Login} />
      </div>
    </Router>
  );
}
export default App;
           

最後,效果:

  1. 在Home點登入,會跳轉到Login頁面:登入網站
  2. 登入頁面輸入:admin,admin後,将自動跳轉到首頁,輸入其它彈出登入失敗
    十六、React 渲染資料注意事項、以及react-router4.x中使用js跳轉路由(登入成功自動跳轉首頁)一、React加載資料流程回顧二、react-router中用js跳轉路由