React路由學習(六)
阿新 • • 發佈:2018-12-09
我們再處理表單的時候,有時候會不小心點選別的連結,或者使用者放棄繼續註冊,我們可以再跳轉的時候提示使用者,是否需要跳轉,等使用者確認以後再跳轉,如果使用者沒有確認,就繼續停留再當前頁面,阻止跳轉
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組建的基本功能,算是對路由有了一定的認識…..為自己的進步加油