queryString (查詢字符串)
通常我們把 URL `?` 後面的內容稱爲 queryString,在 React.js 中,我們可以通過 `this.props.location.search` 來獲取,它的值是字符串,
格式爲:?k1=v1&k2=v2,爲了方便操作,我們把它轉成對象形式
URLSearchParams
在原生 JJavaScript 中內置了一個 URLSearchParams 的類,我們通過它可以很方便的操作 queryString
js原生方法
或者可以用qs 庫,效果同原生
https://www.npmjs.com/package/qs
安裝
npm i -S qs
使用
import queryString from 'qs';
let qsTest = queryString.parse(search, {ignoreQueryPrefix: true});
let sort = qsTest.sort;
通過 JavaScript 編程的方式切換路由
除了使用 \<Link\> 組件像 a 一樣點擊跳轉路由,我們還可以通過編程的方式(JavaScript) 來切換路由
應用場景(四)
現在,我想給頁面頂部的導航加上高亮效果,用來標識當前頁面。這個時候,我們就可以使用 react-router-dom 提供的 NavLink
組件來實現
NavLink 組件
NavLink 與 Link 類似,但是它提供了兩個特殊屬性用來處理頁面導航
activeStyle
噹噹前 URL 與 NavLink 中的 to 匹配的時候,激活 activeStyle 中的樣式
activeClassName
與 activeStyle 類似,但是激活的是 className
isActive
默認情況下,匹配的是 URL 與 to 的設置,通過 isActive 可以自定義激活邏輯,isActive 是一個函數,返回布爾值
exact
精確匹配
strict
嚴格模式
應用場景(五)
當用戶訪問不存在的路由,我們需要提供一個反饋頁面,也就是 404
index.js
NotFound.js
默認情況下,React.js 會渲染所有與之匹配的路由組件,上面的案例中,當我們訪問任意路由(如:/about),也會匹配 NotFound
路由組件渲染
Switch 組件
該組件只會渲染首個被匹配的組件
應用場景(六)
現在,我們要給用戶增加一個購物車的功能
index.js
<NavLink to="/cart" activeStyle={{color:'red'}} exact>Cart</NavLink>
Cart.js
Cart.js
app.js
註冊登錄
index.js
Redirect 組件
未登錄用戶是不能訪問購物車的,所以,我們需要在訪問購物車的時候加入用戶權限驗證(鑑權),如果沒有登錄則跳轉到登錄
index.js
to
設置跳轉的 URL
登錄代碼
login({username, password}) {
return new Promise( (resolve, reject) => {
if (!username || !password) {
reject('請輸入用戶名和密碼');
}
let user = this.state.users.find(user => user.username === username && user.password === password);
if ( !user ) {
reject('用戶不存在或者密碼錯誤');
}
this.setState({
userInfo: {
id: user.id,
username: user.username
}
});
resolve('登錄成功');
} );
}
<Route path='/login' component={props => {
return <Login {...props} onLogin={this.login.bind(this)} />;
}} />
// login.js
import React from 'react';
export default class Login extends React.Component {
constructor(...props) {
super(...props);
this.login = this.login.bind(this);
this.usernameRef = React.createRef();
this.passwordRef = React.createRef();
}
login() {
let {onLogin, history: {push}} = this.props;
if (typeof onLogin === 'function') {
onLogin({
username: this.usernameRef.current.value,
password: this.passwordRef.current.value
}).then(msg=>{
alert(msg);
push('/');
}).catch(e=>alert(e));
}
}
render() {
return(
<div>
<p>
用戶名:<input type="text" ref={this.usernameRef} />
</p>
<p>
密碼:<input type="password" ref={this.passwordRef} />
</p>
<p>
<button onClick={this.login}>登錄</button>
</p>
</div>
);
}
}
應用場景(七)
我突然發現賣東西比做碼農要賺錢(主要是能生髮),所以加大產品投入量,期待有一天,我的頭髮要寶哥多,然後推薦給
莫莫。隨着產品的增多,那麼多的數據就不可能一次性全部展示出來,所以我們爲商品的展示添加一個分頁功能
Home.js
Home.js
// Pagination.js
import React from 'react';
import PropTypes from 'prop-types';
import {withRouter, Link} from 'react-router-dom';
class Pagination extends React.Component {
static defaultProps = {
pages: 1,
page: 1
}
static propTypes = {
pages: PropTypes.number,
page: PropTypes.number
}
render() {
let {pages, page, history: {push}} = this.props;
// console.log(this.props);
return (
<div className="pagination">
{
(new Array(pages)).fill('').map((v, i) => {
return (
<Link
key={++i}
className={i === page ? 'active' : ''}
to={'/'+i}
>
{i}
</Link>
);
})
}
前往
<input type="text" className="goto" onKeyDown={({target:{value}})=>{
if (value !== '') {
push('/' + value);
}
}} />
頁
</div>
);
}
}
export default withRouter(Pagination);
withRouter 組件
如果一個組件不是路由綁定組件,那麼該組件的 props 中是沒有路由相關對象的,雖然我們可以通過傳參的方式傳入,但是如果
結構複雜,這樣做會特別的繁瑣。幸好,我們可以通過 withRouter 方法來注入路由對象