tab vue 禁用_[Vue]自定义指令禁用所有表单元素

背景

最近几个项目都有流程式的表单输入。产品提出,在上一步的表单提交完毕之后,不能够修改但是依然要展示给用户(用户在填写下一步的表单时可能需要参照上一步表单中的内容)。

最初因为项目工期紧张,直接采用了对表单容器添加pointer-events: none;的作法。这样导致了很多问题,表单元素的样式并没有变为disabled状态,看上去还是可以点击的;使用Tab键索引到元素之后,还是可以触发表单行为;容器内的元素的滚动条失效。

方案

解决这个问题有一个很直接的思路,就是遍历所有的表单元素,添加disabled属性。但是项目中的表单元素很多,一个个添加,非常麻烦。有没有简单一点的办法呢?

利用fieldset元素

无意中看到张鑫旭老师个人空间中的一篇文章如何disabled禁用所有表单input输入框元素。阅读之后发现可以给form表单下添加一个fieldset元素,通过给这个fieldset元素设置disabled属性来统一禁用所有的表单元素。

表单标题

复制代码

自定义指令

因为项目使用的是vue框架,对于添加fieldset元素这种dom操作,我第一时间想到了自定义指令。

在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

自定义指令在平时也用过一些,例如常见的transfer-dom,clickoutside。借此机会也来自己实践一下。

因为我们的需求是要在form元素下插入fieldset,因此只要使用inserted钩子即可(保证form已经插入到dom当中),类似官网文档给出的autofocus的例子。

export default {

inserted(el, {

value

}) {

if (el.tagName.toLocaleLowerCase() === "form") {

wrapInner(el, value)

}

Array.from(el.querySelectorAll("form")).forEach(child => {

wrapInner(child, value)

})

}

};

复制代码

inserted钩子的第一个参数代表被绑定的元素。遍历这个元素的所有子代元素,找到form元素,执行包裹逻辑。需要注意的是,有可能这个元素本身就是form,所以增加一个判断。从第二个参数中解构出value属性(指令的绑定值,例如:v-disabled="true" 中,绑定值为 true)。

相信大家也比较少用原生api操作dom,这里详细说下如何完成对form内元素包裹fieldset标签。

jquery当中恰好有一个比较冷门的api:wrapInner可以满足我们的需求,来看下jquery的实现,核心逻辑如下

// The elements to wrap the target around

// 创建一个包裹元素

wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );

// 插入到目标元素的第一个子元素之前

if ( this[ 0 ].parentNode ) {

wrap.insertBefore( this[ 0 ] );

}

wrap.map( function() {

var elem = this;

while ( elem.firstElementChild ) {

elem = elem.firstElementChild;

}

return elem;

} ).append( this );

复制代码

参考jquery的实现思路,代码如下

function wrapInner(el, disabled) {

const wrapper = document.createElement('fieldset');

wrapper.disabled = disabled

//先插入一个空的fieldset标签到第一个元素之前

el.insertBefore(wrapper, el.firstElementChild);

const children = el.children,

len = children.length;

//把原来的每个子元素移入到fieldset内

//不是children[i],insertBefore是同步操作

//每次插入的都是第一个元素

for (let i = 1; i < len; i++) {

wrapper.insertBefore(children[1], null);

}

}

复制代码

总结

这样的方案要求表单元素被嵌套在form内。这里也可以看出HTML语义化的好处,除了代码可读性好,SEO有帮助,无障碍优化外,还能充分发挥出标签本身的特性。

如果项目使用一些第三方框架,例如element-ui,使用封装过的form组件(自带disabled属性)会更好一些。

代码传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值