關於Vue中的ref和$refs的二三事


  Vue中的ref可以用來給元素或子組件注冊引用信息,而$refs可以用來獲取ref注冊過的元素或組件,關於這一點概念,其實很容易理解,使用一下就可以上手了,詳細的概念參見 [vue-ref]   [vue-$refs]

  但是在實際項目中,會發現,有時候通過 this.$refs.ref名稱 來獲取對應的DOM或組件時,並不能成功,而要在后面加一個 [0] 才能成功獲取到。多留心一下,會發現好像是涉及到循環時,就會出現這種情況,那不如來多做幾組測試來驗證一下,順便試試各種特殊情況下的特別之處。

  太長了,我要直接看結論

  

  part 1 常規用法

  當ref用在組件上時,通過$refs獲取的是該組件的實例,可進而調用組件內定義的方法、屬性等;

  如下圖所示,當ref定義在組件Home上時,通過this.$refs.test獲取的是Home組件對應的實例對象,通常我們可以通過這種方式來調用某個組件內的methods、data中定義的數據、或是進而獲取其子組件等。

<template>
  <div id="app">
    <Home ref="test" />
  </div>
</template>

<script> import Home from './views/Home' export default {
  components: { Home },
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>

  當ref用在DOM節點上時,通過$refs獲取的是該DOM元素節點。

  如下圖所示,當ref定義在DOM元素上時,通過this.$refs.test獲取的是該DOM元素,且包含子元素,進而可以進行下一步的DOM操作。

<template>
  <div id="app">
    <p ref="test">
      <span>123</span>
    </p>
  </div>
</template>

<script>
export default {
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>

 


 

  Part 2 多處ref引用的值相同時(非v-for內使用時)

   當html中ref值相同的節點是兄弟節點時,通過$refs獲取到的是文檔中順序靠下的節點(使用在DOM上和組件上原則一致,以DOM為例)

<template>
  <div id="app">
    <p ref="test">
      <span>123</span>
    </p>
    <span ref="test">456</span>
  </div>
</template>

<script>
export default {
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>

 

   當html中ref值相同的節點是嵌套關系時,比如父子關系,則通過$refs獲取到的是外層節點(使用在DOM上和組件上原則一致,以DOM為例)

<template>
  <div id="app">
    <p ref="test">
      <span ref="test">123</span>
    </p>
  </div>
</template>

<script>
export default {
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>

 

   當html中ref值相同的節點不在同一層級,也不是嵌套關系時,仍然遵循文檔中順序靠下的節點被獲取的原則(使用在DOM上和組件上原則一致,以DOM為例)

<template>
  <div id="app">
    <p ref="test">456</p>
    <p>
      <span ref="test">123</span>
    </p>
  </div>
</template>

<script>
export default {
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>


 

   Part 3 當ref值是個變量時(非v-for內使用時)

   ref值使用變量時,通過this.$refs[變量名稱]指向的依舊是該DOM節點或組件實例,不需要加[0],且當出現ref值重復時,仍然滿足Part2實踐中的原則

<template>
  <div id="app">
    <p :ref="name">
      <span>123</span>
    </p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: 'test'
    }
  },
  mounted () {
    console.log(this.$refs[this.name])
  }
}
</script>

 


 

   Part 4 ref用在v-for上時

  當ref值相同時,this.$refs[ref名稱]獲取到的是該DOM節點或組件的數組,此處以組件為例

<template>
  <div id="app">
    <Home v-for="num in loop" :key="num" ref="test"></Home>
  </div>
</template>

<script> import Home from './views/Home'
export default {
  components: { Home },
  data () {
    return {
      loop: 3
    }
  },
  mounted () {
    console.log(this.$refs.test)
  }
}
</script>

 

   當ref值不同時,this.$refs[ref名稱]無法獲取對應的DOM節點或是組件,需要在其后追加[0]才可訪問,此處以組件為例

<template>
  <div id="app">
    <Home v-for="num in loop" :key="num" :ref="'test' + num"></Home>
  </div>
</template>

<script> import Home from './views/Home'
export default {
  components: { Home },
  data () {
    return {
      loop: 3
    }
  },
  mounted () {
    console.log(this.$refs.test1)
  }
}
</script>

 


 

   總結:

     1. ref用在DOM上時,通過this.$refs[ref名稱]訪問的是該DOM元素節點;ref用在組件上時,通過this.$refs[ref名稱]訪問的是該組件的實例對象,可以進而調用組件的方法或者獲取組件的屬性等;

    2. 當同一組件內部,有多處ref引用值相同的情況時,this.$refs[ref名稱]指向文檔流中靠下的組件或DOM節點,若是父子關系,則指向父級組件或DOM節點;

    3. 若ref的值是個變量,只要不是用在v-for里,通過this.$refs[變量名稱]指向的依舊是該DOM節點或組件實例,且當出現ref值重復時,仍然滿足取靠下的節點或是父級節點的規則;

    4. 若ref用在v-for里,當循環內的ref值相同時,this.$refs[ref名稱]獲取到的是該DOM節點或組件的數組,當ref值不同時,需提供this.$refs[ref名稱][0]來獲取該DOM節點或組件實例。

 

  以上各項實踐可能考慮的情況不一定全,若是有遇到其他情況出現不一樣的用法和結果,再進行補充。

 

 

 

 

 

 

 

 

 

 


免責聲明!

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



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