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

How to use the MySQL authorization command grant

The examples in this article run on MySQL 5.0 and...

Detailed explanation of MySQL combined index method

For any DBMS, indexes are the most important fact...

Six-step example code for JDBC connection (connecting to MySQL)

Six steps of JDBC: 1. Register the driver 2. Get ...

Detailed explanation of mysql5.6 master-slave setup and asynchronous issues

Table of contents 1. MySQL master-slave replicati...

About using Alibaba's iconfont vector icon in Vue

There are many import methods on the Internet, an...

How to keep running after exiting Docker container

Phenomenon: Run an image, for example, ubuntu14.0...

Getting Started with Vue 3.0 Custom Directives

Table of contents 1. Custom instructions 1. Regis...

Tutorial on installing PHP on centos via yum

First, let me introduce how to install PHP on Cen...

JavaScript basics for loop and array

Table of contents Loop - for Basic use of for loo...

Embed codes for several older players

The players we see on the web pages are nothing m...

Detailed explanation of HTML area tag

The <area> tag defines an area in an image ...

Example of Vue uploading files using formData format type

In Vue, we generally have front-end and back-end ...

Implementation of FIFO in Linux process communication

FIFO communication (first in first out) FIFO name...