1. 程式人生 > >React路由學習(六)

React路由學習(六)

我們再處理表單的時候,有時候會不小心點選別的連結,或者使用者放棄繼續註冊,我們可以再跳轉的時候提示使用者,是否需要跳轉,等使用者確認以後再跳轉,如果使用者沒有確認,就繼續停留再當前頁面,阻止跳轉

Prompt元件

使用方式,這個元件支援兩個引數。when:是否需要阻止跳轉,message:提示使用者的時候的提示語

實現思路:

1.再路由新建一個屬性(block),用來儲存是否需要提示跳轉的狀態

2.我們改變路由之前加一個判斷,如果block屬性不為空,則阻止跳轉,並彈出提示框

3.使用者點選取消,則不做任何操作,使用者點選確認,進入下一步

4.再當前元件銷燬之前重置block為null,然後push新的路由

呼叫程式碼

// 引入元件
import {Prompt} from '../react-router-dom'

// 呼叫 
// 下邊的例子,我們再inputchangge的時候設定為需要阻止跳轉
 <Prompt 
    when={this.state.isBlocking}
    message= {
        loc => `請問你是否確定要切換到${loc.pathname}路徑`
    }
/>
<div className="form-group">
    <label
htmlFor="username">
使用者名稱:</label> <input ref={input => this.username = input} type="text" className="form-control" id="username" onChange={() => this.setState({isBlocking: true})}/> </div>

Prompt元件實現

在react-router-dom下新建檔案Prompt.js,檔案內容如下

import React, {Component} from 'react'
; import {Consumer} from './context' {/* <Prompt when={this.state.isBlocking} message= { loc => `請問你是否確定要切換到${loc.pathname}路徑` } /> */} // when 判斷是否需要組織跳轉 // message 阻止跳轉時的提示語 export default class Prompt extends Component{ componentWillUnmount () { // 再元件解除安裝之前清空狀態 this.history.unblock() } render () { return ( // 使用上下文拿到location物件 <Consumer> { value => { // 將history物件掛載到當前物件上,方便在元件解除安裝的時候清空狀態 this.history = value.history // 解構引數 let {when, message} = this.props console.log(when, message) // 如果存在when引數,則進行阻攔,不存在,就清空之前的狀態 if (when) { value.history.block(message) } else { value.history.unblock() } } } </Consumer> ) } } // 元件複用的策略 // 高階元件 // 函式作為子元件

HashRouter.js檔案修改

1.新增block方法,儲存阻止跳轉的狀態和提示語

2.新增unblock方法,清空狀態為預設

3.在push新路由的時候判斷block是否需要提示

import React, {Component} from 'react';
import {Provider} from './context'
// 每當位址列裡的錨點發生改變的時候都需要重新匹配
export default class HashRouter extends Component{
    state = {
        location: {
            pathname: window.location.hash ?  window.location.hash.slice(1) : '/'
        }
    }
    /**
     * 元件掛載完成
     */
    componentDidMount () {
        /**
         * 監聽hashchange 事件,重新整理頁面
         */
        window.addEventListener('hashchange', () => {
            this.setState({
                location: {
                    ...this.state.location,
                    // 更新錨點
                    pathname: window.location.hash ?  window.location.hash.slice(1) : '/'
                }
            })
        })
    }
    /**
     * 渲染
     */
    render () {
        // Provider 進行跨元件訊息傳遞
        // 通過value屬性傳值
        let _self = this
        let value = {
            location: _self.state.location,
            // Link元件動態修改hash
            history: {
                push (to) {
                    /**
                    * 阻止跳轉新增
                    */
                    // 這裡新增判斷,看是否需要阻擋跳轉
                    if (_self.block) {
                        // 將to轉換為一個物件
                        to = typeof to === 'object' ? to : {pathname: to}
                        let ok = window.confirm(_self.block(to))
                        // 如果返回值為false,就直接返回
                        if (!ok) return null;
                    }
                    // console.log('to', to)
                    if (typeof to === 'object') {
                        let {pathname, state} = to
                        _self.setState({
                            ..._self.state,
                            // 重新解構賦值
                            location: {
                                // 原始的location
                                ..._self.state.location,
                                // 使用新的路徑覆蓋
                                pathname,
                                state
                            }
                        })
                        window.location.hash = pathname
                    } else {
                        window.location.hash = to
                    }
                },
                /**
                * 阻止跳轉新增
                */
                /**
                 * 
                 * @param {string} msg 傳遞過來的提示語 
                 */
                block (msg) {
                    _self.block = msg
                },
                /**
                * 阻止跳轉新增
                */
                unblock () {
                    _self.block = null
                }
            },
            goback () {
                window.history.go(-1)
            }
        }
        // 返回this.props.children
        // 具體路由判斷的規則在children元件進行處理
        return(
            <Provider value={value}>
               {this.props.children}
            </Provider>
        )
    }
}

結束語

因為已經寫了好多了,關於在react-router-dom目錄下index.js匯出該元件的程式碼就不寫了。就是複製貼上,到目前位置也完成了router組建的基本功能,算是對路由有了一定的認識…..為自己的進步加油

傳送門 貼上完整程式碼