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)
This question is related to
javascript
dom
vue.js
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>
Just by this (in your method in "methods"):
element = this.$el;
:)
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
}
}
})
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:
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!
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__);
}
})
_x000D_
<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>
_x000D_
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(key,e){
// it contains the bound reference
console.log(this.$refs['item'+key]);
}
}
});
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
}
}
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.
Source: Stackoverflow.com