作为Store lifecycle question人的后续行动,

在一个典型的web应用程序中,通过URL有一个指向当前应用程序状态的快捷方式很好,这样你就可以重新访问该状态,并使用前进和后退按钮在状态之间移动.

对于Flux,我们希望所有操作都通过dispatcher,我想这也包括URL更改.如何管理flux应用程序中的URL更改?

推荐答案

[Update]

在研究了一系列React/flux应用程序之后,我得出了一个结论:我更喜欢单独处理路由,并与flux正交.策略是,URL/路由应该确定哪些组件被装载,组件根据路由参数和其他必要的应用程序状态从存储中请求数据.

[Original Answer]

在最近的一个项目中,我在try Flux时采用了一种方法,就是将路由层变成另一个存储.这意味着所有更改URL的链接实际上都会通过dispatcher触发一个操作,请求更新路由.RouteStore通过在浏览器中设置URL并设置一些内部数据(通过route-recognizer)来响应该调度,以便在store 触发change事件时,视图可以查询新的路由数据.

对我来说,一个不明显的问题是如何确保URL更改触发操作;我最终创建了一个mixin来为我管理它(注意:这不是100%健壮的,但对我使用的应用程序有效;您可能需要进行修改以满足您的需求).

// Mix-in to the top-level component to capture `click`
// events on all links and turn them into action dispatches;
// also manage HTML5 history via pushState/popState
var RoutingMixin = {
  componentDidMount: function() {
    // Some browsers have some weirdness with firing an extra 'popState'
    // right when the page loads
    var firstPopState = true;

    // Intercept all bubbled click events on the app's element
    this.getDOMNode().addEventListener('click', this._handleRouteClick);

    window.onpopstate = function(e) {
      if (firstPopState) {
        firstPopState = false;
        return;
      }
      var path = document.location.toString().replace(document.location.origin, '');
      this.handleRouteChange(path, true);
    }.bind(this);
  },

  componentWillUnmount: function() {
    this.getDOMNode().removeEventListener('click', this._handleRouteClick);
    window.onpopstate = null;
  },

  _handleRouteClick: function(e) {
    var target = e.target;

    // figure out if we clicked on an `a` tag
    while(target && target.tagName !== 'A') {
      target = target.parentNode;
    }

    if (!target) return;

    // if the user was holding a modifier key, don't intercept
    if (!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey) {
      e.preventDefault();

      var href = target.attributes.href.value;
      this.handleRouteChange(href, false);
    }
  }
};

其用途如下:

var ApplicationView = React.createClass({
  mixins: [RoutingMixin],

  handleRouteChange: function(newUrl, fromHistory) {
    this.dispatcher.dispatch(RouteActions.changeUrl(newUrl, fromHistory));
  },

  // ...
});

store 中的处理程序可能类似于:

RouteStore.prototype.handleChangeUrl = function(href, skipHistory) {
  var isFullUrl = function(url) {
    return url.indexOf('http://') === 0 || url.indexOf('https://') === 0;
  }

  // links with a protocol simply change the location
  if (isFullUrl(href)) {
    document.location = href;
  } else {
    // this._router is a route-recognizer instance
    var results = this._router.recognize(href);
    if (results && results.length) {
      var route = results[0].handler(href, results[0].params);
      this.currentRoute = route;
      if (!skipHistory) history.pushState(href, '', href);
    }

    this.emit("change");
  }
}

Reactjs相关问答推荐

有没有办法将在服务器端全局获取的一些数据传递到Next&>13应用程序目录中的客户端组件?

面对动画警告:未指定`useNativeDriver`.这是必需的选项,并且必须在REACT本机中显式设置为`true`或`False`

使用下一步中的路由/导航不会立即加载路由

Gitlab CI和VITE环境变量出现问题

如何在我的 React 应用程序中仅显示我的 Register 组件

如何删除 bootstrap 手风琴上的边框

React 错误: 只能用作 元素的子元素,从不直接渲染.请将您的 包裹在

如何在一个 Next.js 项目中使用两种布局?

在React中使用if条件时如何更改Tailwind中元素的文本 colored颜色

为什么 useEffect 的初始化对于加载 localStorage 不起作用?

Next.js 和理智 | npm run build 时预渲染页面/时发生错误

无法从子组件传递数据到父组件

如何在使用 React Router v6 将当前页面的状态传递给上一页的同时导航到上一页?

react-router v6 中的 BrowserRouter 和 createBrowserRouter 有什么区别?我可以在不使用数据 API 的情况下使用 createBrowserRouter 吗?

如何使用 React 更改 Material UI 中 ButtonGroup 的 colored颜色 ?

React Native PermissionsAndroid 不包括 READ_MEDIA_IMAGES.如何解决这个问题?

如何从 extrareducer redux 更改对象中元素的值

如果 URL 已随功能组件更改,则取消刷新

如何通过 Material Ui 设计将 Accordion 添加到您的 React 项目中?

如果两个组件在 React 中导入相同的 CSS 文件会发生什么?