如何从同级组件访问 Vue 组件元素 属性
How to access Vue component element property from sibling component
问题
我正在使用 Vue CLI 应用程序。有一个孙组件需要访问另一个组件的元素的属性。它真的只需要 clientHeight
属性.
所以Content2.vue组件需要访问这个元素的clientHeight
属性:<div id="header"></div>
(在Header.vue).
尝试的解决方案
我试过使用 $refs
。并且根据 $refs
仅适用于与 parent/child.
直接相关的组件
我也考虑过将 $refs
或 clientHeight
添加到商店 (vuex),但这似乎有点过头了。
我总是可以使用原版 querySelector or getElementById。但是觉得可能会有更好的东西。
感谢您的帮助!
那么你可以尝试使用一个叫做 "event bus" 的东西。您可以通过全局事件总线将任何内容的事件发送到另一个内容,而其他内容将监听此事件。然后你执行一个通过事件总线发出高度的函数,你再次用 "on" 监听这个事件并执行一个函数
如果您完全确定这不能用 CSS 解决并且您确实需要元素的 clientHeight
,您只能从以下选项中选择最不糟糕的解决方案:
- 将
Header
实例的 id
从 App
传递到 Content
再到 Content2
。然后让 Content2
使用查询选择器来获取高度。这似乎比 Content2
具有硬编码的 id
. 稍微不那么脆弱
- 让
Header
计算自己的高度并向 App
发出事件,然后将高度传递给 Content
,然后传递给 Content2
。请注意,如果高度不固定,您可能需要监听调整大小事件。
- 执行 (1) 或 (2),但将其存储在 Vuex 中或使用事件总线而不是传递参数。
您选择哪一个不仅取决于问题中呈现的内容。
如果没有其他组件需要知道 Header
的高度,我会选择 (1)。
如果其他组件需要知道 Header
的高度,或者如果 Header
实例处于确定其自身动态高度的最佳位置,我会选择 (2)。
如果我已经在使用某种全局状态管理器,我会选择 (3)。
截至今天可能的解决方案:
-
$refs
在声明它们的组件上设置。如果你想访问它,你可以via $parent
,比如this.$parent.$parent.$children[0].$refs.name
。
- 优点:快速且肮脏。有效。
- 缺点:耦合非常脆弱。从 train wreck 可以看出,没有多少程序员会认为它是一个好的解决方案。
Vuex
- 获取
clientHeight
并将其添加到商店。 (不要添加 $refs
,它们不是数据对象)
- Pros/Cons:似乎有些矫枉过正。如果您还没有 Vuex 并且只会为此目的添加它,那就是。如果不是这种情况,Vuex 存储是 "natural" 存储全局信息的地方之一
clientHeight
。几乎没有任何新的项目开发人员会惊讶地发现 clientHeight
,它由树中远处的组件共享,在商店中。
原版
- 使用querySelector or getElementById.
- Pros/Cons:这里的问题是耦合。并且是隐藏的,最糟糕的一种。这是一个快速而肮脏的解决方案,将是原型制作和所有方面的第一个很好的选择。但是这种隐藏的依赖在应用程序成熟后是非常危险的。
-
- 在根组件中创建一个
data()
并在那里有一个 clientHeight
属性。您现在可以使用 this.$root.clientHeight = newValue
从任何组件设置它或使用 this.$root.clientHeight
. 读取它
- 优点:如果您不 want/need 拥有一个完整的 Vuex 商店,那很好。可从树中的任何组件轻松访问。无反应。
- 缺点:您必须在根组件中声明
data()
。需要小心,因为有人可能会开始在那里添加属性,这很快就会变成一个糟糕的情况(有 Vuex 的缺点而没有优点)。如果发生这种情况,你应该开始使用 Vuex。
- 创建一个 Vue 实例并将其用作事件 hub/bus。这类似于
$root
解决方案,不同之处在于您不是直接设置数据,而是发出和接收事件。
- 优点:解耦,根目录中不需要
data()
。
- 缺点:仍然需要创建将充当 hub/bus 的实例(尽管您也可以为此使用
$root
)。这里不好的部分是这个解决方案对你的情况来说并不自然。 clientHeight
的设置在任何方面都不是事件(或者是?),所以这可能是不自然的。
传递道具
- 组件通过事件向上传递 属性,通过 props 向下传递,一次一跳。换句话说,
Header.vue
将 clientHeight
(通过事件)传递给 App.vue
,然后向下传递到 Content.vue
(通过 props),再向下传递到 Content2.vue
(通过道具)。
- 优点:不需要任何全局存储或
$root
/hub/bus 个实例。在每个组件的签名(事件或道具)中,每个数据传递(在我们的输出中)都是明确的。
- 缺点:四处耦合;仅供传递的样板;可以说是使用像 Vuex 这样的商店的主要原因之一。
Dependency injection via provide
/inject
又名 "long-range-props"
就我个人而言,我会选择 Vuex,特别是如果您已经配置了它。如果没有,我会使用 $root
,但承诺在第一时间使用 Vuex 任何其他道具在全球范围内都是必需的。
问题
我正在使用 Vue CLI 应用程序。有一个孙组件需要访问另一个组件的元素的属性。它真的只需要 clientHeight
属性.
所以Content2.vue组件需要访问这个元素的clientHeight
属性:<div id="header"></div>
(在Header.vue).
尝试的解决方案
我试过使用
$refs
。并且根据$refs
仅适用于与 parent/child. 直接相关的组件
我也考虑过将
$refs
或clientHeight
添加到商店 (vuex),但这似乎有点过头了。我总是可以使用原版 querySelector or getElementById。但是觉得可能会有更好的东西。
感谢您的帮助!
那么你可以尝试使用一个叫做 "event bus" 的东西。您可以通过全局事件总线将任何内容的事件发送到另一个内容,而其他内容将监听此事件。然后你执行一个通过事件总线发出高度的函数,你再次用 "on" 监听这个事件并执行一个函数
如果您完全确定这不能用 CSS 解决并且您确实需要元素的 clientHeight
,您只能从以下选项中选择最不糟糕的解决方案:
- 将
Header
实例的id
从App
传递到Content
再到Content2
。然后让Content2
使用查询选择器来获取高度。这似乎比Content2
具有硬编码的id
. 稍微不那么脆弱
- 让
Header
计算自己的高度并向App
发出事件,然后将高度传递给Content
,然后传递给Content2
。请注意,如果高度不固定,您可能需要监听调整大小事件。 - 执行 (1) 或 (2),但将其存储在 Vuex 中或使用事件总线而不是传递参数。
您选择哪一个不仅取决于问题中呈现的内容。
如果没有其他组件需要知道 Header
的高度,我会选择 (1)。
如果其他组件需要知道 Header
的高度,或者如果 Header
实例处于确定其自身动态高度的最佳位置,我会选择 (2)。
如果我已经在使用某种全局状态管理器,我会选择 (3)。
截至今天可能的解决方案:
-
$refs
在声明它们的组件上设置。如果你想访问它,你可以via$parent
,比如this.$parent.$parent.$children[0].$refs.name
。- 优点:快速且肮脏。有效。
- 缺点:耦合非常脆弱。从 train wreck 可以看出,没有多少程序员会认为它是一个好的解决方案。
Vuex
- 获取
clientHeight
并将其添加到商店。 (不要添加$refs
,它们不是数据对象) - Pros/Cons:似乎有些矫枉过正。如果您还没有 Vuex 并且只会为此目的添加它,那就是。如果不是这种情况,Vuex 存储是 "natural" 存储全局信息的地方之一
clientHeight
。几乎没有任何新的项目开发人员会惊讶地发现clientHeight
,它由树中远处的组件共享,在商店中。
- 获取
原版
- 使用querySelector or getElementById.
- Pros/Cons:这里的问题是耦合。并且是隐藏的,最糟糕的一种。这是一个快速而肮脏的解决方案,将是原型制作和所有方面的第一个很好的选择。但是这种隐藏的依赖在应用程序成熟后是非常危险的。
-
- 在根组件中创建一个
data()
并在那里有一个clientHeight
属性。您现在可以使用this.$root.clientHeight = newValue
从任何组件设置它或使用this.$root.clientHeight
. 读取它
- 优点:如果您不 want/need 拥有一个完整的 Vuex 商店,那很好。可从树中的任何组件轻松访问。无反应。
- 缺点:您必须在根组件中声明
data()
。需要小心,因为有人可能会开始在那里添加属性,这很快就会变成一个糟糕的情况(有 Vuex 的缺点而没有优点)。如果发生这种情况,你应该开始使用 Vuex。
- 在根组件中创建一个
- 创建一个 Vue 实例并将其用作事件 hub/bus。这类似于
$root
解决方案,不同之处在于您不是直接设置数据,而是发出和接收事件。 - 优点:解耦,根目录中不需要
data()
。 - 缺点:仍然需要创建将充当 hub/bus 的实例(尽管您也可以为此使用
$root
)。这里不好的部分是这个解决方案对你的情况来说并不自然。clientHeight
的设置在任何方面都不是事件(或者是?),所以这可能是不自然的。
- 创建一个 Vue 实例并将其用作事件 hub/bus。这类似于
传递道具
- 组件通过事件向上传递 属性,通过 props 向下传递,一次一跳。换句话说,
Header.vue
将clientHeight
(通过事件)传递给App.vue
,然后向下传递到Content.vue
(通过 props),再向下传递到Content2.vue
(通过道具)。 - 优点:不需要任何全局存储或
$root
/hub/bus 个实例。在每个组件的签名(事件或道具)中,每个数据传递(在我们的输出中)都是明确的。 - 缺点:四处耦合;仅供传递的样板;可以说是使用像 Vuex 这样的商店的主要原因之一。
- 组件通过事件向上传递 属性,通过 props 向下传递,一次一跳。换句话说,
Dependency injection via
provide
/inject
又名 "long-range-props"
就我个人而言,我会选择 Vuex,特别是如果您已经配置了它。如果没有,我会使用 $root
,但承诺在第一时间使用 Vuex 任何其他道具在全球范围内都是必需的。