Vue based on Element button permission implementation solution

Vue based on Element button permission implementation solution

Background requirements: The ERP system needs to add a "button permission control" function, and the control granularity of permissions should be extended to the button level.

expected

There are two interactive modes for button permission control: "invisible" and "visible but not clickable".

Invisible

The invisible interaction method is relatively simple. We can use v-if to control whether it is displayed. You can use v-show, but it is not safe enough. After all, v-show only changes the style to display: none, and it still exists in the real DOM rendering, so it is recommended to use v-if to control the invisible.

Visible but not clickable

"You can see, but you can't."

  • Style control (you need to add a disabled style), such as cursor: not-allowed, graying out, etc.
  • Not clickable, that is, to disable or block click events, it seems that preventDefault/stopProgration can achieve this;

The final product requirement chose "visible but not clickable", probably because invisible was considered too simple. (¬_¬)

Idea Exploration

  • Add a wrapper function to the callback function of the button click event to control its permissions and intercept and trigger the event. It is like making a proxy, which is a bit like a high-order component (but it changes the existing business too much, and each @click binding function must be modified one by one, so this solution is abandoned);
  • To prevent the button click event from bubbling and triggering, it seems that preventDefautl/stopProgration can be used. It feels like the event can be monitored on the DOM element in the form of instructions. If it is allowed, the event will be executed normally, otherwise it will be blocked;

Practice plan

Finally, we chose the instruction method to expand at the lowest cost and avoid changing the existing business code logic.
Elements that need click hijacking for permission control:

  • el-button
  • btn-wrapper (self-encapsulated component)
  • div/span/a etc tags

Please see below for the specific implementation plan:

Permission entry: Vuex control, global use

//After the user logs in, get the user's permission CODE code and store it in the store
this.$store.commit('SET_AUTH_CODE', authCodeList);

SET_AUTH_CODE: (state, acthCode) => {
 if (acthCode) {
   state.autoCodeList = acthCode;
 }
 setStore({
  name: 'autoCodeList',
  content: state.autoCodeList || [],
 });
}

Defining permission instructions

const disableClickFn = (event) => {
  event && event.stopImmediatePropagation();
}

export const hasPermission = () => {
  Vue.directive('permission', {
    bind(el, binding) {
      let disable = true;
      if (autoCodeList.length && autoCodeList.includes(binding.value)) {
        disable = false;
      }

      if (disable) {
        el.classList.add('permission-disabled');
        el.setAttribute('disabled', 'disabled');
        el.addEventListener('click', disableClickFn, true);
      }
    },
    unbind(el) {
      el.removeEventListener('click', disableClickFn);
    }
  });
};

  • First, we use useCapture as true in the third parameter of addEventListener to trigger it during the capture phase, so the event listener here will take precedence over @click to trigger the callback;
  • Secondly, stopImmediatePropagation is used to prevent event bubbling and the triggering of other listeners of the same event;

If multiple event listeners are attached to the same event type on the same element, they will be called in the order in which they were added when the event is triggered. If you call stopImmediatePropagation() in one of the event listeners, the remaining event listeners will not be called. MSDN - stopImmediatePropagation

Add disabled CSS styles

.permission-disabled {
  position: relative;
  cursor: not-allowed !important;
  pointer-events: none; // Prevent elements from receiving mouse events border:none;
  background-image: none;
  &::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0px;
    right: 0px;
    height: 100%;
    z-index: 9;
    background: rgba(255, 255, 255, 0.5);
  }
}

A relatively unfamiliar CSS property, pointer-events, is used here.

The CSS3 pointer-events property specifies under what circumstances (if any) a particular graphic element can become the target of a mouse event. For more usage reference: MSDN - pointer-events

The use of pointer-events here is just an auxiliary function. It does not necessarily mean that the event listener on the element will never be triggered. If the descendant element has specified pointer-events and allows to become the event target, the parent element event can be triggered. And relying solely on CSS properties to control not clicking is still risky, so it is only used for auxiliary purposes here.

Global "permission judgment" tool function

import { getStore, } from '@/util/store';
const autoCodeList = getStore({ name: 'autoCodeList', }) || [];

export function hasPermission(authName) {
  return !(autoCodeList.length > 0 && autoCodeList.includes(authName));
}

Specific use

// Command method (oms/order/save here corresponds to the CODE permission code when the user logs in)
<el-button v-permission="'oms:order:save'">Save</el-button>

// Function method <el-button :disabled="hasPermission('oms:order:save')"></el-button>

This is the end of this article about the implementation of Vue-based Element button permissions. For more relevant Element button permissions, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue+elementUI component recursively implements foldable dynamic rendering multi-level sidebar navigation
  • Example code of vue + element ui to realize player function
  • Analysis of Vue element background authentication process
  • Vue+element+oss realizes front-end fragment upload and breakpoint resume
  • Solve the problem that the element DateTimePicker+vue pop-up box only displays hours
  • Vue imitates ElementUI's form example code
  • An example of implementing a tree component using Vue
  • Specific use of Vue+iview using tree controls
  • Implementation code of editable tree table in Vue
  • Vue Element front-end application development tree list component

<<:  Solution to the problem that the configuration file my.cnf in MySQL cannot be started due to permission issues

>>:  Docker uses busybox to create a base image

Recommend

Implementation of Vue package size optimization (from 1.72M to 94K)

1. Background I recently made a website, uidea, w...

How to deploy FastDFS in Docker

Install fastdfs on Docker Mount directory -v /e/f...

Summary of DTD usage in HTML

DTD is a set of grammatical rules for markup. It i...

Java+Tomcat environment deployment and installation process diagram

Next, I will install Java+Tomcat on Centos7. Ther...

Tutorial on using prepare, execute and deallocate statements in MySQL

Preface MySQL officially refers to prepare, execu...

How to start and restart nginx in Linux

Nginx (engine x) is a high-performance HTTP and r...

JavaScript to achieve custom scroll bar effect

In actual projects, the up and down scroll bars a...

Detailed explanation of the setting of background-image attribute in HTML

When it comes to pictures, the first thing we thi...

How to deploy redis in linux environment and install it in docker

Installation Steps 1. Install Redis Download the ...

Markup validation for doctype

But recently I found that using this method will c...

How to install MySQL 8.0 database on M1 chip (picture and text)

1. Download First of all, I would like to recomme...

Summary of some related operations of Linux scheduled tasks

I have searched various major websites and tested...

SQL implementation LeetCode (185. Top three highest salaries in the department)

[LeetCode] 185. Department Top Three Salaries The...

Implementation of the Pycharm installation tutorial on Ubuntu 18.04

Method 1: Download Pycharm and install Download a...