vue3使用自定義hooks獲取dom元素的問題說明
使用自定義hooks獲取dom元素問題
在自定義hooks的onMounted事件里面 獲取ref元素,組件調(diào)用hooks的時(shí)候必須要傳遞響應(yīng)式對象。
分享下樓主自己的觀點(diǎn)
代碼如下
<script> // demo.vue import { defineComponent, ref } from 'vue' import useBars from './useBars' export default defineComponent({ ? ? props: { ? ? ? ? Bars: Array, ? ? }, ? ? setup() { ? ? ? ? const rootRef = ref(null)? ? ? ? const { currentPageIndex } = useBars(rootRef) // 這里傳遞過去的是一個(gè)響應(yīng)式對象 ?? ??? ? ?? ??? ? const { currentPageIndex: currentPageIndex1 ?} = useBars(rootRef) // 這里傳遞過去的就是一個(gè)null,而不是對象 ? ? ? ? console.log('組件 setup 最后一段') ? ? ? ? return { ? ? ? ? ? ? rootRef, ? ? ? ? ? ? currentPageIndex, ? ? ? ? } ? ? }, }) </script>
// useBar.js import { onMounted } from 'vue' export default function useSliders(rootRef) { ?? ? /** ? ? ?* 1. 傳遞過來是一個(gè)響應(yīng)式對象 ? ? ?* ? ? ?* ?傳過來是一個(gè)響應(yīng)式對象,調(diào)用這個(gè)函數(shù)的時(shí)候rootRef.value = nul ? ? ?* ?組件實(shí)例化完畢,在組件里面 rootRef.value = <div></div> ? ? ?* ?執(zhí)行 這個(gè)onmonted事件,里面就獲取到了一個(gè)div,這個(gè)onMounted事件是當(dāng)組件實(shí)例化完畢才會執(zhí)行的 ? ? ?*/ ? ? /** ? ? ?* ?傳過來就是一個(gè)null ? ? ?* ? onMounted 執(zhí)行的時(shí)候自然也是null ? ? ?*? ? ? ?*/ ? ? // ! 感覺是訪問同一個(gè)地址,如果傳遞一個(gè)響應(yīng)式對象,然后組件里面給 rootRef.value賦值,這里就也能拿到了 ? ? onMounted(() => { ? ? ? ? // debugger ? ? ? ? console.log('hooks slider mounted --->', rootRef) ? ? }) ? ? return {} }```
vue獲取/操作組件的dom元素
最近剛做了一個(gè)項(xiàng)目,需要用到地圖,選擇的是騰訊地圖,創(chuàng)建地圖的時(shí)候,需要給地圖創(chuàng)建函數(shù)中傳入地圖容器的id或者容器的dom元素,但是在調(diào)試過程中,發(fā)現(xiàn)怎么都無法獲取dom元素,直接通過getElementById也無法獲取元素內(nèi)容。
下面是我的代碼內(nèi)容(非全部內(nèi)容)
<template> <a-modal> ? ? <div id="map"></div> </a-modal> </template>
<script> import TMap from 'TMap' export default{ ? ? method:{ ? ? ? ? open(){ ? ? ? ? ? ? this.initMap() ? ? ? ? }, ? ? ? ? initMap(){ ? ? ? ? ? ? const center = new TMap.LatLng(39.984120,116.307484) ? ? ? ? ? ? const container = document.getElementById('map') ? ? ? ? ? ? const map = new TMap.Map(container, { ? ? ? ? ? ? ? ? center:center, ? ? ? ? ? ? ? ? zoom:11 ? ? ? ? ? ? }) ? ? ? ? } ? ? } } </script>
頁面調(diào)試的時(shí)候,一直報(bào)錯(cuò),無法讀取到id的值,直接打印container的值,卻是null,但是看了網(wǎng)上其他使用騰訊地圖的例子,基本上是一樣的思路。
然后就開始找問題,一直折騰,最后才想到是不是因?yàn)槲野训貓D容器放到a-modal組件中的原因,然后對比網(wǎng)上的代碼,才發(fā)現(xiàn),別人的都是直接放在template中,或者使用其他html元素包裹,而我把地圖容器放到了a-modal組件中。
這時(shí)就想到,是不是可以通過a-modal組件來獲取dom元素,然后就給a-modal組件加上ref屬性,代碼如下
<a-modal ref="modal"> ? ? <div id="map"></div> </a-modal>
然后打印this.$refs.modal,觀察打印的對象,看能不能找到dom元素內(nèi)容,又想到容器元素被a-modal包裹,相當(dāng)于使用插槽,所以找到了$slots.default屬性,在上面找到了渲染的VNode,終于找到了div#map元素。
既然找到了,那把這個(gè)元素傳給地圖創(chuàng)建函數(shù)就行,說做就做,立即改代碼。
<template> <a-modal ref="modal"> ? ? <div id="map"></div> </a-modal> </template>
<script> import TMap from 'TMap' export default{ ? ? method:{ ? ? ? ? open(){ ? ? ? ? ? ? this.initMap() ? ? ? ? }, ? ? ? ? initMap(){ ? ? ? ? ? ? const center = new TMap.LatLng(39.984120,116.307484) ? ? ? ? ? ? const container = this.$refs.modal.$slots.default[0] ? ? ? ? ? ? const map = new TMap.Map(container, { ? ? ? ? ? ? ? ? center:center, ? ? ? ? ? ? ? ? zoom:11 ? ? ? ? ? ? }) ? ? ? ? } ? ? } } </script>
Tip:vue中插槽若沒有名稱,默認(rèn)是default,所以default[0]就是default插槽中的第一個(gè)元素,即我的div#map,好了,開始調(diào)試。
但是還是有問題,地圖有時(shí)出來,有時(shí)出不來,就想到出不來時(shí),是不是因?yàn)閐iv元素還沒有渲染出來,既然這樣,那就使用vue的$nextTick了,修改open函數(shù):
open(){ ? ? this.$nextTick(()=>{ ? ? ? ? this.initMap() ? ? }) },
果然,立馬沒有問題了,無論何時(shí),地圖內(nèi)容都能正常渲染出來。
最后總結(jié)
vue中獲取/操作頁面dom元素,如果元素與template之間都是html標(biāo)簽,可以直接通過document的獲取元素方法來獲取元素,但是如果之間有自定義組件,則必須通過組件的$slots來獲取dom元素,如果有具名插槽,則要根據(jù)插槽名稱來查找對應(yīng)插槽下的元素。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue(定時(shí)器)解決mounted不能獲取到data中的數(shù)據(jù)問題
這篇文章主要介紹了Vue(定時(shí)器)解決mounted不能獲取到data中的數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07詳解Vue項(xiàng)目中出現(xiàn)Loading chunk {n} failed問題的解決方法
這篇文章主要介紹了詳解Vue項(xiàng)目中出現(xiàn)Loading chunk {n} failed問題的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09vue實(shí)現(xiàn)側(cè)邊欄導(dǎo)航效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)側(cè)邊欄導(dǎo)航效果,右側(cè)顯示對應(yīng)內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10vue3中如何使用Pinia實(shí)現(xiàn)數(shù)據(jù)持久化操作
使用vue3中的pinia,我們可以在多個(gè)頁面間共享數(shù)據(jù),但是一旦我們關(guān)閉或刷新頁面,這些數(shù)據(jù)就會丟失,因此,我們需要有一種數(shù)據(jù)持久化的解決方案,下面我們就來看看具體如何解決的吧2023-10-10