在这篇文章中,我们将带领您了解恢复滚动y位置react-router-dom的全貌,包括恢复滑动的相关情况。同时,我们还将为您介绍有关''react-router-redux''到''connecte
在这篇文章中,我们将带领您了解恢复滚动 y 位置 react-router-dom的全貌,包括恢复滑动的相关情况。同时,我们还将为您介绍有关''react-router-redux''到''connected-react-router''、./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”、connected-react-router: react-router-dom 必须总是最后安装、DOM、SAX、JDOM DOM、JDOM SAX、DOM4J DOM、DOM4J SAX 性能比对的知识,以帮助您更好地理解这个主题。
本文目录一览:- 恢复滚动 y 位置 react-router-dom(恢复滑动)
- ''react-router-redux''到''connected-react-router''
- ./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”
- connected-react-router: react-router-dom 必须总是最后安装
- DOM、SAX、JDOM DOM、JDOM SAX、DOM4J DOM、DOM4J SAX 性能比对
恢复滚动 y 位置 react-router-dom(恢复滑动)
如何解决恢复滚动 y 位置 react-router-dom
Here 我复制了一个简单的片段,其中包含使用 react-spring
进行的页面转换。
有没有办法在点击浏览器后退按钮时恢复上一页滚动位置?
周围有很多相关的QA,但是在使用动画库时找不到任何解决方案
知道如何实现这一目标吗?
解决方法
导航时恢复 scrollY 位置并不容易。我们可能需要一个上下文来存储页面的 y 位置。以下是我的解决方案。
用于监听滚动事件的自定义钩子(hooks/scroll.js)
import { useEffect,useState } from ''react'';
import { useLocation } from ''react-router-dom'';
export const useScrollPositions = () => {
const [positions,setPositions] = useState(new Map());
const location = useLocation();
useEffect(() => {
const listener = (ev) => {
console.log(''position: '',ev.target.scrollTop);
positions.set(location.pathname,{
left: ev.target.scrollLeft,top: ev.target.scrollTop
});
setPositions(new Map(positions));
}
window.addEventListener(''scroll'',listener,true);
return () => {
window.removeEventListener(''scroll'',true);
}
},[location]);
return positions;
}
用于存储页面 y 位置的上下文(context/scroll-context.js)
import { createContext } from ''react'';
export const ScrollContext = createContext();
将所有页面包装在上下文提供程序中:应用组件
const App = () => {
const location = useLocation();
const positions = useScrollPositions();
const transitions = useTransition(location,{
from: { opacity: 0,transform: ''translate3d(100vw,0)'' },enter: { opacity: 1,transform: ''translate3d(0,leave: { opacity: 0,transform: ''translate3d(-20vw,});
return (
<ScrollContext.Provider value={positions}>
<GlobalStyles />
<Switch>
<Route path=''/'' exact component={Home} />
<Route path="/about" component={About} />
</Switch>
{transitions((props,item) => (
<animated.div style={props}>
<Switch location={item}>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
</Switch>
</animated.div>
))}
</ScrollContext.Provider>
);
};
滚动页面组件
import React,{ useEffect,useRef,useContext } from ''react'';
import { useLocation } from ''react-router-dom'';
import { ScrollContext } from ''../context/scroll-context'';
const Page = ({children,...rest}) => {
const main = useRef();
const positions = useContext(ScrollContext);
const location = useLocation();
useEffect(() => {
if (main.current) {
const position = positions.get(location.pathname);
if (position && position.top) {
main.current.scrollTop = position.top;
}
}
},[])
return (
<main {...rest} ref={main}>
{children}
</main>
)
}
export default Page
注意:您必须将所有页面都包装在此页面组件中。这个页面组件的 CSS 样式(scroll: auto)也很重要。在现实世界的项目中,它可能需要更灵活的代码。无论如何,对于一个完整的工作项目,请检查 here
,您可以在卸载组件时调用以下方法并保留它。
export const getScrollPage = (): number => {
let docScrollTop = 0;
if (document.documentElement && document.documentElement !== null) {
docScrollTop = document.documentElement.scrollTop;
}
return window.pageYOffset || docScrollTop;
};
使用保留的滚动 y 位置值并传递给下面的函数。
export const scrollTo = (scrollnumber: number = 0): number =>
window.requestAnimationFrame(() => {
window.scrollTo(0,scrollnumber);
});
''react-router-redux''到''connected-react-router''
背景:
redux和react-router两者协同工作会出现,路由变化而store无法感知到,的问题。
react-router-redux :
一. 作用:
react-router-redux 是 redux 的一个中间件,加强了React Router库中history这个实例,以允许将history中接受到的变化反应到state中去。
使用方法1:
使用syncHistoryWithStore包裹browserHistory,当url改变时,会自动触发 LOCATION_CHANGE action,更改store中维护的 locationBeforeTransitions 状态对象,实现store状态的更新。
// 只需要传入react-router中的history以及redux中的store,就可以获得一个增强后的history对象。
// 将这个history对象传给react-router中的Router组件作为props,就给应用提供了观察路由变化并改变store的能力。
import { syncHistoryWithStore, routerReducer } from ''react-router-redux''
const store = createStore(
combineReducers({
...reducers,
routing: routerReducer
})
)
const history = syncHistoryWithStore(browserHistory, store)
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App} />
</Router>
</Provider>,
document.getElementById(‘app'')
)
// 对应的reducer.js
export const LOCATION_CHANGE = ''@@router/LOCATION_CHANGE''
const initialState = {
locationBeforeTransitions: null
}
使用方法2:
手动触发路由的跳转,同时需要。
直接store.dispatch(push(''/foo'')),会触发 CALL_HISTORY_METHOD 这个action,调用中间件,等同于调用 browserHistory上相应的push方法。
// 触发路由跳转(使用redux action的方式来触发)
import { createStore, combineReducers, applyMiddleware } from ''redux'';
import { routerMiddleware, push } from ''react-router-redux''
// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
reducers,
applyMiddleware(middleware)
)
// 使用dispatch手动触发 push 等操作
store.dispatch(push(''/foo''))
源码的具体实现:
// import 的 push, replace, go, goBack, goForward之类的方法出自: action.js
export const push = updateLocation(''push'')
function updateLocation(method) {
return (...args) => ({
type: CALL_HISTORY_METHOD,
payload: { method, args }
})
}
//中间件代码
export default function routerMiddleware(history) {
return () => next => action => {
if (action.type !== CALL_HISTORY_METHOD) {
return next(action)
}
const { payload: { method, args } } = action
history[method](...args) //这里直接改变browserHistory
}
}
二. react-router-redux原理图
CALL_HISTORY_METHOD,这类 action 一般会在组件内派发,它不负责 state 的修改,通过 routerMiddleware 后,会被转去调用 history。
面临的问题:
react-router-redux 只兼容 react-router 2.x and 3.x,所以要改成使用 connected-react-router 来兼容 react-router 4.x。
解决:
把之前 react-router-redux 中 store.dispatch(push(''/foo'')) 这么使用的,直接改成 history.push(''/foo'') 之类的。
参考文章:
https://blog.csdn.net/weixin_... React 的路由状态管理
./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”
如何解决./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”
./node_modules/react-router-dom/react-router-dom.js Attempted import error: ''Navigate'' is not exported from ''react-router''.
react-router-dom的版本是6.0.0-alpha.2,而react-router是5.2.0。 两者均已正确安装。我不确定如何解决此错误。有人可以给我任何可能的解决方法吗?
我的代码中甚至没有<Navigate to=?>
行。
解决方法
为什么只安装两个都需要,这可以工作
- 执行npm删除react-router
- 删除node_modules
- 纱线安装或npm安装和
- 启动纱线或启动npm
connected-react-router: react-router-dom 必须总是最后安装
如何解决connected-react-router: react-router-dom 必须总是最后安装
我从我的开发文件夹中排除了我的 node_modules 文件夹,并且只有一个指向它的软链接(因此它不会同步到云)。我使用 connected-react-router 并且一切正常,直到我之后安装任何其他 npm 包。然后我在浏览器中收到错误:Uncaught Error: Invariant Failed: You should not use <Switch> outside a <Router>
当我再做 npm install react-router-dom
时,一切都会恢复正常。出于某种原因,react-router-dom 必须始终是最新安装的软件包。
即使我直接包含 node_modules 文件夹,而不是作为软链接,也会出现此问题。有没有人知道这是怎么发生的以及如何解决这个问题?
DOM、SAX、JDOM DOM、JDOM SAX、DOM4J DOM、DOM4J SAX 性能比对
测试xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<RESULT>
<VALUE>
<NO>A1234</NO>
<ADDR>XX号</ADDR>
</VALUE>
<VALUE>
<NO>B1234</NO>
<ADDR>XX组</ADDR>
</VALUE>
</RESULT>
测试代码:
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
import org.jdom.Element;
import org.jdom.input.DOMBuilder;
import org.jdom.input.SAXBuilder;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLParserTest {
@Test
public void testDOMTypeParseXML() throws ParserConfigurationException, SAXException,
IOException {
long lasting =System.currentTimeMillis();
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse(is);
org.w3c.dom.NodeList nl = doc.getElementsByTagName("VALUE");
for (int i=0;i<nl.getLength();i++){
// System.out.print("车牌号码:" + doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue());
// System.out.println("车主地址:" + doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue());
}
long end = System.currentTimeMillis();
System.out.println("DOM TYPE PARSE COST "+(end - lasting)+"毫秒");
}
public class MyXMLReader extends DefaultHandler{
@SuppressWarnings("rawtypes")
java.util.Stack tags = new java.util.Stack();
public MyXMLReader() {
super();
}
@SuppressWarnings("unchecked")
public void startElement(String uri,String localName,String qName,Attributes attrs) {
tags.push(qName);
}
public void characters(char ch[], int start, int length) throws SAXException {
String tag = (String) tags.peek();
if (tag.equals("NO")) {
// System.out.print("车牌号码:" + new String(ch, start, length));
}
if (tag.equals("ADDR")) {
// System.out.println("地址:" + new String(ch, start, length));
}
}
}
@Test
public void testSAXTypeParseXML() throws SAXException, IOException, ParserConfigurationException{
long lasting = System.currentTimeMillis();
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sp = sf.newSAXParser();
MyXMLReader me = new MyXMLReader();
sp.parse(is, me);
System.out.println("SAX TYPE PARSE COST "+(System.currentTimeMillis() - lasting)+"毫秒");
}
@Test
public void testJDOMSAXTypeParseXML(){
long lasting = System.currentTimeMillis();
try {
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
SAXBuilder builder = new SAXBuilder();
org.jdom.Document doc = builder.build(is);
Element foo = doc.getRootElement();
List allChildren = foo.getChildren();
for(int i=0;i < allChildren.size();i++) {
// System.out.print("车牌号码:" + ((Element)allChildren.get(i)).getChild("NO").getText());
// System.out.println("车主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
}
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("JDOM SAX TYPE PARSE COST "+(System.currentTimeMillis() - lasting)+"毫秒");
}
}
@Test
public void testJDOMDOMTypeParseXML(){
long lasting = System.currentTimeMillis();
try {
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(is);
DOMBuilder builder1 = new DOMBuilder();
org.jdom.Document doc = builder1.build(document);
Element foo = doc.getRootElement();
List allChildren = foo.getChildren();
for(int i=0;i < allChildren.size();i++) {
// System.out.print("车牌号码:" + ((Element)allChildren.get(i)).getChild("NO").getText());
// System.out.println("车主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
}
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("JDOM DOM TYPE PARSE COST "+(System.currentTimeMillis() - lasting)+"毫秒");
}
}
@Test
public void testDOM4JSAXTypeParserXML() throws DocumentException{
long lasting = System.currentTimeMillis();
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
SAXReader reader = new SAXReader();
Document doc = reader.read(is);
org.dom4j.Element root = doc.getRootElement();
org.dom4j.Element foo;
for (Iterator i = root.elementIterator("VALUE");i.hasNext();){
foo = (org.dom4j.Element)i.next();
// System.out.print("车牌号码:" + foo.elementText("NO"));
// System.out.println("车主地址:" + foo.elementText("ADDR"));
}
System.out.println("DOM4J SAX TYPE PARSE COST "+(System.currentTimeMillis() - lasting)+"毫秒");
}
@Test
public void testDOM4JDOMTypeParserXML() throws DocumentException, ParserConfigurationException, SAXException, IOException{
long lasting = System.currentTimeMillis();
InputStream is = XMLParserTest.class.getClassLoader().getResourceAsStream("test.xml");
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(is);
DOMReader reader = new DOMReader();
Document doc = reader.read(document);
org.dom4j.Element root = doc.getRootElement();
org.dom4j.Element foo;
for (Iterator i = root.elementIterator("VALUE");i.hasNext();){
foo = (org.dom4j.Element)i.next();
// System.out.print("车牌号码:" + foo.elementText("NO"));
// System.out.println("车主地址:" + foo.elementText("ADDR"));
}
System.out.println("DOM4J DOM TYPE PARSE COST "+(System.currentTimeMillis() - lasting)+"毫秒");
}
}
结论:
当测试xml文件大小为50kb左右时:
DOM TYPE PARSE COST 144毫秒
SAX TYPE PARSE COST 43毫秒
JDOM SAX TYPE PARSE COST 179毫秒
JDOM DOM TYPE PARSE COST 145毫秒
DOM4J SAX TYPE PARSE COST 128毫秒
DOM4J DOM TYPE PARSE COST 106毫秒
今天关于恢复滚动 y 位置 react-router-dom和恢复滑动的介绍到此结束,谢谢您的阅读,有关''react-router-redux''到''connected-react-router''、./node_modules/react-router-dom/react-router-dom.js尝试导入错误:未从“ react-router”导出“ Navigate”、connected-react-router: react-router-dom 必须总是最后安装、DOM、SAX、JDOM DOM、JDOM SAX、DOM4J DOM、DOM4J SAX 性能比对等更多相关知识的信息可以在本站进行查询。
本文标签: