一个React包装器的应用 - 权限管理

在我们的应用中,每个按钮都有个权限点,前端通过接口的方式取得此用户的权限点列表,再来决定按钮是否显示。假設我们权限点列表取得后存在window.globals.permissions

传统的方式可以在redner的时候,判断用户是否有此权限,在来决定按钮是否显示。例如:

class Page1 extend React.Component {
    render() {
        const {create, update} = window.globals.permissions;
        return (
            {create && <Button>Create Project</Button>}
            {update && <Button>Update Project</Button>}
        );
        
    }
}

如果现在又有个页面叫做Page2,又要再写类似的判断在Page2里面。再者如果需求改变成:"当用户没有权限的时候,按钮设定为disabled"。这样又要把分散再各页面的权限管理逻辑,通通修改一变,如:

class Page1 extend React.Component {
    render() {
        const {create, update} = window.globals.permissions;
        return (
            {<Button disabled={!create}>Create Project</Button>}
            {<Button disabled={!update}>Update Project</Button>}
        );
        
    }
}

这显然不是一个优雅的解法。其实用户是否有某按钮的权限,只需要关心權限點的名稱,能不能这样写?

class Page1 extend React.Component {
    render() {
        return (
            {<Button auth="create">Create Project</Button>}
            {<Button auth="update">Update Project</Button>}
        );        
    }
}

在按钮的地方,只要指定权限点名称就好了。要判断window.globals.permissions和是否隐藏/disabled就交由包装器统一处理即可。接下来我们看一下包装器的部份:

export default function injectAuth(component) {
    const checkAuth = (props) => {
      let {auth} = props;
      // No Auth required
      if(auth == null) {
        return true;
      }
      return windows.globals.permissions[auth];      
    }

    let WrappedClass = class extends component {

      render() {
        if(checkAuth(this.props)) {
          return super.render();
        }
        else {
          const noAuthType = this.props.noAuthType || 'hidden';
          if(noAuthType === 'hidden') {
            return null;
          } else if(noAuthType === 'disabled') {
            // React doesn't allow to modify props like this.prpos.disabled=ture
            // Should clone the element to with inital props
            // See: http://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children
            return React.cloneElement(super.render(), {disabled:true});
          } else {
             throw new Error('noAuthType必须是hidden或disabled');
          }

        }
      }
    }

    return WrappedClass;
}

injectAuth(component)方法的入参是组件的Class,这里的例子是Button。injectAuth将产生了一个新的Class,这个Class继承了Button Class,所以原本Button组件的行为都会被保留下来。

内部再调用checkAuth方法,检查此外部传进来的auth property是否在windows.globals.permissions是存在的。如果权限检查通过,就直接返回原本Button的render结果:

return super.render();

如果权限检查不通过,則根据noAuthType来决定是要隐藏或者disabled组件。

OK, 有了这个injector后,在我们可以在组件本身都统一置入这样的功能:

class Button { 
    ...
}
export default injectAuth(Button);

这样在个页面使用组件的时候,就不用一一的去写injectAuth的带代码了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值