【问题标题】:Get element height with Vuejs使用 Vuejs 获取元素高度
【发布时间】:2017-12-10 10:47:29
【问题描述】:

我想获取一个 div 的高度,以使另一个 div 的高度与之匹配。我使用了 clientHeight 方法,但它没有给我返回好的值(较小的值)。实际上,它似乎在所有元素都被充电之前返回了一个高度。 在网上进行了一些研究后,我尝试将 window.load() 延迟到所有费用都已收费,但效果不佳。一些想法?

mounted () {
  this.matchHeight()
},
matchHeight () {
  let height = document.getElementById('info-box').clientHeight
}
<div class="columns">
  <div class="left-column" id="context">
  <p>Some text</p>
  </div>
  <div class="right-column" id="info-box">
    <img />
    <ul>
      some list
    </ul>
  </div>
</div>

【问题讨论】:

  • 你能创建一个复制品吗?它似乎工作正常:jsfiddle.net/wostex/63t082p2/84(当然,如果你从你的方法返回高度,因为在你的代码中你什么都不返回)。
  • 其实我的组件有很多行和方法。我在这里简化了。但我不明白为什么它返回的数字小于实际高度(检查元素时)。是加载问题吗?不应该在加载所有内容时运行该方法吗?
  • 如果它在简单的情况下有效,但在有更多代码的情况下无效,那么很可能其他一些代码在加载过程中运行较晚并以这种方式修改 DOM至于改变高度。如果是这种情况,那么您需要在 DOM 修改代码执行后的加载过程中稍后调用 matchHeight 方法。
  • 但是在加载组件的那一刻,mounted 是最后一步,不是吗?渲染后没有任何修改。它只是显示

标签: javascript html node.js vue.js vuejs2


【解决方案1】:

花了很多时间⌚解决了这个问题。最初我试图通过Ron C 来回答。尝试获取 this.$refs.infoBox.clientHeight; 没有成功 - 它给出了 undefined。

然后我探索了this.$refs.infoBox 对象。

哇!!!我不知道他编写的代码如何为他和所有其他人工作,但没有任何名为clientHeight 的属性。终于在$el里面搞定了。

所以我们需要用this.$refs.infoBox.$el.clientHeight;替换this.$refs.infoBox.clientHeight;

这对我来说效果很好。

更新

虽然使用 nuxt this.$refs.infoBox.$el.clientHeight; 不起作用。但Ron C 的答案适用于这种情况。 this.$refs.infoBox.$el.clientHeight; 似乎在使用 @vue/cli 时有效

【讨论】:

  • 你所看到的对我来说非常有趣和莫名其妙。 McWayWeb 最近提议更改我的答案,以您建议的方式添加 $el。我最初批准了该编辑,但随后它破坏了我的答案,因此“运行代码片段”按钮会产生此错误“无法读取未定义的属性'clientHeight'”。所以我恢复了编辑,它现在又可以工作了。我真的很好奇,当您单击我的答案中的“运行代码片段”按钮时,它是否运行没有错误并且两个框的高度相同?
  • 我用最新的 vue 和 vue-cli 在我的机器上运行它
  • 非常有趣。我刚刚更新了我的答案以使用最新版本的 vue 2.6.12,它使用的是 2.2.5,当您单击“运行代码片段”按钮时,答案仍然有效。那么,通过 cli 运行代码与在浏览器中运行代码之间可能存在差异?很奇怪。
  • 我没有批评。只是试图理解。我不使用 cli,在我的情况下,我将 vue 作为 js 文件从 cdn 加载并在浏览器中运行。从中可以得出的结论是,如果使用 cli,您的答案是人们需要的答案,而如果从 cdn 或本地将 vue 作为 js 文件加载,我的答案是他们需要的答案。在这里有两个答案很好。
  • 它不应该与 vue-cli 有任何关系,而是与您将 ref 添加到的位置有关。是不是 Vue 组件,那么 ref 指向的是组件本身,它有一个 $el 属性。如果 ref 放在一个普通的 HTML 标签上,那么就没有 Vue 组件,所以 ref 直接指向 HTML 元素。
