Route
組件的渲染方式有三種:component
,render
,children
,優先級由高到低css
代碼能夠看 這裏,這與 另一篇 是同樣的,本文只是把這部分單獨拿出來,而那篇文章的內容比較完整,基本上項目裏用到的,能想到的都有了react
效果: git
使用 Route
組件的 render
方法代替經常使用的 component
,使得詳情 Detail
組件掛載在 List
下面,即進入詳情,可是列表並不會被註銷;github
AuthRoute
是封裝官方Route
的組件,使用Route
替代也不會有問題antd
import AuthRoute from '@/routes/auth-route';
import * as React from 'react';
import Loadable from '@loadable/component';
const List = Loadable(() => import('@/views/list'));
// 實現列表保留滾動條位置的寫法
// list
export default [
<AuthRoute
key="list"
// exact={true}
path="/list"
// component={Loadable(() => import('@/views/list'))}
render={() => {
return (
<List>
<AuthRoute
exact={true}
path="/list/detail/:id"
component={Loadable(() => import('@/views/list-detail'))}
/>
</List>
)
}}
/>
]
複製代碼
列表:props.children
表明詳情組件 <Detail />
,在上面的路由文件能夠看到;react-router
列表滾動時記錄滾動條位置,從詳情返回列表時恢復滾動條位置,從而實現 keep-alive
的效果post
從列表到詳情則重置滾動條位置爲0ui
// src/views/list/index.tsx
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router';
import styles from './list.scss';
const { useState, useEffect } = React;
interface IProps extends RouteComponentProps {
[prop: string]: any
}
export interface IListItem {
id: number,
text: string
}
const arr: IListItem[] = [
{ id: 1, text: 'list1skdjfnsdnfsdnfsdf' },
{ id: 2, text: 'list2jilkfsjjfnsdnfsdf' },
{ id: 3, text: 'list3sudfjnfnfnffffsdf' },
{ id: 4, text: 'list4kl.mlmjjjfsdnfsdf' },
{ id: 5, text: 'list5ldskfoiquqiquwwww' },
{ id: 6, text: 'list6skdjfnsdnfsdnfsdf' },
{ id: 7, text: 'list7jufhfbvbvvvvaaadf' },
{ id: 8, text: 'list8,lkoqpoqwkeqlwele' }
];
let scrollTop: number = 0;
// list
function List(props: IProps) {
const [list, setList] = useState([{ id: 1, text: '' }]);
useEffect(() => {
setList(arr);
window.addEventListener('scroll', onScroll);
return () => {
window.removeEventListener('scroll', onScroll);
}
}, []);
// 監聽列表與詳情的切換
useEffect(() => {
if (props.location.pathname.includes("/list/detail/") ) {
// console.log('scrollTop -- detail: ', scrollTop);
document.documentElement.scrollTop = 0;
} else {
window.addEventListener('scroll', onScroll);
setTimeout(() => {
// console.log('scrollTop -- list: ', scrollTop);
document.documentElement.scrollTop = scrollTop;
}, 0);
}
}, [props.location.pathname]);
// 監聽滾動
function onScroll() {
// location.pathname 由於是同一組件,因此有問題,因此用原生js的
if (location.hash.includes("/list/detail/") ) {
window.removeEventListener('scroll', onScroll);
} else {
scrollTop = document.documentElement.scrollTop;
}
}
function toDetail(id: number) {
props.history.push(`/list/detail/${id}`);
}
return (
<div className={styles.list}> <section className="list-content" style={{ display: props.location.pathname.includes("/list/detail/") ? 'none' : 'block' }} > { list.map((item, index) => { return ( <div key={index} className={styles['list-item']} onClick={() => toDetail(item.id)} > { item.text } </div> ) }) } </section> {/* detial */} { props.children } </div>
)
}
export default withRouter(List);
複製代碼
應該有其餘實現方法,本文也只是「僞實現」。。。spa