likes
comments
collection
share

项目实现|v-show不生效的一个场景解析

作者站长头像
站长
· 阅读数 56

问题背景如下:

根据某数组的长度,对界面中,具有相对定位的按钮,进行显示和隐藏

项目实现|v-show不生效的一个场景解析

起初我使用了v-show进行操作,刷新界面,发现没用,我以为我眼花了,结果又验证了一次,果然v-show没有生效,所以我在本地复现了一下。

经过排查我发现代码中出现了一个很神奇的一处,就是在mounted中进行了js样式的赋值,完整代码如下:

<template>
  <div class="v-show-wrapper">
    <el-button type="primary"
               size="mini"
               class="el-button-position"
               v-show="buttonFlag">某按钮</el-button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      buttonFlag: false,
      value: 10
    }
  },
  mounted () {
    let el = document.getElementsByClassName('el-button-position')
    if (this.value === 10) {
      el[0].setAttribute('style', 'top:20px')
    }
  }
}
</script>

<style>
.v-show-wrapper {
  position: relative;
  height: 100%;
  width: 100%;
}
.el-button-position {
  position: absolute;
  top: 0;
  right: 10px;
}
</style>

问题感觉出来了,感觉是mounted中修改的样式,会冲突到v-show,但是看了v-show的官网介绍和mounted并没有发现2个有什么冲突

一开始感觉mounted中渲染出来了元素,按理说,在进行display:none 页面没有按钮才是合理的

就这样纠结了很久,我终于找到了点,v-show就是display:none,那display:none执行的时机是什么,还是会不执行?

v-show是直接作用在元素上,那就是内联样式style="display: none;"

终于我想起来了js样式和css样式的优先级

项目实现|v-show不生效的一个场景解析

看看这句话说的多好!!!参考css样式与js样式优先

但是也不对呀,我的代码里并没有直接操作display的属性,为什么display:none不执行

项目实现|v-show不生效的一个场景解析

看看这句话说的多好!!!参考【CSS】display、position、float 三者的优先级

因为我是绝对定位的按钮,所以默认是display: inline-block; 那display:none 因为优先级低 就不会执行了

接下来验证一下,不使用绝对定位

  mounted() {
    let el = document.getElementsByClassName('el-button-position')
    if (this.value === 10) {
      // el[0].setAttribute('style', 'top:20px')
      el[0].setAttribute('style', 'color:red')
    }
  },
.el-button-position {
  /* position: absolute;
  top: 0;
  right: 10px; */
}

期望的是v-show起作用,因为刚才分析的是 绝对定位 默认是display: inline-block; 覆盖了display:none

但是现在没有绝对定位了,但是display:none 还是没有起作用。

那就说明和display没有半毛钱关系,原因还没有找到

经过思考.......

再次验证自己的猜想:

    <el-button 
        type="primary"
        size="mini"
        class="el-button-position"
        style="display:none">
        某按钮
    </el-button>

    mounted() {
    let el = document.getElementsByClassName('el-button-position')
    if (this.value === 10) {
      // el[0].setAttribute('style', 'top:20px')
      el[0].setAttribute('style', 'color:red')
    }
  }

界面的按钮依然存在,并没有消失,所以走到这步说明已经和v-show 还有display:none 没有关系了,跳出思维定式

仔细看代码

项目实现|v-show不生效的一个场景解析

终于 看出来了!

setAttribute中的style会覆盖元素本身的style,看生命周期图,mounted的时候,元素已经挂载渲染完毕了 所以setAttribute里再执行就会进行覆盖

项目实现|v-show不生效的一个场景解析

类似于这种代码:

.box {
  color: red;
}
.box {
  color: green; // 覆盖前一个
}

去网上验证一下:参考DOM简介

项目实现|v-show不生效的一个场景解析

MDN解答:

项目实现|v-show不生效的一个场景解析

之前使用setAttribute老是感觉是追加新的属性,没想到是更新属性

转载自:https://juejin.cn/post/7283426137967689728
评论
请登录