【解决方案2】:

你这样做的方式很好。但是通过ref 属性还有另一种特定于 vue 的方式。

 mounted () {
   this.matchHeight()
 },
 matchHeight () {
   let height = this.$refs.infoBox.clientHeight;
 }

    <div class="columns">
        <div class="left-column" id="context">
            <p>Some text</p>
        </div>
        <div class="right-column" id="info-box" ref="infoBox"></>
            <img />
            <ul>
                some list
            </ul>
        </div>
    </div>

在这种情况下,由于您只是获得了价值,因此无论您使用原始的 getElementById 方法还是 vue 特定的 ref 方法都无关紧要。但是,如果您在元素上设置值,那么最好使用 ref 方法,以便 vue 了解该值已更改,并且如果需要更新该节点,则可能不会用原始值覆盖该值DOM。

您可以在这里了解更多信息:https://vuejs.org/v2/api/#vm-refs

更新

一些人留下了上述解决方案对他们不起作用的 cmets。该解决方案提供了概念,但没有提供完整的工作代码作为示例,因此我使用下面演示概念的代码来扩充我的答案。

var app = new Vue({
    el: '#app',
    data: function () {
        return {
            leftColStyles: { },
            lines: ['one', 'two','three']
        }
    },
    methods: {
        matchHeight() {
            var heightString = this.$refs.infoBox.clientHeight + 'px';
            Vue.set(this.leftColStyles, 'height', heightString); 
        }
    },
    mounted() {
        this.matchHeight();
    }

});
.columns{width:300px}
.left-column {float:left; width:200px; border:solid 1px black}
.right-column {float:right; border:solid 1px blue; }
<div id="app">
    <div class="columns">
        <div class="left-column" id="context" v-bind:style="leftColStyles">
            <p>Some text</p>
        </div>
        <div class="right-column" id="info-box" ref="infoBox"> 
            <img />
            <ul>
                <li v-for="line in lines" v-text="line"></li>
            </ul>
        </div>
    </div>

</div>

 <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
 

这是浏览器中的结果截图:

注意:
我的回答假设您是从 cdn 或本地加载 vue.js 到浏览器并在那里执行它。相反,如果您是通过 cli 运行代码而我的答案对您不起作用,请参阅 @mayank1513 的答案。

【讨论】:

  • 谢谢,我试过你的解决方案,但同样的问题。我注意到包含列表的 div 没有被考虑在内。它只返回图像的高度。但是列表中有一个v-if="someVariable",好像是这个原因,不是吗?
  • 有什么问题?
  • 该列表没有被考虑在内。好像没有显示,但确实显示了。
  • 列表是在服务器端还是客户端生成的(例如使用 v-for)?
  • @gman,你为什么将我的代码从一个完整的示例更改为三个片段?唯一真正改变的是代码显示的顺序以及htmlheadbody 标签。似乎编辑后的版本对人们的用处不如我提供的原始代码。考虑到你的声誉,毫无疑问,你做出改变的目的是积极的......
【解决方案3】:

我会使用 flexbox 来实现等高的列 https://css-tricks.com/snippets/css/a-guide-to-flexbox/

.container {
   display: flex;
}
.column {
   border: 1px solid;
   padding: 20px;
   width: 150px;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <div class="container">
        <div class="column">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ac dui sed erat venenatis fermentum. Nulla tempus, magna
            sit amet ornare fringilla, ligula quam faucibus urna
        </div>
        <div class="column">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        </div>
    </div>
</body>
</html>

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 2021-04-24
    • 1970-01-01
    • 2016-05-11
    • 2018-10-04
    • 1970-01-01
    • 2014-09-14
    • 2011-08-05
    • 2013-12-28
    相关资源
    最近更新 更多