对应于vue.js组件的DOM元素


69

如何找到与DOM元素相对应的vue.js组件?

如果我有

element = document.getElementById(id);

是否有一个等效于jQuery的vue方法

$(element)

据我所知,没有办法做到这一点。
Mikael 2014年

你介意接受我的回答吗?
笨蛋

Answers:


49

正确的处理方法是使用v-el指令为其提供引用。那你就可以做this.$$[reference]

vue 2的更新

在Vue 2中,引用用于元素和组件:http : //vuejs.org/guide/migration.html#v-el-and-v-ref-replaced


1
在Vue 2中,该v-el指令似乎不再存在。
bogdan.mustiata

11
在Vue 2中,我添加ref="myid"了元素,但必须在JavaScript中使用进行引用this.$refs["myid"]
汤姆(Tom)

1
关于裁判一个很酷的事情是,它可以动态定义: :ref="'item' + item.id"。但是,这很少是必需的,因为在循环中定义的ref会自动进入此数组this。$ refs ['combo-inside-loop'] [index]
rosell.dk

63

只是这样(在您的方法“方法”中):

element = this.$el;

:)


8
这不是问题要问的。问题是,如果您有对节点的引用,那么如何获得对呈现该节点的Vue组件的引用,而不是该组件的根元素是什么。如果您在中,则methods已经通过引用了该组件this
bogdan.mustiata

24
问题标题欺骗了我-但是由于某些人(也被问题标题欺骗)在这里找到答案,因此我将保留此答案。
卡米尔·基茨凯夫斯基(KamilKiełczewski)

对其他人的提示:渲染后,在我的Vue 1.x环境中,this.$el它只是一个HTML注释对象,甚至不是根对象。
peter_the_oak

1
确保至少在之后依赖这个mounted()。例如,created()这是undefined
Jossef Harush

41

在Vue实例组件内部的Vue.js 2中:

  • 使用this.$el来获取HTML元素的实例/组件被安装到

来自HTMLElement

  • .__vue__从HTMLElement 使用
    • 例如 var vueInstance = document.getElementById('app').__vue__;

VNode名为的变量中vnode可以执行以下操作:

  • 用于vnode.elm获取渲染VNode的元素
  • 使用vnode.context得到VueComponent实例VNODE的组件被宣布(这通常返回父成分,但使用时可能会让你大吃一惊插槽
  • 用于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>


1
github.com/vuejs/vue/blob/dev/src/core/instance/lifecycle.js 给定一个“Vue公司”比如 VMvm._vnode = vnode 有了这一点,你可以横走的DOM节点树,这个虚拟节点(虚拟域)树和Vue树。
smallscript

在哪里vnode.elm记录?
P. Myer Nore,

vnode.contextvnode.componentInstance有
Archsx

@Archsxcontext是Vue实例(根组件)。componentInstance是组件实例(可能不是根组件。如果它是您创建的自定义组件的实例(例如,通过)Vue.component('my-comp', { ...}),则不会是根组件)。
acdcjunior

1
@Archsx也许对您有用vnode.context.$eljsfiddle.net/acdcjunior/9emvr5az/2)。似乎vnode.context指向在其中声明了组件的元素。在这种提琴的情况下,<Child>声明在根中(“插入” <Parent>
acdcjunior

13

如果您从DOM元素开始,请检查__vue__该元素的属性。任何Vue视图模型(组件,按v-repeat使用情况创建的VM )都将具有此属性。

您可以在浏览器开发人员控制台(至少在Firefox和Chrome中)使用“检查元素”功能来查看DOM属性。

希望有帮助!


专家提示:在开发人员控制台的“元素”选项卡中找到该元素,选择它,然后c = $0.__vue__在控制台中键入。现在c是您的Vue组件,您可以检查其所有属性。:)
艾丁(Aidin)

5

由于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(key,e){
      // it contains the bound reference
      console.log(this.$refs['item'+key]);
    }
  }
});

4
  • this.$el -指向组件的根元素
  • this.$refs.<ref name>+ <div ref="<ref name>" ...-指向嵌套元素

💡仅在vue生命周期步骤之后使用$el/$refsmounted()

<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>

在此处输入图片说明


3

因此,我认为$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以获取主要组件。这种方法简单易用,但可提供更好的控制。


1

我在这里找到了这个片段。想法是提升DOM节点层次结构,直到__vue__找到一个属性。

function getVueFromElement(el) {
  while (el) {
    if (el.__vue__) {
      return el.__vue__
    } else {
      el = el.parentNode
    }
  }
}

在Chrome中:

在Chrome中的用法


-1

如果要在具有“ demo” 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组件是什么(如果有)。
Ghigo 2014年

-4

恰恰是卡米尔所说的

element = this.$el

但是确保没有片段实例


2
正是我对卡米尔发表的评论。这不是问题所要问的。
bogdan.mustiata

如果Kamil已经回答了这个问题,那么为什么您提供了同样的答案呢?
undefinedman

-4

由于在Vue 2.0中似乎没有可用的解决方案,因此我发现一种干净的解决方案是创建一个vue-id属性,并将其设置在模板上。然后在createdbeforeDestroy生命周期这些实例更新全局对象上。

基本上:

created: function() {
    this._id = generateUid();
    globalRepo[this._id] = this;
},

beforeDestroy: function() {
    delete globalRepo[this._id]
},

data: function() {
    return {
        vueId: this._id
    }
}

3
在vue 2中,您使用的是裁判
笨蛋,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.