vue2 el-button按钮禁用为什么失效了?

新手上路,请多包涵

vue2中使用template包裹了两个el-button,并且template添加了判断条件,但是当showSteps值变化为3时,其中设置了disabled的‘生成’按钮禁用属性失效,仍然可以点击,elementui版本:2.15.14;webpack版本:3.12.0,vue版本:2.7.16 代码如下

<template>
  <div>
    <el-input-number v-model="showSteps"></el-input-number>
    <el-button size="small" :disabled="!canSave">关闭</el-button>

    <template v-if="![3, 4, 6].includes(showSteps)">
      <el-button v-if="showEdit" size="small">edit</el-button>
    </template>
    <template v-if="showSteps === 3">
      <el-button type="success" size="small">赋值</el-button>
      <el-button type="primary" size="small" :disabled="!canSave">生成</el-button>
    </template>
    <template v-else>
      <el-button v-if="false" type="primary" size="small" :disabled="!canSave">next</el-button>
    </template>
  </div>
</template>

<script>
export default {
  data() {
    return {
      canSave: false,
      showSteps: 1,
      dataStep: 4,
    }
  },
  computed: {
    showEdit() {
      return this.showSteps <= this.dataStep && this.editStep !== this.showSteps
    }
  },
}
</script>

目前已知将template标签更换为span、或者为'生成'按钮添加key可以解决这个问题,求助各位是什么样原因导致了这个问题

阅读 1.2k
2 个回答

使用template标签包裹的话,必须严格的v-if + v-else-if + v-else判断就不会出问题

为什么用 v-if 判断会失效?

每个模块会单独挂载/销毁每一块 DOM,造成:

  • 条件切换时原有的 DOM 可能被销毁又重新创建;
  • 某些状态(比如绑定的 :disabled)会丢失或初始化异常;
  • 尤其在 template 里嵌套多个块的时候,Vue 的虚拟 DOM diff 策略可能出现不稳定行为。

为什么用 v-else-if 就没问题?

因为 v-if + v-else-if + v-else 是一个连续块,Vue 会把它们当作一个整体处理,不会销毁和重建 DOM,而是根据条件“启用或禁用当前分支”。 这样状态就不会中间被“抛失”,所有绑定(比如 :disabled)也会正确应用。这样就能保证:

  • 所有分支是“互斥”的;
  • Vue 渲染时只保留一个逻辑分支;
  • DOM 不被反复销毁与重建,响应式绑定更稳定。

那为什么将template换成span也是可以的?

原因是:<template> 本身不渲染成实际 DOM 元素

  • 每个 <template> 是“虚拟容器”,Vue 会动态添加/移除内部元素;
  • 如果条件快速变化(比如 condA → condB → condA),Vue 可能需要频繁地销毁/重建里面的 <button>;
  • 这会造成状态丢失,或者某些属性(如 :disabled)暂时失效。

span又是好的,原因:

  • <span> 是真实 DOM 元素,Vue 会保留这段元素,即使它当前不显示;
  • 因为真实 DOM 存在,Vue 的 Virtual DOM diff 算法会尽量复用已有 DOM,不会反复销毁重建;
  • 所以按钮状态更稳定,像 :disabled 不容易失效。

当然加key的原因这个就不用说了,显式根据key重新渲染保证渲染一致性。

如果 canSave 变量默认赋值的是 false 就是不禁用啊,如果要禁用的话得是 true 值呀,

<el-button :disabled="true">禁用的按钮</el-button>

图片.png


Edit

看起来是 diff 算法的问题,认为是同一个node节点了。
可以这样修改一下👇

<template v-if="![3, 4, 6].includes(showSteps)">
  <el-button v-if="showEdit" size="small">edit</el-button>
</template>
- <template v-if="showSteps === 3">
+ <template v-else-if="showSteps === 3">
  <el-button type="success" size="small">赋值</el-button>
  <el-button type="primary" size="small" :disabled="!canSave">生成</el-button>
</template>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题