Vue自定義指令獲取DOM元素

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

<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

 

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

 

首先,咱們使用一種比較廣泛的方法來實現,在須要獲取DOM的元素上綁定ref屬性,而後經過 this.$refs [ 屬性值 ] 來獲取。app

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

到了mounted時期,元素已經掛載完成,咱們能夠獲取到sentence對象了,拿到後火燒眉毛的想要修改它的innerHTML,因而又報錯了,this.$refs.sentence.innerHTML是undefined,至關不爽,打斷點,一查究竟,發現this.$refs.sentence是奇奇怪怪的VueComponent,並非咱們傳統的DOM對象,那怎麼獲取到咱們想要的innerHTML、className等等呢?經過斷點仔細查看該VueComponent對象後,發現咱們想要的東西都藏在更深一層的屬性$el裏,以下圖:ide

 

知道了裏面的玄機,咱們就能夠經過 this.$refs.sentence.$el.innerHTML = "whatever you want" 來修改DOM的內容了。函數

 

 

做了如此多的鋪墊,咱們是否是能夠開始今天高大上的主題了?使用Vue的自定義指令來解決這個問題。學習

HTML:ui

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

JavaScript:this

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是相同的,讓咱們感到熟悉又舒服。

相關文章
相關標籤/搜索