解决代码表单组件大量disable的麻烦,实现只读。只需要在需要的地方加上v-read-only
即可达到只读效果,快捷方便。
实现思路
- 父元素下添加一个遮罩层元素
- 遮罩层元素的显示隐藏由参数决定
要想简单快捷的实现,最好用的就是写一个遮罩层,通过遮罩来隔绝用户的操作。
原始代码如下:
<template>
<div class="resource-association-item">
<div v-if="visible" class="read-only"></div>
<!-- 真正的业务代码 -->
<div>
<div>配置项1</div>
<div>配置项2</div>
<div>配置项3</div>
<div>配置项4</div>
</div>
</div>
</template>
<script>
export default {
name: 'ResourceAssociationItem',
props: {
visible: {
type: Boolean,
default: false
}
}
}
<style lang="scss" scoped>
.resource-association-item {
display: flex;
align-items: center;
margin: 16px 0 22px 0;
justify-content: space-between;
position: relative;
.read-only {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: calc(100%);
background: rgba(255, 255, 255, 0.5);
z-index: 10;
}
}
</style>
vue2上代码
import Vue from 'vue'
const readOnly = {
bind(el, binding) {
const mask = document.createElement('div')
mask.className = 'read-only-mask'
const defaultOptions = {
top: '0',
left: '0',
width: '100%',
height: '100%'
}
const options = { ...defaultOptions, ...(binding.value || {}) }
mask.style.position = 'absolute'
mask.style.top = options.top
mask.style.left = options.left
mask.style.width = options.width
mask.style.height = options.height
mask.style.background = 'rgba(255, 255, 255, 0.5)'
mask.style.zIndex = '10'
mask.style.cursor = 'not-allowed'
el.style.position = 'relative'
el.appendChild(mask)
mask.style.display = options.visible ? 'block' : 'none'
el._readonlyMask = mask
},
update(el, binding) {
if (el._readonlyMask) {
const options = { ...el._readonlyMask.dataset, ...(binding.value || {}) }
el._readonlyMask.style.display = options.visible ? 'block' : 'none'
el._readonlyMask.style.top = options.top
el._readonlyMask.style.left = options.left
el._readonlyMask.style.width = options.width
el._readonlyMask.style.height = options.height
}
},
unbind(el) {
if (el._readonlyMask) {
el._readonlyMask.remove()
delete el._readonlyMask
}
}
}
Vue.directive('readOnly', readOnly)
vue3 版本
const readOnly = {
beforeMount(el, binding) {
let mask = null;
if (!el._readonlyMask) {
mask = document.createElement("div");
mask.className = "read-only-mask";
} else {
mask = el._readonlyMask;
}
const defaultOptions = {
visible: true,
top: "0",
left: "0",
width: "100%",
height: "100%",
};
// 初始化遮罩样式
mask.style.position = "absolute";
mask.style.top = defaultOptions.top;
mask.style.left = defaultOptions.left;
mask.style.width = defaultOptions.width;
mask.style.height = defaultOptions.height;
mask.style.background = "rgba(255, 255, 255, 0.5)";
mask.style.zIndex = "10";
mask.style.cursor = "not-allowed";
el.style.position = "relative";
el.appendChild(mask);
el._readonlyMask = mask;
// 根据传递的值设置遮罩样式
readOnly.updateMaskStyle(el, binding);
},
updated(el, binding) {
console.log("updated called", binding.value); // 添加调试日志
readOnly.updateMaskStyle(el, binding);
},
unmounted(el) {
if (el._readonlyMask) {
el._readonlyMask.remove();
delete el._readonlyMask;
}
},
updateMaskStyle(el, binding) {
const arg = binding.arg;
const value = binding.value;
if (arg === "visible") {
el._readonlyMask.style.display = value ? "block" : "none";
} else if (arg === "width") {
el._readonlyMask.style.width = value;
} else if (arg === "height") {
el._readonlyMask.style.height = value;
} else if (arg === "top") {
el._readonlyMask.style.top = value;
}
},
};
export default readOnly;
局部使用:
<template>
<div>
<div
v-read-only:visible="readonlyOptions.visible"
v-read-only:width="readonlyOptions.width"
class="content"
>
<p>这个区域是只读的</p>
</div>
<button @click="toggleReadOnly">切换只读状态</button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import readOnly from '../directives/readonly.js';
const readonlyOptions = reactive({
visible: true,// lcq 根据需求来
top: '0',
left: '0',
width: '100%',
height: '100%'
});
const toggleReadOnly = () => {
readonlyOptions.visible = !readonlyOptions.visible;
console.log(readonlyOptions.visible);
};
const vReadOnly = {
...readOnly
};
</script>
<style scoped>
.content {
padding: 20px;
border: 1px solid #ccc;
}
</style>
标签:el,style,const,readonlyMask,自定义,._,mask,vue2,vue3 From: https://www.cnblogs.com/lcaiqin/p/18285180