Access control (vue)
Often you encounter, the role of access control problem, if the page control, said the booing, but if the current page is partly visible the invisible, which is some trouble, if it is coupled with more stringent conditions. Before simply v-if
controlled, and now want to try the command (these operations have been online mode)
reference
Reference vue-element-admin - Instruction
Scenarios
- Access control
- dom hidden (not recommended)
- Deleted directly from the dom node
- Make changes based on incoming data dynamically
Code
Needs: the need to achieve a modification of the module based on dynamic parameters
test.vue
template
<div class="test-height"> <!-- 指令调用,status是动态参数 --> <h1 v-permission="{ role: ['so'], status }">test</h1> </div>
js
import permission from '@/directives/permission' export default { ... directives: { permission }, data () { return { status: false } }, mounted () { // 动态修改参数 setTimeout(() => { this.status = !this.status }, 1000) } }
permission.js
import store from '@/store' const permission = (el, binding, vnode, oldVnode) => { const { value, oldValue } = binding if (!value || (value.role && !Array.isArray(value.role))) { throw new Error(`need roles! Like v-permission="{ role: ['admin','editor'], [status 可传 boolean]}"`) } // 绑定的参数 const status = value.hasOwnProperty('status') ? value.status : false const roles = store.getters && store.getters.roles const permissionRoles = value.role || [] const hasPermission = roles.some(role => { return permissionRoles.includes(role) }) if (!hasPermission || (hasPermission && status)) { /** * TODO: * 1. 给父元素添加唯一id * 2. 同时找到子元素当前父元素的第几个位置 */ const rid = getRandomId() const index = getChildInParentPosition(el) el.parentNode.setAttribute('id', rid) el.dataset.id = rid el.dataset.index = index el.parentNode && el.parentNode.removeChild(el) } // 判断条件 if (oldValue && oldValue && oldValue.status === true && value.status === false) { // 此处会在 update时触发 const { index, id } = el.dataset const parent = document.getElementById(id) // 根据index找到需要插入父节点的位置 parent.insertBefore(el, Array.from(parent.children)[index]) } } export default { // 此处父元素存在 inserted: permission, // 此处数据更新 update: permission }
Randomly generated id
function getRandomId () { var randomId = 'yxyxyxxyxyy'.replace(/[xy]/g, function (item) { var n = Math.random() * 12 | 0 var v = item === 'x' ? n : (n & 0x3 | 0x8) v = item === 'y' ? 'abcdefghijklmnopqrstuvwsyz'.substr(Math.random() * 26 | 0, 1) : v return v.toString(16) }) return randomId }
Find the position of the child node in the parent node
function getChildInParentPosition (node) { // 用来保留子元素 【cloneNode(true) 深度克隆】 const Parent = node.parentNode.cloneNode(true) let key = -1 Array.from(Parent.children).filter((item, index) => { // 判断子节点是否相同 【isEqualNode】 if (item.isEqualNode(node)) { key = index } }) return key }
Renderings
- Not displayed by default, the data show back
- Individual elements
Multiple elements
- The default display, the data do not show back
Individual elements
Multiple elements
to sum up
- Although it is possible to solve the basic needs, but there are still problems, if siblings are access control, I am afraid that when the echo, be displaced
- Therefore recommend or use
v-if
- Above, can only deal with simple, some complex still struggling
- When instruction is executed, the corresponding relationship in advance to get the parent node and child nodes, and then
update
, the acquired globally, thus generatedid
must be unique - If you want to use for other scenes, we need to add a parent element need access control, while ensuring the child elements unique to
Knowledge Point
cloneNode(true)
Use the depth of cloning due to the changes in real time because the parent element is used, you can keep the child nodesisEqualNode
It used to determine whether the same two child nodes (long knowledge)update
, The need to add a node to the parent node, this timevnode, oldVnode
isparent
not the value of