DOM 元素到对应的 vue.js 组件
Posted
技术标签:
【中文标题】DOM 元素到对应的 vue.js 组件【英文标题】:DOM element to corresponding vue.js component 【发布时间】:2015-01-10 23:18:12 【问题描述】:如何找到一个DOM元素对应的vue.js组件?
如果我有
element = document.getElementById(id);
有没有相当于jQuery的vue方法
$(element)
【问题讨论】:
据我所知,没有办法做到这一点。 你介意接受我的回答吗? 【参考方案1】:如果您想在带有“演示”ID 的输入上监听事件(即 OnClick),您可以使用:
new Vue(
el: '#demo',
data:
n: 0
,
methods:
onClick: function (e)
console.log(e.target.tagName) // "A"
console.log(e.targetVM === this) // true
)
【讨论】:
从一个 dom 元素开始,我试图了解控制该元素的 vue 组件是什么(如果有的话)。【参考方案2】:正确的做法是使用v-el
指令给它一个参考。那你就可以this.$$[reference]
了。
vue 2 更新
在 Vue 2 中,元素和组件都使用引用:http://vuejs.org/guide/migration.html#v-el-and-v-ref-replaced
【讨论】:
在 Vue 2 中,v-el
指令似乎不再存在了。
在 Vue 2 中,我将 ref="myid"
添加到元素中,但必须在 javascript 中使用 this.$refs["myid"]
引用它。
关于 ref 的一个很酷的地方是它可以动态定义::ref="'item' + item.id"
。但是,这很少是必要的,因为在循环中定义的 refs 会自动进入数组 this.$refs['combo-inside-loop'][index]【参考方案3】:
如果您从 DOM 元素开始,请检查该元素上的 __vue__
属性。任何 Vue 视图模型(组件,由 v-repeat
使用创建的 VM)都将具有此属性。
您可以使用浏览器开发者控制台(至少在 Firefox 和 Chrome 中)中的“检查元素”功能来查看 DOM 属性。
希望有帮助!
【讨论】:
专业提示:在开发者控制台的“元素”选项卡中找到元素,选择该元素,然后在控制台中输入c = $0.__vue__
。现在c
是你的 Vue 组件,你可以检查它的所有属性。 :)【参考方案4】:
就这样(在“方法”中的方法中):
element = this.$el;
:)
【讨论】:
这不是问题要问的。问题是如果你有一个节点的引用,你怎么能得到对渲染它的 Vue 组件的引用,而不是组件的根元素是什么。如果您在methods
中,则您已经通过 this
引用了该组件。
问题标题欺骗了我——但是因为有些人(也被问题标题欺骗)在这里找到了答案,所以我会留下这个答案。
提示其他人:渲染后,在我使用 Vue 1.x 的环境中,this.$el
只是一个 HTML 注释对象,甚至不是根对象。
确保你至少在mounted()
之后依赖这个。例如在created()
这是undefined
【参考方案5】:
正是卡米尔所说的,
element = this.$el
但请确保您没有fragment instances。
【讨论】:
正是我对卡米尔的评论。这不是问题所问的。 如果卡米尔已经回答了这个问题,那你为什么提供同样的答案?【参考方案6】:由于在 Vue 2.0 中,似乎没有可用的解决方案,我发现一个干净的解决方案是创建一个 vue-id
属性,并将其设置在模板上。然后在 created
和 beforeDestroy
生命周期中,这些实例在全局对象上更新。
基本上:
created: function()
this._id = generateUid();
globalRepo[this._id] = this;
,
beforeDestroy: function()
delete globalRepo[this._id]
,
data: function()
return
vueId: this._id
【讨论】:
在 vue 2 中你使用 refs【参考方案7】:由于 v-ref 不再是指令,而是特殊属性,所以也可以动态定义。这在与 v-for 结合使用时特别有用。
例如:
<ul>
<li v-for="(item, key) in items" v-on:click="play(item,$event)">
<a v-bind:ref="'key' + item.id" v-bind:href="item.url">
<!-- content -->
</a>
</li>
</ul>
在 Vue 组件中你可以使用
var recordingModel = new Vue(
el:'#rec-container',
data:
items:[]
,
methods:
play:function(item,e)
// it contains the bound reference
console.log(this.$refs['key'+item.id]);
);
【讨论】:
【参考方案8】:所以我认为$0.__vue__
不适用于 HOC(高阶组件)。
// ListItem.vue
<template>
<vm-product-item/>
<template>
从上面的模板中,如果你有ListItem
组件,它有ProductItem
作为它的根,你在控制台中尝试$0.__vue__
,结果出乎意料地是ListItem
实例。
这里我有一个选择最低级别组件的解决方案(在本例中为ProductItem
)。
插件
// DomNodeToComponent.js
export default
install: (Vue, options) =>
Vue.mixin(
mounted ()
this.$el.__vueComponent__ = this
,
)
,
安装
import DomNodeToComponent from'./plugins/DomNodeToComponent/DomNodeToComponent'
Vue.use(DomNodeToComponent)
使用
在浏览器控制台中单击 dom 元素。 输入$0.__vueComponent__
。
用组件做任何你想做的事。访问数据。做改变。从 e2e 运行公开的方法。
奖励功能
如果你想要更多,你可以使用$0.__vue__.$parent
。这意味着如果 3 个组件共享同一个 dom 节点,则您必须编写 $0.__vue__.$parent.$parent
才能获取主要组件。这种方法不那么简洁,但可以提供更好的控制。
【讨论】:
【参考方案9】:在 Vue.js 2 中的 Vue 实例中或组件:
使用this.$el
获取实例/组件安装到的HTMLElement
来自HTMLElement
:
.__vue__
例如var vueInstance = document.getElementById('app').__vue__;
在名为vnode
的变量中包含VNode
,您可以:
vnode.elm
获取VNode 被渲染到的元素
使用vnode.context
获取声明VNode组件的VueComponent实例(这通常返回父组件,但使用slots时可能会让您感到惊讶。
使用vnode.componentInstance
获取VNode所在的Actual VueComponent实例
来源,字面意思:vue/flow/vnode.js。
可运行演示:
Vue.config.productionTip = false; // disable developer version warning
console.log('-------------------')
Vue.component('my-component',
template: `<input>`,
mounted: function()
console.log('[my-component] is mounted at element:', this.$el);
);
Vue.directive('customdirective',
bind: function (el, binding, vnode)
console.log('[DIRECTIVE] My Element is:', vnode.elm);
console.log('[DIRECTIVE] My componentInstance is:', vnode.componentInstance);
console.log('[DIRECTIVE] My context is:', vnode.context);
// some properties, such as $el, may take an extra tick to be set, thus you need to...
Vue.nextTick(() => console.log('[DIRECTIVE][AFTER TICK] My context is:', vnode.context.$el))
)
new Vue(
el: '#app',
mounted: function()
console.log('[ROOT] This Vue instance is mounted at element:', this.$el);
console.log('[ROOT] From the element to the Vue instance:', document.getElementById('app').__vue__);
console.log('[ROOT] Vue component instance of my-component:', document.querySelector('input').__vue__);
)
<script src="https://unpkg.com/vue@2.5.15/dist/vue.min.js"></script>
<h1>Open the browser's console</h1>
<div id="app">
<my-component v-customdirective=""></my-component>
</div>
【讨论】:
github.com/vuejs/vue/blob/dev/src/core/instance/lifecycle.js 给定一个 "Vue" instance vm:vm._vnode = vnode
有了它,你可以遍历 DOM 节点树,即VNode (VDOM) 树和 Vue 树。
vnode.elm
记录在哪里?
vnode.context 和 vnode.componentInstance 有什么区别
@Archsx context
是 Vue 实例(根组件)。 componentInstance
是组件实例(可能是根组件,也可能不是根组件。如果它是您创建的自定义组件的实例——例如,通过Vue.component('my-comp', ...)
,它就不是根组件)。
@Archsx 也许vnode.context.$el
(jsfiddle.net/acdcjunior/9emvr5az/2) 对你有用。似乎vnode.context
指向组件被声明 的元素。在那个小提琴的情况下,<Child>
在根中声明(“插入”到<Parent>
)跨度>
【参考方案10】:
我找到了这个 sn-p here。这个想法是在 DOM 节点层次结构中向上,直到找到 __vue__
属性。
function getVueFromElement(el)
while (el)
if (el.__vue__)
return el.__vue__
else
el = el.parentNode
在 Chrome 中:
【讨论】:
【参考方案11】:this.$el
- 指向组件的根元素
this.$refs.<ref name>
+ <div ref="<ref name>" ...
- 指向嵌套元素
?仅在vue lifecycle的
mounted()
步骤之后使用$el
/$refs
<template>
<div>
root element
<div ref="childElement">child element</div>
</div>
</template>
<script>
export default
mounted()
let rootElement = this.$el;
let childElement = this.$refs.childElement;
console.log(rootElement);
console.log(childElement);
</script>
<style scoped>
</style>
【讨论】:
【参考方案12】:Vue 3 解决方案
我需要创建一个导航栏并在外部单击时折叠菜单项。我在mounted
生命周期钩子中的windows上创建了一个点击监听器,如下
mounted()
window.addEventListener('click', (e)=>
if(e.target !== this.$el)
this.showChild = false;
)
你也可以检查元素是否是 this.$el 的子元素。但是,在我的情况下,孩子都是链接,这并不重要。
【讨论】:
以上是关于DOM 元素到对应的 vue.js 组件的主要内容,如果未能解决你的问题,请参考以下文章