时间:2022-11-22 10:56:55 | 栏目:vue | 点击:次
在自定义hooks的onMounted事件里面 获取ref元素,组件调用hooks的时候必须要传递响应式对象。
代码如下
<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) // 这里传递过去的是一个响应式对象 const { currentPageIndex: currentPageIndex1 } = useBars(rootRef) // 这里传递过去的就是一个null,而不是对象 console.log('组件 setup 最后一段') return { rootRef, currentPageIndex, } }, }) </script>
// useBar.js import { onMounted } from 'vue' export default function useSliders(rootRef) { /** * 1. 传递过来是一个响应式对象 * * 传过来是一个响应式对象,调用这个函数的时候rootRef.value = nul * 组件实例化完毕,在组件里面 rootRef.value = <div></div> * 执行 这个onmonted事件,里面就获取到了一个div,这个onMounted事件是当组件实例化完毕才会执行的 */ /** * 传过来就是一个null * onMounted 执行的时候自然也是null * */ // ! 感觉是访问同一个地址,如果传递一个响应式对象,然后组件里面给 rootRef.value赋值,这里就也能拿到了 onMounted(() => { // debugger console.log('hooks slider mounted --->', rootRef) }) return {} }```
最近刚做了一个项目,需要用到地图,选择的是腾讯地图,创建地图的时候,需要给地图创建函数中传入地图容器的id或者容器的dom元素,但是在调试过程中,发现怎么都无法获取dom元素,直接通过getElementById也无法获取元素内容。
<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>
页面调试的时候,一直报错,无法读取到id的值,直接打印container的值,却是null,但是看了网上其他使用腾讯地图的例子,基本上是一样的思路。
然后就开始找问题,一直折腾,最后才想到是不是因为我把地图容器放到a-modal组件中的原因,然后对比网上的代码,才发现,别人的都是直接放在template中,或者使用其他html元素包裹,而我把地图容器放到了a-modal组件中。
这时就想到,是不是可以通过a-modal组件来获取dom元素,然后就给a-modal组件加上ref属性,代码如下
<a-modal ref="modal"> <div id="map"></div> </a-modal>
然后打印this.$refs.modal,观察打印的对象,看能不能找到dom元素内容,又想到容器元素被a-modal包裹,相当于使用插槽,所以找到了$slots.default属性,在上面找到了渲染的VNode,终于找到了div#map元素。
既然找到了,那把这个元素传给地图创建函数就行,说做就做,立即改代码。
<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中插槽若没有名称,默认是default,所以default[0]就是default插槽中的第一个元素,即我的div#map,好了,开始调试。
但是还是有问题,地图有时出来,有时出不来,就想到出不来时,是不是因为div元素还没有渲染出来,既然这样,那就使用vue的$nextTick了,修改open函数:
open(){ this.$nextTick(()=>{ this.initMap() }) },
果然,立马没有问题了,无论何时,地图内容都能正常渲染出来。
vue中获取/操作页面dom元素,如果元素与template之间都是html标签,可以直接通过document的获取元素方法来获取元素,但是如果之间有自定义组件,则必须通过组件的$slots来获取dom元素,如果有具名插槽,则要根据插槽名称来查找对应插槽下的元素。