使用Vuejs获取元素高度

54

我想获取一个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>


https://dev59.com/xXRB5IYBdhLWcg3wv5o_#526352 - Philipp Sander
3
你能否创建一个翻制品?看起来它运行良好:https://jsfiddle.net/wostex/63t082p2/84/ (当然,如果你的方法返回高度,因为在你的代码中你什么也没有返回)。 - Egor Stambakio
实际上我的组件有很多行和方法。我在这里简化了它。但是我不明白为什么它返回的数字比实际高度要小(当检查元素时)。这是一个加载问题吗? 难道 mounted 不应该在所有东西加载完后运行方法吗? - Juliane Blier
如果在简单情况下它可以正常工作,但在有更多代码的情况下无法正常工作,则很可能是其他一些代码在加载过程中延迟执行并以改变高度的方式修改DOM。如果是这种情况,那么您需要在DOM修改代码执行后更晚地调用matchHeight方法。 - RonC
但是挂载是在组件加载的最后一步,对吧?渲染后没有修改。它只是显示。 - Juliane Blier
显示剩余3条评论
5个回答

73

你现在这样做也可以。但是还有一种Vue专用的方法,通过ref属性实现。

 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://v2.vuejs.org/v2/api/#vm-refs 更新: 一些人留言称上述解决方案对他们无效。该解决方案提供了概念但没有完整的示例代码,因此我通过以下代码增强了我的答案,以演示相关概念。

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",这似乎是原因,对吗? - Juliane Blier
什么问题? - RonC
该列表没有被考虑在内,就好像它没有被显示出来一样,但实际上它确实存在。 - Juliane Blier
@christopherclark - 我可能应该留下一条评论让你知道,因为你的评论,我更新了我的回答,包括完整的工作代码。 - RonC
1
@gman,你为什么把我完全可用的代码改成了三个段落?实际上,唯一真正改变的是代码呈现的顺序以及html headbody标签。看起来编辑后的版本对人们来说比我提供的原始代码更没有用。鉴于您的声誉,毫无疑问您在进行更改时一定有积极的目的... - RonC
显示剩余5条评论

23

解决这个问题花费了很多时间。最初我尝试按照Ron C的回答进行操作,但是尝试获取this.$refs.infoBox.clientHeight;却无法正常工作,返回undefined。

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

哇!我不知道他编写的代码为什么对他和其他人有效,但是没有任何叫做clientHeight的属性。最终在$el里面找到了它。

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

这对我很有效。

更新

使用nuxt时,this.$refs.infoBox.$el.clientHeight;没有效果。但Ron C的回答适用于这种情况。在使用@vue/cli时,this.$refs.infoBox.$el.clientHeight;似乎可以正常工作。


1
你所看到的对我来说非常有趣和令人困惑。McWayWeb最近提出了一个更改我的答案,按照你建议的方式添加$el。我最初批准了该编辑,但后来它却破坏了我的答案,导致“运行代码片段”按钮产生错误“无法读取未定义的'clientHeight'属性”。因此,我撤销了编辑,并且现在它又可以正常工作了。我真的很好奇,当您点击我的答案中的“运行代码片段”按钮时,它是否会无错误地运行,并且这两个框的高度是否相同? - RonC
我在我的机器上使用最新的Vue和Vue-cli运行它。 - Mayank Kumar Chaudhari
非常有趣。我刚刚更新了我的答案,使用了最新版本的Vue,即2.6.12,之前使用的是2.2.5,当你点击“运行代码片段”按钮时,答案仍然有效。所以也许在命令行界面和浏览器中运行代码存在差异?相当奇怪。 - RonC
1
我并不是在批评,只是想理解一下。我不使用CLI,在我的情况下,我从CDN加载vue作为js文件,并在浏览器中运行。我的收获是,如果使用CLI,则您的答案是人们需要的答案,而如果从CDN或本地加载vue作为js文件,则我的回答是他们需要的答案。在这里拥有两个答案是很好的。 - RonC
1
这与vue-cli无关,而是与您添加ref的位置有关。如果它是Vue组件,则ref指向组件本身,该组件具有$el属性。如果ref放置在常规HTML标记上,则没有Vue组件,因此ref直接指向HTML元素。 - shabushabu
显示剩余3条评论

5
我会使用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>


0

在我的情况下,它按照以下路径找到了clientHeight

this.$refs.infoBox.$el.nextElementSibling.clientHeight


0

小提示 - 我也遇到了访问 $el 的问题(返回 undefined)。使用 vue/typescript 时,以下方法可行:

console.log('scriptPanel: mounted: sizes: ', (this.$refs.scriptSheet! as any).$el.clientHeight)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接