单页Web应用程序,它不会改变URL

时间:2017-02-20 22:58:31

标签: javascript reactjs redux

好吧,我知道我在这里反对传统智慧,但是这里有。我正在学习如何使用react和redux构建SPA,事情进展顺利。我已经将反应路由器合并,因为它似乎是可接受的事情,但现在我遇到了问题。我希望我的SPA就像一个真正的应用程序,用户将始终在登录页面进入,然后从那里开始。当用户从一个页面导航到另一个页面时,会提取和存储各种内容。有些页面需要授权,例如,其他页面不需要授权。问题是当我使用react路由器时,URL会在每条路由上发生变化。那么,当用户通过说出书签回来后续访问时,应用程序会尝试跳转到他们离开的页面,而不是在我需要它们的入口点。这搞砸了引擎盖下面的一堆东西,他们得到了gobbledegook。

我从来没有真正理解为什么传统智慧才能永远打破后退按钮"并始终反映用户在网址中所做的一切。这似乎是一种教条,很难找到任何其他的思维方式。例如,我有时间进行谷歌搜索,然后去我点击一段时间的网站,找不到我要找的东西,然后想用后退按钮去回到我的谷歌搜索结果,但它点击了点击 - 点击返回我在该网站上制作的每一步。的Bleh。我最终必须关闭该标签并重新开始。这种情况一直发生在我身上。

在移动应用中,用户习惯于始终到达目标网页,并从那里点击。为什么网络应用程序的行为方式不一样?

所以我的问题是:我如何在react-redux应用程序中实现它?我有一个内部"返回"用户可以单击以转到上一页"页面的按钮"在应用程序内。我以为我能保持历史记录"在redux商店中,写一些goBack方法,以及其他不需要的URL。有没有使用这种方法的例子?

任何建议都非常感谢。

2 个答案:

答案 0 :(得分:1)

你的建议有两个挑战。首先,如果没有网址,用户就无法为其位置添加书签。第二,应用程序在浏览器窗口中运行,浏览器窗口有后退按钮(前进和历史记录)。

我正在开发SPA,在初始引导程序之后只通过RESTful api发出JSON请求。这非常有效,但需要额外的工作来管理页面历史记录。如果没有它,用户会感到沮丧,因为他们已经退出了#39;从应用程序返回到登录页面时,他们点击后面的'浏览器中的按钮。

我们维护的页面历史记录是我们控制的页面历史记录,因此可以将其管理为我们想要的粒度。有许多api调用不会更改URL。不幸的是,对于许多框架,他们希望您在一个页面内操作。心态,希望很快就能改变。 (就个人而言,我正在考虑禁用后退按钮,以便用户将其视为一个应用程序。)

我认为你正在制作的这一点,我同意的是,我们正在构建应用程序并受限于传统的应用程序。页面的概念使" SINGLE页面应用的概念"比它应该的少一些。

答案 1 :(得分:1)

正如你所说,反对谷物并创建你自己的后退按钮可能不是一个好主意。

也就是说,如果您不想要react-router的这些功能,那么实现您自己的路由器应该非常困难。

例如,您可以使用历史记录列表建立您的redux状态

{
  history: ["home"],
  home: { ... },
  otherPage: { ... },
}

然后在你的顶级渲染功能中确定页面并渲染,

import HomeComponent from 'components/HomePage'
import OtherPageComponent from 'components/OtherPageComponent'

const pages = {
    'home': HomeComponent,
    'otherPage': OtherPageComponent
}

export class App extends React.Component {
    ...
    render() {
        const CurrentPage = this.props.history[this.props.history.length-1];
        return (
             <CurrentPage />
        )
    }
}

export default App;

然后你需要一个减速器/动作来改变路线,

// reducer.js
export default function reducer(state, action) {
    switch(action.type) {
        case 'CHANGE_ROUTE':
            return {
                ...state,
                history: state.history.concat([action.route])
            }
        case 'GO_BACK':
            return { 
                ...state,
                history: history.slice(0,-1)
            }
        default:
            return state
    }
}

// action.js
export const changeRoute = (route) => ({ type: 'CHANGE_ROUTE', route });
export const goBack = () => ({ type: 'GO_BACK'});

然后,您可以通过调度相关操作

来更改任何页面上的路径
// some-component.js
import { goBack, changeRoute } from 'action.js'

...
// in some render method

<button onClick={() => dispatch(goBack())}>
    Go Back
</button>
<button onClick={() => dispatch(changeRoute('somePage'))}>
    Go to some page
</button> 

您可能希望将onClick内容打包在某种<Link>组件中,如react-router。

祝你好运!