Vue v-if resolve Promise - 在 Vue 中实现 Laravel Gate

Posted

技术标签:

【中文标题】Vue v-if resolve Promise - 在 Vue 中实现 Laravel Gate【英文标题】:Vue v-if resolve Promise - implementing Laravel Gate in Vue 【发布时间】:2021-07-31 02:31:03 【问题描述】:

我正在尝试在 Vue 中实现 Laravel 的授权和策略,方法是实现一个向后端控制器发送 GET 请求的 mixin。

问题是 v-if 指令正在接收 Promise,这显然无法解决

下面是我正在尝试做的一个非常简化的版本:

全局混合,auth.js

import axios from "axios"

export default 
    methods: 
        async $can (permission, $model_id) 
            let isAuthorized = false;

            await axios.get(`/authorization?$permission&$model_id`)
            .then(function (response) 
                isAuthorized = response.data.isAuthorized
            )
            .catch((error) => 
                isAuthorized = false;
            );

            return isAuthorized;
        
    

主入口文件,app.js

import Auth from '@/auth';

Vue.mixin(Auth);
...
new Vue(...)

组件.vue

<template>
    <div>
        <div v-if="$can('do-this', 12)">
            Show Me
        </div>
    </div>
</template>

<script>
export default 
</script>

有没有办法在 v-if 中“等待”异步 $can 操作?还是我从一个完全错误的方向接近这个?

【问题讨论】:

有没有办法在 v-if 中“等待”异步 $can 操作?还是我从一个完全错误的方向接近这个? - 不,没有办法。是的,你是。如果在应用程序初始化上有一个等待它的承诺,使用异步组件或其他。 isAuthorized 应该是状态的一部分(通常是 Vuex)并与 $can 分开。 考虑过,但在这种情况下可能是不可能的。在某个页面上,我可能对当前用户有多个具有不同权限的项目,我事先不知道权限的类型和种类。我的 $can 方法“理想地”处理这个问题,因为它会被提供权限名称、模型类型和可选的模型 ID。 那么你有一个需要以不同方式解决的问题。不要在模板中编写逻辑。 Angular 支持这一点,而 Vue 不支持。您可能会用 JS 编写它,就像答案显示的那样,或其他方式。 【参考方案1】:

你不需要 async/await 因为 axios 返回一个承诺。我认为您可以从创建的钩子中调用该函数。不要返回值,而是更改相关的数据属性,并在 v-if 中使用它,如下所示:

<div v-if="permissions['do-this__12']">

data() 
  return 
    permissions: 
      'do-this__12': false,
      'or-this__13': false,
    ,
  


methods: 
  getPermissions() 
    for (const key in this.permissions) 
      this.can(key.split('__')[0], key.split('__')[1])
    
  ,
  can(permission, model_id) 
    axios.get(`/authorization?$permission&$model_id`)
      .then(response => 
        this.permissions[`$permission__$model_id`] = response.data.isAuthorized
      )
      .catch(error => 
        this.permissions[`$permission__$model_id`] = false;
      );
  ,

created() 
  this.getPermissions();

我没有尝试我的代码,如果失败,请告诉我。顺便说一句,将此实现提取到 mixin 将是一个更好的主意。如果您喜欢这样做,只需将“权限”对象留在组件中,然后将其他所有内容移至 mixin。

但当您需要多次 API 调用以获取权限时,这种方法无效。这就是为什么我认为您应该将整个权限对象传递给后端并在服务器中进行工作:

iPreferThisBecauseOfSingleAPICall() 
    axios.get(`/authorization`, this.permissions)
         .then(( data ) => this.permissions = data)

// AuthorizationController

public function index(Request, $request)

   $permissions = [];

   foreach($request->all() as $permission) 
     // run your backend code here
   

   return $permissions;

最后一点,最好不要每次都请求权限,而是一次性加载所有权限。

【讨论】:

你不需要 async/await 因为 axios 返回一个承诺 - 为什么这是不使用 async..await 的理由?它应该与 Promise 一起使用,这就是它的目的。 因为他只等待一个函数,它返回一个承诺。 我没有看到这种关系。 await 需要不明确写 then。这是代码一致性的问题。另外,cangetPermissions 有气味。它们不返回承诺并封装异步过程,这限制了它们可以组合和测试的方式。如有必要,可以故意这样做,但在这里,如果在预期的地方使用 async..await,这似乎是不存在的问题。 问题不是异步,是缺少默认值。如果设置为 false(根据原始代码应该为 false),那么一切都会很容易解决,并且 async 将变得不必要。正如您在问题下所说的那样,“不,没有办法”。我向他展示了一种不同的方法。如果对你来说还不够好,让我们看看你的答案。 我的评论仅指指出等待情况并非如此的行,而不是答案的其余部分。我认为这是一种误导,特别是因为答案中使用原始承诺的代码可能很麻烦,因为它没有遵循 async..await 自然提供的良好实践。

以上是关于Vue v-if resolve Promise - 在 Vue 中实现 Laravel Gate的主要内容,如果未能解决你的问题,请参考以下文章

vue promise

Vue- Promise函数---参数resolve(调用.then方法)-- 参数reject(调用.catch方法)---链式结构

Vue--Promise的基本使用

vue中Promise.all 多请求使用

vue中Promise.all 多请求使用

Vue相关笔记