Vue自定義指令獲取DOM元素


我們知道,Vue.js的核心是數據驅動,當數據有所變化時,DOM就會被更新,比如:

<span v-text="msg"></span> export default { data(){   return{   msg : 'oldMsg'   }  }  methods : {   changeMsg : function(){     this.msg = 'newMsg'   }  } }

當調用了changeMsg方法,msg被修改為 ' newMsg ' ,我們可以把這次修改理解為數據發生了變化,此時數據的變化就要驅動DOM變化,我們可以看到<span>oldMsg</span>變成了<span>newMsg</span>,Vue 實現這種響應式並不是數據發生變化之后 DOM 立即變化,而是按一定的策略進行 DOM 的更新,這里涉及到Vue.nextTick 和 vm.$nextTick 等等另外一大堆知識點,我們這里不作深入討論,我們只需要知道,是數據的變化驅動了DOM的變化,在這個過程中,我們發現我們並沒有去操作具體的DOM元素,按照以前的做法,我們可能需要getElementByAnyWays(不論用什么方式獲取元素,原生Js或者jQuery.....)獲取這個span元素,然后在適當的時候修改它的innerHTML,但我們沒有這樣做,我們只修改了數據,Vue幫我們實現了DOM的修改與更新,這就是Vue最大的特性之一:數據驅動。

 

明白了數據驅動這回事,在使用Vue的過程中,我們發現大部分時候不用去操作具體的每個DOM元素,但是,就怕那剩下的小部分時間……我們還是需要獲取具體的DOM並且對它做一些事情,當你有這個需求並且去做的時候,你會發現在Vue中獲取DOM元素是一件令人頭疼的事情。

 

首先,我們使用一種比較普遍的方法來實現,在需要獲取DOM的元素上綁定ref屬性,然后通過 this.$refs [ 屬性值 ] 來獲取。

<p ref="sentence">I'm waiting for ref</p> export default{
created(){
    console.log(this.$refs.sentence);    // undefined  
   }
   mounted(){
    console.log(this.$refs.sentence)    // VueComponent
   }
}

這里有個小的注意點,就是mounted時期之前,包括beforeMount、created時期,this.$refs都是一個空對象,無法獲取到想要的sentence對象,詳細解說請戳 官方生命周期圖 ,所以,我們要在正確的時間做正確的事情嘛,學習時間就好好看我的文章O(∩_∩)O 。

到了mounted時期,元素已經掛載完成,我們可以獲取到sentence對象了,拿到后迫不及待的想要修改它的innerHTML,於是又報錯了,this.$refs.sentence.innerHTML是undefined,相當不爽,打斷點,一查究竟,發現this.$refs.sentence是奇奇怪怪的VueComponent,並不是我們傳統的DOM對象,那怎么獲取到我們想要的innerHTML、className等等呢?通過斷點仔細查看該VueComponent對象后,發現我們想要的東西都藏在更深一層的屬性$el里,如下圖:

 

知道了里面的玄機,我們就可以通過 this.$refs.sentence.$el.innerHTML = "whatever you want" 來修改DOM的內容了。

 

 

作了如此多的鋪墊,我們是不是可以開始今天高大上的主題了?使用Vue的自定義指令來解決這個問題。

HTML:

<span v-getdom="regist('span1')"></span>
<p v-getdom="regist('p1')"></p>

JavaScript:

const vm = new Vue({ el:'#app', data : { domEles: {} }, directives : { getdom(el, binding) { if (typeof binding.value == 'function') binding.value(el); } }, methods : { regist (flag) { return (el)=>{ this.domEles[flag] = el; } } }, mounted () { console.log(this.domEles.span1);  //=> the span DOM Element
    console.log(this.domEles.p1);   //=> the p DOM Element
 } }) 

 

首先,我們通過官方提供的directives開發一個局部(局部是指該directives只屬於該new Vue()對象,不可被其他Vue對象使用)自定義指令getdom,然后你就可以在模板任何元素上使用v-getdom指令做一些事。

getdom( )傳入了兩個參數,el 和 binding ,這是官方特定參數,有具體的寓意,如下:

 

 

 

接着,建立一個名為 regist 的方法,接收一個 flag 參數,並根據這個參數返回一個用於將傳入參數注冊到 this.domEles對象中的閉包函數

將getdom指令與regist方法搭配使用,就可以將想要的元素注冊進this.domEles對象中,不論在mounted還是methods中使用都非常方便,只需要this.domEles [ 注冊名 ]訪問即可,這里我們得到的DOM對象,可以直接獲取innerHTML等屬性,不需要再深入一層,這與原生DOM是相同的,讓我們感到熟悉又舒服。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM