One from the start [Admin] Five ║ achieve "buttons" level permissions configuration

First, the antecedent Review

Hello Hello, everyone, on this happy day, Zhang wish you all work can be booming! Today is just the first day of the establishment of the community, I also hope that today can be a Day, complacent this big celebration!

This two-day holiday, it touches learned a lot, I admit this is yesterday's transaction commits, today's button-level permissions are the group programs and ideas of small partners, fear and trepidation that I wrote the article I would say I am always afraid of thieves knowledge, of course, entirely for my community, I did not get a penny after all, no matter how much traffic there is, at best, is likely to look good numbers.

 

Closer to home, remember six months ago (2019.02.27) the time of my vue Project II: Blog.Admin officially open ( https://github.com/anjoy8/Blog.Admin ), was going to do a simple background of privilege system, I think some common features, of course, some people say ugly, some people say chaos, but some people use in their own projects and companies, but also my efforts to pay, but also perfectly in line with the Blog.Core program at the time envisaged in several major functions, there is a delay function is not implemented on hold for a long time - that is, by privilege level configuration button :

 

 

 

 

This was why I did not do it, there are two considerations, one, because I did not let you super administrator access, afraid of misuse of data, affect the rights of others to watch; 2, another consideration, they want a button violence spilled, and see if it is true test test account can delete the data. Then I started thinking, it's time to add to the mix this authority, that is no permission to delete, delete button is not displayed, but consider for a long time, a little knowledge is stuck to the point, is not thought of how dynamic event binding this do not understand it does not matter, my next article will talk the day before yesterday to provide a solution ideas and solutions by the group management @ cucumber and @Kawhi, shines, and finally achieve this functionality.

Contributing author: @ cucumber and @ Kawhi ;

Effect Preview: My major changes in order to prevent, currently only in the " Role Management " page, adds this feature, all the late replacement;

Online Address: http://vueadmin.neters.club

Github branches: a main branch;

Tips: Currently I still do not open Admin rights, so if you want to see the full effect, you can download a local, self-configuring view.

 

 

 

 Below to start formal talks, divided into two parts, the focus of knowledge + step instructions, so look at the steps when the direct hands on the line, do not bother why, Part III below - the highlights knowledge, will speak briefly.

 

Second, the detailed design step

1, the back-end fine-tuning, the Save button information

I do not know there is no junior partner remember, I'm backstage permissions system, the left side of the navigation bar has been automated, so-called automation, is already entirely to the database, no matter how much authority to increase, not front-end or back-end operations , should be configured to achieve the purpose, was it, I put on the left side of the menu buttons and knead to a table, was feeling very unreasonable, but now it is simple to change, thanks to the design ideas, so this we almost do not change anything, just need to put out the button information can be, there are two small points:

1, Permission.cs menu table Func new field, the method used to store the current button corresponding to the event;

2, / Permission / GetNavigationBar interface, remove the restriction IsButton == false, so that it can fit recursive menu;

//var rolePermissionMoudles = (await _permissionServices.Query(d => pids.Contains(d.Id) && d.IsButton == false)).OrderBy(c => c.OrderSort);
 var rolePermissionMoudles = (await _permissionServices.Query(d => pids.Contains(d.Id))).OrderBy(c => c.OrderSort);

3, in RecursionHelper.cs, add IsButton attribute database data, return to the front end Tree ride;

So we put the menu button data combined with the data together return to the front, you can view at:

 

 

 

Here, we first part - the back-end data is complete, of course, if you want to be more cool, more than can increase the field, such as style buttons, or other property, and so on and so on, where you must understand that I will not fine said.

Start from below, we began to say Blog.Admin project, please open VSCode, to modify our Vue project:

 

2, modify the background rights management, the Add button event

This step is very simple, that is the top of our field Func established to CRUD look like in the page, the specific code changes to their own.

 

 

 

 

3, the control "buttons" and not "Menu" to show the conflict

We just comes to the top, the menu button data combined with the open together out, that this time we need to check, and the menu does not show conflict, here I'll just say the place changes:

 

1, modify Sidebar.vue component that allows data button Do not show specific look at the code to understand, it is very simple;

2, modifying  the src \ Router \ The index.js injection of dynamic routing, filtering off the button data;

 

 

To here, our second part - the preparatory work to done, then, it is the top priority of this paper highlight of this design tool bar, and that specifically how to operate, this time I hope you can pause it, Do not look down, first in my mind to think about, according to my way of thinking, that is, the data also have buttons, how to design the common components of it? Consider five minutes it ......

 

Five minutes later, assuming you have thought about it, I began a formal statement.

 

4. Design toolbar components --Toolbar.vue

 

If it wants to make automated assembly, it must be abstracted, the first step is to create a component that is not similar to each page to write a bunch of code;

Actually, we have to be configured, not just the button to put forward, should also have such other <input /> Search box, and so on, should be placed in the toolbar;

Be sure to load or do not load, you can not show or hide, so that others will also see the elements of time to see;

 

To sum up, my design is in the form of a button, all referred to the top, renderings give us a show, this is the color I manually add delete, you can also add their own fields Configuration:

 

 

 

First we create the assembly, src \ Components \ Toolbar .vue, specific code is as follows:

<template>
  <el-col v-if="buttonList.length>0" :span="24" class="toolbar" style="padding-bottom: 0px;">
    <el-form :inline="true" @submit.native.prevent>
      <el-form-item>
        <el-input v-model="searchVal" placeholder="请输入内容"></el-input>
      </el-form-item>
      <!-- 这个就是当前页面内,所有的btn列表 -->
      <el-form-item v-for="item in buttonList">
        <!-- 这里触发点击事件 -->
        <el-button type="primary" @click="callFunc(item)">{{item.name}}</el-button>
      </el-form-item>
    </el-form>
  </el-col>
</template>
<script>
export default {
  name: "Toolbar",
  data() {
    return {
      searchVal: "" //双向绑定搜索内容
    };
  },
  props: ["buttonList"], //接受父组件传值
  methods: {
    callFunc(item) {
      item.search = this.searchVal;
      this.$emit("callFunction", item); //将值传给父组件
    }
  }
};
</script>

 

相信每个人都能看的懂,只是字面意思能看得懂,其中的核心知识点就是 List for渲染,父给子传值,子给父传值,我下文会重点讲到,其中 buttonList  数组的格式,很简单,你可以自己后端封装一下,我这里就偷懒了,直接使用的菜单的数据结果,就是上边我 localstorage.routes 中的结构,毕竟我把按钮和菜单共有一套嘛。

那现在我们设计好了子组件——工具栏,接下来就要设计父组件了,传递数据和接受子组件广播了。

 

 

5、将按钮事件绑定到组件上

刚刚我们说到了 ,在 Toolbar.vue 中,核心的内容,就是把动态的事件方法给推送到一个个父组件上,这里是以 Role.vue 页面举例的,所有用到了  $emit("callFunction", item)  方法,这个如果你开发vue的话,肯定都知道这个的,这个父子通讯实例中,使用很多,具体的我在之前的文中中,也讲到了,你可以看看,这里不细说,说白了一句话,就是子组件执行父组件方法。二十║Vue基础终篇:传值+组件+项目说明。其实到这个地方,我也想到了,但是问题来了:你可以先看看 emit 的用法,使用 emit 一般都是传递数据,但是如果传递 function 的话,肯定也是一个 name 的字符串,那父组件接受到这个 function name 的时候,很容易当成一个 data,如果强行执行,他们又不在一个对象里,因为有闭包,如何让页面执行这个 function 呢?我思考了很久(说明自己学的不到家)。


这个就是这两个月来困扰我的地方,前边的思路和后边的 Table 隔离我都想到了,只是这里我没有想到,看来还是需要一些高级前端的朋友哟,前天听到了一个 apply 方法后,我豁然开朗,原来可以这样,那下边我就详细的说一说,如何父组件执行事件:

在 src\views\User\Roles.vue 页面呢,修改我们的工具栏使用:

 

 

 

这种引用组件,在data中,定义 buttonList ,就不说,重点还是要理解 @callFunction 这个必须要和子组件的 $emit 中的方法名一致。然后我们定义 callFunction,用来动态执行一个个事件:

    callFunction(item) {//这个 item 就是我们的 permission.cs 数据
      this.filters = {
        name: item.search
      };//这里是把子组件中的 search 内容,也接受过来
      this[item.Func].apply(this, item);//核心就是要执行 apply 方法
    },

 

是不是很简单,难点就在于,.apply()这个方法,下文会说到。这个 this ,就是当然父组件的内容,就是我们执行可以在子组件来调用父组件的方法了

 

 

 

这里再说下

 

6、父组件获取 ButtonList 数据

上边我们也说到了,我们把 button 和 菜单揉在一起了,所以我们很简单操作一下之前的数据就行,做一下筛选:

   // 在 mounted 钩子中,调用 router
   let routers = window.localStorage.router
      ? JSON.parse(window.localStorage.router)
      : [];
    this.getButtonList(routers);

   // 定义方法,目的我为了递归
    getButtonList(routers) {
      let _this = this;
      routers.forEach(element => {
        let path = this.$route.path.toLowerCase();
        if (element.path && element.path.toLowerCase() == path) {
          _this.buttonList = element.children;
          return;
        } else if (element.children) {
          _this.getButtonList(element.children);
        }
      });
    }

 

OK,数据准备完毕。

 

7、修改 Table 组件,将工具栏与 Table 逻辑隔离

到了这里就是最后一步了,我们把之前的 tabel 右侧 “操作栏” 删掉,统一放到顶部,然后绑定数据,就可以加载出来了,

 

 

 

现在我们把操作栏给取消了,但是我们如何获取 scope.row  呢?是不是很麻烦,要修改很多呢,其实不是的。

 

8、Table 改为单选,通过点击,选择某行

这个功能特别简单,思路就是通过单击某一行,来获取这个 table 的 row,这个 element 官网写的很详细,我就简单的说一下吧:

    //触发事件,获取到这个row
    selectCurrentRow(val) {
      this.currentRow = val;
    },


    <!--列表-->
    <el-table
      :data="users"
      highlight-current-row
      v-loading="listLoading"
      @current-change="selectCurrentRow"
      style="width: 100%;"
    >

 

然后只需要简单的修改一下我们的 edit 和 delete 方法即可,因为我们已经拿到了这个 row:

 

 

 

 搞定啦!是不是很简单,几乎没有修改什么,感觉之前设计的方案还可以吧,至少扩展还是很不错的!

到了这里,我们的动态按钮权限功能,就已经完全做完了,一个八个步骤,大家动手起来,搞一搞吧。

 

三、重点知识解析

 

1、组件 ——子传父 & 父传子

 这块内容呢,其实我们都已经讲过很多遍了,父传子很简单,只需要定一个自定属性即可,然后子组件接受,比如上文中的:

  <toolbar :buttonList="buttonList" @callFunction="callFunction"></toolbar>

 name: "Toolbar",
  data() {
    return {
      searchVal: "" //双向绑定搜索内容
    };
  },
  props: ["buttonList"], //接受父组件传值

 

比较复杂的就是 子传父 了,重点还是要了解一些 $emit 这个api,二十║Vue基础终篇:传值+组件+项目说明 我这篇文章写的还算是详细,如果还是不懂,咱们再一对一讨论吧。

 

 

2、动态事件绑定—— apply

 这个apply 有点儿想 call 回调函数,首先,每个函数都包含两个非继承而来的方法:.apply()和 .call()。这两个方法的用途都是在特定的作用域中调用函数,实际等于设置函数体内this对象的值。

这两个方法接收的参数可以分为两个部分,

  第一部分是在其中运行函数的作用域,如果就在当前函数体中运行,就可以直接使用this值,如果在window作用域中使用,可以传入window值,这样,可以实现扩充作用域;

  第二部分是参数组,在apply中可以传入Array实例,也可以是arguments对象;在call中,传递给函数的参数必须逐个列举;如果没有参数,这个部分可以省略。

首先我们来看看网上apply()方法的定义:

1. apply()方法能劫持另外一个对象的方法,继承另外一个对象的属性

2.Function.apply(obj,args)方法能接收两个参数

3.obj:这个对象将代替Function类里this对象

4.args:这个是数组,它将作为参数传给Function(args–>arguments)

 


举个例子,如下所示:

function sum(num1,num2){
  return num1+num2;
}

//两个数相等就相加,不相等就相乘
function mul(num1,num2){
  if(num1 != num2){
    return num1*num2;
  }else{
    return sum.apply(this,arguments);
    //可以为 sum.apply(this,[num1,num2])或sum.call(this,num1,num2);
  }
}

console.log(mul(5,6));   //30
console.log(mul(6,6));   //12

 

说句简单的,我认为就是在其他地方,去调用某一个方法,很重要的一个点,就是 this 这个到底指向什么,自己可以好好调调。

 

 

3、动态路由过滤—— addRoutes

 这个在上边的步骤里我没有说到,是因为我们把 按钮 给放出来以后,在动态菜单路由的时候,会出现重复的问题,所以我们就需要坐下过滤,注意这个不是错误,是警告,意思就是我们把一些重复的东西添加到路由里了,路由会忽略掉,只不过给大家一个 warm 而已。

 

 

 

所以呢,我做了一个过滤,封装了下 route.addRoutes——在 src\router\index.js 中,我们过滤下重复路由,还是递归:

router.$addRoutes = (params) => {

    var f = item => {
        
        if (item['children']) {
            item['children'] = item['children'].filter(f);
            return true;
        } else if (item['IsButton']) {
            return item['IsButton']===false;
        }  else {
            return true;
        }
        
    }
    
    var paramsFilt = params.filter(f);

    router.addRoutes(paramsFilt)
}

 

然后咋其他的地方,将 router.addRoutes 统一都换成 router.$addRoutes 。但是这个目前还有一些小问题,我会后期继续优化。

 

 

四、Github && Gitee

 

Core: https://github.com/anjoy8/Blog.Core

 Vue: https://github.com/anjoy8/Blog.Admin

 

Guess you like

Origin www.cnblogs.com/laozhang-is-phi/p/11614437.html