How can I find the vue.js component corresponding to a DOM element?
If I have
element = document.getElementById(id);
Is there a vue method equivalent to the jQuery
$(element)
How can I find the vue.js component corresponding to a DOM element?
If I have
element = document.getElementById(id);
Is there a vue method equivalent to the jQuery
$(element)
The proper way to do with would be to use the v-el
directive to give it a reference. Then you can do this.$$[reference]
.
In Vue 2 refs are used for both elements and components: http://vuejs.org/guide/migration.html#v-el-and-v-ref-replaced
v-el
directive seems not to be there anymore. –
Emileeemili ref="myid"
to the elements but had to reference it in JavaScript with this.$refs["myid"]
. –
Holt :ref="'item' + item.id"
. However, this will seldom be neccesary because refs defined in loops automatically gets gets into an array this.$refs['combo-inside-loop'][index] –
Siobhan Just by this (in your method in "methods"):
element = this.$el;
:)
methods
you already have a reference to the component via this
. –
Emileeemili this.$el
is just an HTML comment object, not even the root object. –
Stadler mounted()
. for example on created()
this is undefined
–
Hysteria In Vue.js 2 Inside a Vue Instance or Component:
this.$el
to get the HTMLElement the instance/component was mounted toFrom an HTMLElement
:
.__vue__
from the HTMLElement
var vueInstance = document.getElementById('app').__vue__;
Having a VNode
in a variable called vnode
you can:
vnode.elm
to get the element that VNode was rendered tovnode.context
to get the VueComponent instance that VNode's component was declared (this usually returns the parent component, but may surprise you when using slots.vnode.componentInstance
to get the Actual VueComponent instance that VNode is aboutSource, literally: 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/[email protected]/dist/vue.min.js"></script>
<h1>Open the browser's console</h1>
<div id="app">
<my-component v-customdirective=""></my-component>
</div>
vm._vnode = vnode
With that, you can cross-walk the DOM Node tree, the VNode (VDOM) tree and the Vue tree. –
Scorpius vnode.elm
documented? –
Plastic context
is the Vue instance (the root component). componentInstance
is the component instance (may or may not be the root component. It won't be the root component if it is an instance of a custom component you created -- via Vue.component('my-comp', { ...})
, for instance). –
Hodgkin Root.vue file
,and its template is <Parent><Child v-custom-directive><Child></Parent>
so vnode.context
is the Root component
instance ,and vnode.componentInstance
is Child component
instance ? right ? –
Elnoraelnore context
seems to be the parent component (not the root component). I have update the answer to make it clearer. See if this fiddle helps you: jsfiddle.net/acdcjunior/ukweftav let me know! –
Hodgkin vnode.context.$el
(jsfiddle.net/acdcjunior/9emvr5az/2) is of use to you. It appears that vnode.context
points to the element the component was declared in. In the case of that fiddle, the <Child>
is declared in the root ("slotted" into <Parent>
) –
Hodgkin The proper way to do with would be to use the v-el
directive to give it a reference. Then you can do this.$$[reference]
.
In Vue 2 refs are used for both elements and components: http://vuejs.org/guide/migration.html#v-el-and-v-ref-replaced
v-el
directive seems not to be there anymore. –
Emileeemili ref="myid"
to the elements but had to reference it in JavaScript with this.$refs["myid"]
. –
Holt :ref="'item' + item.id"
. However, this will seldom be neccesary because refs defined in loops automatically gets gets into an array this.$refs['combo-inside-loop'][index] –
Siobhan If you're starting with a DOM element, check for a __vue__
property on that element. Any Vue View Models (components, VMs created by v-repeat
usage) will have this property.
You can use the "Inspect Element" feature in your browsers developer console (at least in Firefox and Chrome) to view the DOM properties.
Hope that helps!
c = $0.__vue__
in console. Now c
is your Vue component and you can inspect all its properties. :) –
Kinlaw this.$el
- points to the root element of the componentthis.$refs.<ref name>
+ <div ref="<ref name>" ...
- points to nested element💡 use
$el
/$refs
only aftermounted()
step of vue lifecycle
<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>
Since v-ref is no longer a directive, but a special attribute, it can also be dynamically defined. This is especially useful in combination with v-for.
For example:
<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>
and in Vue component you can use
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]);
}
}
});
So I figured $0.__vue__
doesn't work very well with HOCs (high order components).
// ListItem.vue
<template>
<vm-product-item/>
<template>
From the template above, if you have ListItem
component, that has ProductItem
as it's root, and you try $0.__vue__
in console the result unexpectedly would be the ListItem
instance.
Here I got a solution to select the lowest level component (ProductItem
in this case).
// DomNodeToComponent.js
export default {
install: (Vue, options) => {
Vue.mixin({
mounted () {
this.$el.__vueComponent__ = this
},
})
},
}
import DomNodeToComponent from'./plugins/DomNodeToComponent/DomNodeToComponent'
Vue.use(DomNodeToComponent)
$0.__vueComponent__
.If you want more, you can just use $0.__vue__.$parent
. Meaning if 3 components share the same dom node, you'll have to write $0.__vue__.$parent.$parent
to get the main component. This approach is less laconic, but gives better control.
I found this snippet here. The idea is to go up the DOM node hierarchy until a __vue__
property is found.
function getVueFromElement(el) {
while (el) {
if (el.__vue__) {
return el.__vue__
} else {
el = el.parentNode
}
}
}
In Chrome:
I needed to create a navbar and collapse the menu item when clicked outside. I created a click listener on windows in mounted
life cycle hook as follows
mounted() {
window.addEventListener('click', (e)=>{
if(e.target !== this.$el)
this.showChild = false;
})
}
You can also check if the element is child of this.$el. However, in my case the children were all links and this didn't matter much.
If you want listen an event (i.e OnClick) on an input with "demo" id, you can use:
new Vue({
el: '#demo',
data: {
n: 0
},
methods: {
onClick: function (e) {
console.log(e.target.tagName) // "A"
console.log(e.targetVM === this) // true
}
}
})
Since in Vue 2.0, no solution seems available, a clean solution that I found is to create a vue-id
attribute, and also set it on the template. Then on created
and beforeDestroy
lifecycle these instances are updated on the global object.
Basically:
created: function() {
this._id = generateUid();
globalRepo[this._id] = this;
},
beforeDestroy: function() {
delete globalRepo[this._id]
},
data: function() {
return {
vueId: this._id
}
}
© 2022 - 2024 — McMap. All rights reserved.