天天看點

Vue擷取DOM元素等相關操作

vue.js 是資料綁定的架構,大部分情況下我們都不需要直接操作 DOM Element,但在某些時候,我們還是有擷取DOM Element的需求的;記得曾經公司隻想使用vue資料雙向綁定部分,事件等部分單列出來由背景驅動就用到了擷取dom。

那怎麼擷取相關的dom元素呢?

這裡我想到了3個方法:

方法一:

直接給相應的元素加id,然後再document.getElementById(“id”);擷取,然後設定相應屬性或樣式,這個就不用過多介紹了吧,直接過。

方法二:

使用ref,給相應的元素加ref=“name” 然後再this.$refs.name擷取到該元素,官網介紹

demo1

<template>
 <div style="display: block;" ref="abc">
  <!-- ... -->
 </div>
</template>
<script>
  export default {
   mounted () {
     console.log(this.$refs.abc.style.display)
   }
  }
</script>
           

demo2

<div id="app">
	<div class="alass" ref="dom" style="font-size: 30px;">
		在
		<span>不在</span>
	</div>
</div>

new Vue({
  el:'#app',
  mounted () {
		console.log(this.$refs.dom.firstElementChild)
      	var _this=this;
      	this.$refs.dom.firstElementChild.addEventListener("click",function(){
      		console.log(_this.$refs.dom)
      	})
  }
})
           

注意:在擷取相應元素之前,必須在mount鈎子進行挂載,否則擷取到的值為空,

如果是給子元件加id并修改自定義屬性,則直接會加載改子元件對應的外層div上,并不會改變該子元件原本的自定義屬性的值

如果給子元件加ref,然後擷取到該DOM元素之後改變相應的自定義屬性的值,vue會報錯:

方法三:

在 vue.js 中,擷取某個DOM Element常用的方法是将這個元素改成一個元件 (component),然後通過 this.$el 去擷取,但是在一些很小的項目裡,在一些沒有使用 webpack 等建構工具的項目中,建立一個元件并不是那麼值得,是以 vue 提供了另一種操作DOM元素的方式,就是自定義指令 (directive) ;

自定義指令功能在DOM Element的生命周期内提供了不同的鈎子函數,并允許我們監聽指令綁定的資料的變化,但是它也是有缺點的,就是在指令的鈎子函數内無法通過 this 來通路目前 vue 執行個體,也就無法進一步進行複雜的操作(雖然一般不需要什麼複雜的操作),在 vue 的鈎子函數 (lifecycle hook) 和方法 (method) 中也無法像 this.$el 那樣輕易的通路到自定義指令綁定的DOM元素;

不過隻要通過一點點變通的做法,就可以突破這個限制:

HTML代碼:

<div id="app">
      <span class='test' v-run="register('test1')"></span>
      <p class='test' v-run="register('test2')"></p>
    </div> 
           

JavaScript代碼:

const vm = new Vue({
  el:'#app',
  data : {
    elements : {}
  },
  directives : {
    run (el, binding) {
      if (typeof binding.value == 'function')
        binding.value(el);
    }
  },
  methods : {
    register (flag) {
      return (el)=>{
        this.elements[flag] = el;
      }
    }
  },
  beforeMount () {
    console.log(this.elements.test1); //=> undefined
  },
  mounted () {
    console.log(this.elements.test1); //=> the span DOM Element
    console.log(this.elements.test2); //=> the p DOM Element
  }
})
           

如代碼所示,建立一個名為 run 的自定義指令,運作綁定的方法,并将目前 DOM Element 作為參數傳入;

同時建立一個名為 register 的方法,接收一個 flag 參數,并根據這個參數傳回一個用于将傳入參數注冊到 this.elements 對象中的閉包函數;

将寫好的 run 指令和 register 方法搭配使用,就可以把想要的 DOM 注冊進this.elements,并在 hook 或者 method 中十分友善的通路;

注意:自定義指令将會在DOM元素插入 Document 時,也就是元件 mount 時首次執行,是以在此之前,比如 beforeMount 鈎子中是無法使用的,這點也和 this.$el 一緻,詳情可以檢視官方文檔中的生命周期圖示;

其實也很好了解啦……在 mount 之前,根本就沒有這個實際的 DOM 元素,怎麼可能通路的到……(:з)∠)

繼續閱讀