经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue3使用自定义hooks获取dom元素的问题说明
来源:jb51  时间:2022/4/18 12:05:21  对本文有异议

使用自定义hooks获取dom元素问题

在自定义hooks的onMounted事件里面 获取ref元素,组件调用hooks的时候必须要传递响应式对象。

分享下楼主自己的观点

代码如下

  1. <script>
  2. // demo.vue
  3. import { defineComponent, ref } from 'vue'
  4. import useBars from './useBars'
  5. export default defineComponent({
  6. ? ? props: {
  7. ? ? ? ? Bars: Array,
  8. ? ? },
  9. ? ? setup() {
  10. ? ? ? ? const rootRef = ref(null)? ? ? ? const { currentPageIndex } = useBars(rootRef) // 这里传递过去的是一个响应式对象
  11. ?? ??? ?
  12. ?? ??? ? const { currentPageIndex: currentPageIndex1 ?} = useBars(rootRef) // 这里传递过去的就是一个null,而不是对象
  13. ? ? ? ? console.log('组件 setup 最后一段')
  14. ? ? ? ? return {
  15. ? ? ? ? ? ? rootRef,
  16. ? ? ? ? ? ? currentPageIndex,
  17. ? ? ? ? }
  18. ? ? },
  19. })
  20. </script>
  1. // useBar.js
  2. import { onMounted } from 'vue'
  3. export default function useSliders(rootRef) {
  4. ?? ?
  5. /**
  6. ? ? ?* 1. 传递过来是一个响应式对象
  7. ? ? ?*
  8. ? ? ?* ?传过来是一个响应式对象,调用这个函数的时候rootRef.value = nul
  9. ? ? ?* ?组件实例化完毕,在组件里面 rootRef.value = <div></div>
  10. ? ? ?* ?执行 这个onmonted事件,里面就获取到了一个div,这个onMounted事件是当组件实例化完毕才会执行的
  11. ? ? ?*/
  12. ? ? /**
  13. ? ? ?* ?传过来就是一个null
  14. ? ? ?* ? onMounted 执行的时候自然也是null
  15. ? ? ?*?
  16. ? ? ?*/
  17. ? ? // ! 感觉是访问同一个地址,如果传递一个响应式对象,然后组件里面给 rootRef.value赋值,这里就也能拿到了
  18. ? ? onMounted(() => {
  19. ? ? ? ? // debugger
  20. ? ? ? ? console.log('hooks slider mounted --->', rootRef)
  21. ? ? })
  22. ? ? return {}
  23. }```

vue获取/操作组件的dom元素

最近刚做了一个项目,需要用到地图,选择的是腾讯地图,创建地图的时候,需要给地图创建函数中传入地图容器的id或者容器的dom元素,但是在调试过程中,发现怎么都无法获取dom元素,直接通过getElementById也无法获取元素内容。

下面是我的代码内容(非全部内容)

  1. <template>
  2. <a-modal>
  3. ? ? <div id="map"></div>
  4. </a-modal>
  5. </template>
  1. <script>
  2. import TMap from 'TMap'
  3. export default{
  4. ? ? method:{
  5. ? ? ? ? open(){
  6. ? ? ? ? ? ? this.initMap()
  7. ? ? ? ? },
  8. ? ? ? ? initMap(){
  9. ? ? ? ? ? ? const center = new TMap.LatLng(39.984120,116.307484)
  10. ? ? ? ? ? ? const container = document.getElementById('map')
  11. ? ? ? ? ? ? const map = new TMap.Map(container, {
  12. ? ? ? ? ? ? ? ? center:center,
  13. ? ? ? ? ? ? ? ? zoom:11
  14. ? ? ? ? ? ? })
  15. ? ? ? ? }
  16. ? ? }
  17. }
  18. </script>

页面调试的时候,一直报错,无法读取到id的值,直接打印container的值,却是null,但是看了网上其他使用腾讯地图的例子,基本上是一样的思路。

然后就开始找问题,一直折腾,最后才想到是不是因为我把地图容器放到a-modal组件中的原因,然后对比网上的代码,才发现,别人的都是直接放在template中,或者使用其他html元素包裹,而我把地图容器放到了a-modal组件中。

这时就想到,是不是可以通过a-modal组件来获取dom元素,然后就给a-modal组件加上ref属性,代码如下

  1. <a-modal ref="modal">
  2. ? ? <div id="map"></div>
  3. </a-modal>

然后打印this.$refs.modal,观察打印的对象,看能不能找到dom元素内容,又想到容器元素被a-modal包裹,相当于使用插槽,所以找到了$slots.default属性,在上面找到了渲染的VNode,终于找到了div#map元素。

既然找到了,那把这个元素传给地图创建函数就行,说做就做,立即改代码。

  1. <template>
  2. <a-modal ref="modal">
  3. ? ? <div id="map"></div>
  4. </a-modal>
  5. </template>
  1. <script>
  2. import TMap from 'TMap'
  3. export default{
  4. ? ? method:{
  5. ? ? ? ? open(){
  6. ? ? ? ? ? ? this.initMap()
  7. ? ? ? ? },
  8. ? ? ? ? initMap(){
  9. ? ? ? ? ? ? const center = new TMap.LatLng(39.984120,116.307484)
  10. ? ? ? ? ? ? const container = this.$refs.modal.$slots.default[0]
  11. ? ? ? ? ? ? const map = new TMap.Map(container, {
  12. ? ? ? ? ? ? ? ? center:center,
  13. ? ? ? ? ? ? ? ? zoom:11
  14. ? ? ? ? ? ? })
  15. ? ? ? ? }
  16. ? ? }
  17. }
  18. </script>

Tip:vue中插槽若没有名称,默认是default,所以default[0]就是default插槽中的第一个元素,即我的div#map,好了,开始调试。

但是还是有问题,地图有时出来,有时出不来,就想到出不来时,是不是因为div元素还没有渲染出来,既然这样,那就使用vue的$nextTick了,修改open函数:

  1. open(){
  2. ? ? this.$nextTick(()=>{
  3. ? ? ? ? this.initMap()
  4. ? ? })
  5. },

果然,立马没有问题了,无论何时,地图内容都能正常渲染出来。

最后总结

vue中获取/操作页面dom元素,如果元素与template之间都是html标签,可以直接通过document的获取元素方法来获取元素,但是如果之间有自定义组件,则必须通过组件的$slots来获取dom元素,如果有具名插槽,则要根据插槽名称来查找对应插槽下的元素。 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号