簡體   English   中英

DOM 元素到對應的 vue.js 組件

[英]DOM element to corresponding vue.js component

如何找到與 DOM 元素對應的 vue.js 組件?

如果我有

element = document.getElementById(id);

有沒有等效於 jQuery 的 vue 方法

$(element)

就這樣(在“方法”中的方法中):

element = this.$el;

:)

正確的處理方法是使用v-el指令給它一個參考。 然后你可以這樣做this.$$[reference]

vue 2的更新

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

在 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實例(這通常返回父組件,但在使用slot時可能會讓您感到驚訝。
  • 使用vnode.componentInstance獲取 VNode 的實際 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>

如果您從 DOM 元素開始,請檢查該元素上的__vue__屬性。 任何 Vue 視圖模型(組件、由v-repeat使用創建的 VM)都將具有此屬性。

您可以使用瀏覽器開發者控制台(至少在 Firefox 和 Chrome 中)中的“檢查元素”功能來查看 DOM 屬性。

希望有幫助!

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

💡 僅在vue 生命周期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>

在此處輸入圖像描述

由於 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]);
    }
  }
});

所以我認為$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來獲取主要組件。 這種方法不那么簡潔,但提供了更好的控制。

我在 這里找到了這個片段。 這個想法是向上 DOM 節點層次結構,直到找到__vue__屬性。

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

在 Chrome 中:

在 Chrome 中的使用

Vue 3 的解決方案

我需要創建一個導航欄並在外部單擊時折疊菜單項。 我在已mounted的生命周期掛鈎中的窗口上創建了一個點擊偵聽器,如下所示

mounted() {
    window.addEventListener('click', (e)=>{
        if(e.target !== this.$el)
            this.showChild = false;
    })
}

您還可以檢查元素是否是 this.$el 的子元素。 但是,在我的情況下,孩子們都是鏈接,這並不重要。

如果您想在具有“演示”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
  }
 }
})

正如卡米爾所說,

element = this.$el

但請確保您沒有片段實例

由於在 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
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM