如何从同级组件访问Vue组件元素属性

时间:2019-10-01 22:29:10

标签: javascript vue.js vue-cli

问题
我正在使用Vue CLI应用程序。有一个孙组件,需要访问另一个组件的元素的属性。它实际上只需要clientHeight属性。

component structure

因此 Content2.vue 组件需要访问以下元素的clientHeight属性:<div id="header"></div>(在 Header.vue 中)。

尝试的解决方案

  • 我尝试使用$refs。根据{{​​3}},$refs仅适用于与父/子直接相关的组件。

  • 我还考虑过将$refsclientHeight添加到商店(this stackoverflow answer)中,但这似乎有些过分。

  • 我总是可以放心使用vuexquerySelector。但是认为可能会有更好的结果。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

如果您完全确定CSS无法解决此问题,并且确实需要元素的clientHeight,则可以从以下选项中选择最差的解决方案:

  1. id实例的HeaderApp传递到ContentContent2。然后让Content2使用查询选择器获取高度。这似乎比让Content2拥有硬编码的id来得容易一些。
  2. Header计算自己的高度并将事件发送到App,然后将高度传递到Content,然后传递到Content2。请注意,如果高度不固定,您可能需要侦听调整大小事件。
  3. 执行(1)或(2),但将其存储在Vuex中或使用事件总线而不是传递参数。

您选择的哪一项取决于问题中所提出的内容。

如果没有其他组件需要知道Header的高度,我会选择(1)。

如果其他组件需要知道Header的高度,或者Header实例是否处于确定其动态高度的最佳位置,我会选择(2)。

如果我已经在使用某种全局状态管理器,我会选择(3)。

答案 1 :(得分:1)

截至目前的可行解决方案:

  • $refs

      在声明它们的组件上设置
    • $refs。如果要访问它,可以像this.$parent.$parent.$children[0].$refs.name一样via $parent
    • 优点:快速又脏。有效。
    • 缺点:非常脆弱的耦合。从train wreck中可以看到,没有多少程序员会认为它是一个很好的解决方案。
  • Vuex

    • 获取clientHeight并将其添加到商店。 (不要添加$refs,它们不是数据对象)
    • 优点/缺点:似乎过于矫kill过正。如果您还没有Vuex,并且仅为此添加它,那就可以了。如果不是这种情况,则Vuex商店是存储诸如clientHeight之类的全局信息的“自然”场所之一。知道树中远处的组件共享的clientHeight在商店中,几乎不会令您的项目的任何新开发人员感到惊讶。
  • 香草

    • 使用querySelectorgetElementById
    • 优点/缺点:这里的问题是耦合。并且是一种隐藏的,更糟糕​​的一种。这是一个快速而又肮脏的解决方案,将是原型设计和所有产品的最佳首选。但是,当应用程序成熟时,这种隐藏的依赖性非常危险。
  • this.$root: The root instance

    • 在根组件中创建一个data(),并在其中具有clientHeight属性。现在,您可以使用this.$root.clientHeight = newValue从任何组件中进行设置,也可以使用this.$root.clientHeight进行读取。
    • 优点:如果您不希望/不需要完整的Vuex商店,则很好。可以从树中的任何组件轻松访问。反应性的。
    • 缺点:您必须在根组件中声明data()。需要有人照顾,因为有人可能会开始在此处添加属性,这很快会变成一种糟糕的情况(Vuex的缺点没有缺点)。如果发生这种情况,您应该开始使用Vuex。
  • Event Hub/bus

    • 创建一个Vue实例并将其用作事件中心/总线。这类似于$root解决方案,不同之处在于,您可以直接发送和接收事件,而不是直接设置数据。
    • 优点:解耦,根本不需要data()
    • 缺点:仍然需要创建充当集线器/总线的实例(尽管您也可以使用$root)。这里的坏处是这种解决方案对您的情况而言并不自然。 clientHeight的设置无论如何都不是事件(或者是?),所以这可能是不自然的。
  • 传递道具

    • 组件通过事件向上传递属性,通过道具向下传递属性,一次传递一跳。换句话说,Header.vue(通过事件)传递给clientHeight(通过事件),App.vue(通过道具)传递给Content.vue,然后向下传递到Content2.vue(通过道具)。
    • 优点:不需要任何全局存储或$root / hub / bus实例。每个组件(事件或道具)的签名(事件或道具)中传递的每一个数据都是清楚的。
    • 缺点:四处都是耦合;只是为了过去的样板;可以说,使用Vuex这样的商店的主要原因之一。
  • Dependency injection via provide/inject又名“远程道具”

    • 与道具不同,您将clientHeightHeader.vue传递给App.vue,而App.vue将声明一个provide函数。然后Content2.vue将在其中使用inject。有关更多信息,请参见docsdemo
    • 缺点:在Vue应用中不是很常见,更多的新手开发人员可能不知道。仍然需要通过事件将clientHeightHeader.vue传递到App.vue,尽管那只是一跳。
    • 优点:数据从App.vueContent2.vue的传递是非常干净的,毕竟,这正是provide的目的。

就个人而言,我会选择Vuex的,特别是如果您已经配置了Vuex。如果不是这样,我会使用$root,但是在第一次使用Vuex的承诺下,就需要全局使用任何其他道具。

答案 2 :(得分:0)

那么您可以尝试使用一种称为“事件总线”的东西。您可以从全局事件总线上的任何内容向另一个内容发出事件,然后其他内容侦听此事件。然后,您执行一个在事件总线上发出高度的函数,然后您在该事件上再次用“ on”侦听并执行一个函数

这可能会帮助您: https://alligator.io/vuejs/global-event-bus/