【问题标题】:DOM element to corresponding vue.js componentDOM 元素到对应的 vue.js 组件
【发布时间】:2015-01-10 23:18:12
【问题描述】:

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

如果我有

element = document.getElementById(id);

有没有相当于jQuery的vue方法

$(element)

【问题讨论】:

  • 据我所知,没有办法做到这一点。
  • 你介意接受我的回答吗?

标签: javascript dom vue.js


【解决方案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 属性,并将其设置在模板上。然后在 createdbeforeDestroy 生命周期中,这些实例在全局对象上更新。

基本上:

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

      • 使用 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.contextvnode.componentInstance 有什么区别
      • @Archsx context 是 Vue 实例(根组件)。 componentInstance 是组件实例(可能是根组件,也可能不是根组件。如果它是您创建的自定义组件的实例——例如,通过Vue.component('my-comp', { ...}),它就不是根组件)。
      • @Archsx 也许vnode.context.$el (jsfiddle.net/acdcjunior/9emvr5az/2) 对你有用。似乎vnode.context 指向组件被声明 的元素。在那个小提琴的情况下,&lt;Child&gt; 在根中声明(“插入”到&lt;Parent&gt;)跨度>
      【解决方案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.&lt;ref name&gt; + &lt;div ref="&lt;ref name&gt;" ... - 指向嵌套元素

        ?仅在vue lifecyclemounted()步骤之后使用$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 的子元素。但是,在我的情况下,孩子都是链接,这并不重要。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-05-29
            • 1970-01-01
            • 2016-09-03
            • 2019-08-06
            • 1970-01-01
            • 2021-07-20
            • 2016-06-01
            • 2018-04-23
            相关资源
            最近更新 更多