用 React 编写的 Chrome 扩展中的路由
Posted
技术标签:
【中文标题】用 React 编写的 Chrome 扩展中的路由【英文标题】:Routing in Chrome Extension written in React 【发布时间】:2017-05-11 03:57:50 【问题描述】:我希望 Chrome 扩展程序中有 2 个页面。例如:第一个(默认)页面包含用户列表,第二个页面包含该用户的操作。
我想通过单击用户(在我的情况下为ClickableListItem
)来显示第二页。我使用 React 和 React 路由器。这是我拥有的组件:
class Resents extends React.Component
constructor(props)
super(props);
this.handleOnClick = this.handleOnClick.bind(this);
handleOnClick()
console.log('navigate to next page');
const path = '/description-view';
browserHistory.push(path);
render()
const ClickableListItem = clickableEnhance(ListItem);
return (
<div>
<List>
<ClickableListItem
primaryText="Donald Trump"
leftAvatar=<Avatar src="img/some-guy.jpg" />
rightIcon=<ImageNavigateNext />
onClick=this.handleOnClick
/>
// some code missed for simplicity
</List>
</div>
);
我还尝试将ClickableListItem
包装成Link
组件(来自react-router
),但它什么也没做。
也许问题是 Chrome 扩展没有他们的browserHistory
...但是我在控制台中没有看到任何错误...
如何使用 React 进行路由?
【问题讨论】:
handleOnClick
在我单击项目时调用,我可以看到控制台消息
确实,工具栏弹出窗口无法导航。只需显示/隐藏 DOM 元素。还要确保查看正确的控制台(扩展有 3 种类型)。
@wOxxOm 不,可以导航!使用 react-router 或者,正如@Paul 回答的那样,使用 createMemoryHistory
我在经典含义中使用了 navigation
,而不是特定于 React(它只是按照我的建议通过切换/添加 DOM 元素来模仿导航)。跨度>
【参考方案1】:
虽然您不想为扩展程序使用浏览器(或哈希)历史记录,但您可以使用内存历史记录。内存历史复制浏览器历史,但维护自己的历史堆栈。
import createMemoryHistory from 'history'
const history = createMemoryHistory()
对于只有两个页面的扩展,使用 React Router 是多余的。在 state 中维护一个值会更简单,该值描述要呈现哪个“页面”并使用 switch 或 if/else 语句仅呈现正确的页面组件。
render()
let page = null
switch (this.state.page)
case 'home':
page = <Home />
break
case 'user':
page = <User />
break
return page
【讨论】:
我稍后试试! 这是标准做法吗?在 Chrome 扩展程序中进行路由应该很常见【参考方案2】:我知道这篇文章已经过时了。不过,我会在此处留下我的答案,以防有人仍在寻找它并想要快速回答以修复他们现有的路由器。
就我而言,我只是从BrowserRouter
切换到MemoryRouter
。无需额外的memory
包,它就像魅力一样工作!
import MemoryRouter as Router from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<Router>
<OptionsComponent />
</Router>
</React.StrictMode>,
document.querySelector('#root')
);
您可以在ReactRouter Documentation中尝试其他适合您的方法
【讨论】:
嗨,Snek,你能解释一下如何在没有 path="" 的情况下切换到不同的路线吗? @joshmillgate “切换到没有路径的不同路线”是什么意思?你的意思是<Route render=something>
没有路径?我不认为那是一回事。或者您的意思是在没有<Link>
的情况下切换到不同的路线?如果是这种情况,您可以使用<Route>
的渲染道具history
属性或只使用<Redirect>
。如果需要,请随时与我联系。
@SnekNOTSnake 这行得通,但是“返回”操作不起作用:/ 知道如何处理吗?【参考方案3】:
我通过使用单路由而不是嵌套路由解决了这个问题。问题出在别的地方……
另外,我创建了一个问题:https://github.com/ReactTraining/react-router/issues/4309
【讨论】:
太糟糕了,维护者锁定了这个问题。 :-/【参考方案4】:我只需要使用createMemoryHistory
而不是createBrowserHistory
:
import React from "react";
import ReactDOM from "react-dom";
import Router, Switch, Route, Link from "react-router-dom";
import createMemoryHistory from "history";
import Page1 from "./Page1";
import Page2 from "./Page2";
const history = createMemoryHistory();
const App: React.FC<> = () =>
return (
<Router history=history>
<Switch>
<Route exact path="/">
<Page1 />
</Route>
<Route path="/page2">
<Page2 />
</Route>
</Switch>
</Router>
);
;
const root = document.createElement("div");
document.body.appendChild(root);
ReactDOM.render(<App />, root);
import React from "react";
import useHistory from "react-router-dom";
const Page1 = () =>
const history = useHistory();
return (
<button onClick=() => history.push("/page2")>Navigate to Page 2</button>
);
;
export default Page1;
【讨论】:
【参考方案5】:这是我刚刚找到的一个非常轻量级的解决方案。我刚刚尝试过 - 简单而高效:react-chrome-extension-router
【讨论】:
【参考方案6】:一个现代轻量级选项出现在包wouter
。
您可以创建自定义挂钩以根据哈希更改路由。
见wouter docs。
import useState, useEffect from "react";
import Router, Route from "wouter";
// returns the current hash location in a normalized form
// (excluding the leading '#' symbol)
const currentLocation = () =>
return window.location.hash.replace(/^#/, "") || "/";
;
const navigate = (to) => (window.location.hash = to);
const useHashLocation = () =>
const [loc, setLoc] = useState(currentLocation());
useEffect(() =>
// this function is called whenever the hash changes
const handler = () => setLoc(currentLocation());
// subscribe to hash changes
window.addEventListener("hashchange", handler);
return () => window.removeEventListener("hashchange", handler);
, []);
return [loc, navigate];
;
const App = () => (
<Router hook=useHashLocation>
<Route path="/about" component=About />
...
</Router>
);
【讨论】:
以上是关于用 React 编写的 Chrome 扩展中的路由的主要内容,如果未能解决你的问题,请参考以下文章
如何从 JS 开发控制台访问用 Chrome 扩展编写的功能?
React.js Chrome 扩展 - 如何将 Background.js 中的数据存储在 React 内部的变量中?
如何使用具有多个页面和入口点的 React 和 TypeScript 设置 chrome 扩展?