Mitrhil.js 条件路由和身份验证

Mitrhil.js conditional routing and authentication

我正在学习 javascriptmithril.js 1.1.6。我正在写一个简单的网络应用程序,用户可以在其中登陆一个他可以登录的页面。已经登录的用户登陆了不同的页面。我正在尝试使用条件路由,这里是主要组件:

const m = require("mithril");
...
import Eventbus from './whafodi/eventbus.js';
import WelcomePage from './ui/welcome.js';
import User from './model/user.js';
var eventbus = new Eventbus();
function MyApp() {
  return {
    usrAuth: function() {
      m.route(document.body, "/", {
        "/": { view: () => m("p", "hello")}
    })
  },
  usrNotAuth: function() {
    m.route(document.body, "/", {
      "/": { render: v => m(WelcomePage, eventbus) }
    })
  },
  oninit: function(vnode) {
    vnode.state.user = new User();
    eventbus.subscribe({
      type: "login",
      handle: function(action) {
        vnode.state.user.token = action.token;
        console.log(JSON.stringify(vnode.state.user));
      }
    });
  },
  view: function(vnode) {
    if(vnode.state.user.token) {
      this.usrAuth();
    } else {
      this.usrNotAuth();
    }
  }
}
};
m.mount(document.body, MyApp);

MyApp为主成分。它检查用户是否有令牌,然后 return 正确的 route。这是负责让用户登录的组件:

const m = require("mithril");
const hellojs = require("hellojs");
function TopBar(node) {
  var bus = node.attrs.eventbus;
  function _login() {
    hellojs('facebook').login({scope:'email'});
  }
  return {
    oninit: function(vnode) {
      hellojs.init({
         facebook: XXXXXXX,
      }, {
         redirect_uri: 'http://localhost'
      });
      hellojs.on('auth.login', auth => {
        var fbtoken = auth.authResponse.access_token;
        m.request({
          method:"POST",
          url:"./myapp/login/fb/token",
          data:auth.authResponse,
          background: true
        }).then(function(result){
          console.log(result);
          bus.publish({ type: "login", token: result.jwttoken });
          m.route.set("/");
        }, function(error){
          console.log(error);
          bus.publish({ type: "login", token: "" });
        });
      });
    },
    view: function(vnode) {
      return m("div", [
        m("button", { onclick:  _login }, "Login")
      ]);
    }
  }
}
export default TopBar;

TopBar 组件出现在主组件中提到的 WelcomePage 组件中。 TopBar 呈现一个按钮并使用 hello.js 登录。它使用 EventBus 总线参数来告诉主要组件用户已登录(主要组件中有一个处理程序来更新用户模型)。一旦用户登录,事件就会被触发,主要组件会更新用户模型。好的。现在,如何触发主组件加载正确的路由?

我再次阅读了 mithril'docs,发现 RouteResolvers 完全符合我的需要。这是一个例子:

var App = (function() {
  var login;
  function isLoggedIn(component) {
    if(login) {
      return component;
    } else {
      m.route.set("/hey");
    }
  }
  return {
    oninit: function(vnode) {
      EventBus.subscribe({
        type: "login",
        handle: function(action) {
          console.log("incoming action: " + JSON.stringify(action));
          login = action.value;
        }
      });
    },
    oncreate: function(vnode) {
      Foo.eventbus = EventBus;
      Bar.eventbus = EventBus;
      Hey.eventbus = EventBus;
      m.route(document.body, "/hey", {
        "/foo": {
          onmatch: function(args, requestedPath, route) { return isLoggedIn(Foo); }
        },
        "/bar": {
          onmatch: function(args, requestedPath, route) { return isLoggedIn(Bar); }
        },
        "/hey": Hey
      });
    },
    view: function(vnode) {
      return m("div", "home..");
    }
  };
})();

Eventbus用于让组件与App通信。它们触发 App 可以处理的事件(登录类型事件)。我发现以 oncreate 方法显示的方式传递 Eventbus 很方便,我可以在每个组件的 oncreate 中使用 Eventbus 让组件触发事件。