vue中使用scrollIntoView()让选中的下拉列表项定位在视野中

问题出现

需求需要实现一个单选下拉列表,选项在一屏显示不完,做了滚动条overflow:auto, 设置了height高度。
那就出现了一个问题,当我点击某一个item选项时,如果这个item选项不在第一屏,而在滚动后才能看到的区域,那么再次点开这个下拉菜单时无法重新定位到被选中的item所在的这一屏,所以我们需要让下拉单选菜单再次打开时自己定位到这一屏。

查阅资料

问了一下同组的有经验的姐姐,说我可以使用window.scroll这些方法,详见
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/scroll

但是这些都需要定位坐标x,y,要么就是距离下拉单选弹框顶部/底部的像素值,我觉得计算的方式都太麻烦了于是继续找方法。

后来查到了这篇文章VUE移动到指定位置(scrollIntoView)这不正是我想要的方法吗!!

应用到我的项目中的大概步骤就是

  1. 为我的v-for循环出来的每一个item绑定一个唯一的id,可以选择动态绑定:id = 'id'+item.value(value值对于每个item是唯一的,所以选用了这个参数做id值)
  2. 在每个item绑定的点击事件函数中,把这个id值传出去,传给父组件(因为这里我的按钮在父组件中,下拉单选弹框单独写了一个子组件)
  3. 然后在父组件的按钮绑定的事件中,使用documet.getElementById每次获取点击了item之后的某个item的id值,然后使用scrollIntoView函数,让这个item定位在视野屏中。

实现代码

父组件index.vue

<template>
 	<div class="fixed-icon">
      <img v-else :src="..."   @click="showPicker(dialogItemID)"/>
    </div>
    <SelectRouteDialog
      id="myDropdown"
      :route-select-click="onLiClick"
      :route-info="data"
      :is-checked="isChecked"
      :show-dialog="isShowRouteDropdown"
      @closeDialog="isShowRouteDropdown=false"/>
</template>

<script>
export default {
	data() {
		return {
			 dialogItemID: '', //从子组件中传过来的元素的id值
		}
	},
	methods:{
		/* 按钮绑定的方法 */
	    showPicker(e) {
	        this.isShowRouteDropdown = true;  //控制对话框显示
	        document.getElementById(e).scrollIntoView(); // 根据传过来的item的id,滚动到id所在视野中
	    },
	    /*每个item绑定的方法
	    	itemId —— 子组件传入的id值 */
	    onLiClick(selectedVal,itemId){
	    	const valArr = [];
			valArr.push(selectedVal);
			
			this.isShowRouteDropdown = false;
	   		this.isChecked = valArr[0];
	   		
	        this.dialogItemID = itemId;  // 点击对话框中某个item获取到它的id值存入dialogItemID
	      // console.log("dialogItemID",this.dialogItemID);
	    }
	}
}
</script>

子组件selectRouteDialog.vue

<template>
  <div name="dialog">
  	<!--就是这里之前用的v-if,导致document.getElementById(e)一直获取不到对象-->
    <div v-show="showDialog"
         id="dialog-bg"
         :data="routeInfo"
         :checked="isChecked"
         @touchMove.prevent>
      <div id="dialog">
        <!-- 对话框的头部区域 -->
        <div class="dialog-header">
          <img :src="..." @click="close" class="dialog-closed">
        </div>
        <div style="overflow: auto;height: 100%">
          <ul>
            <li class="liStyle"
                v-for="(item,index) in routeInfo"
                :key="index"
                :checked="isChecked"
                @click="routeSelectClick(item.value,'id'+item.value)"
                :id="'id'+item.value">
              <div class="routeNameStyle">
                <div class="textStyle">{{item.text}}</div>
                <img v-if="item.value===isChecked" src="~/..." class="nor-active-icon"/>
                <img v-else src="~/..." class="nor-active-icon">
              </div>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import LANGUAGE from '../../../common/js/language'
export default {
  name: "selectRouteDialog",
  props:{
    showDialog:{
      type: Boolean
    },
    isChecked:{
      type: String
    },
    title:{
      type: String
    },
    message:{
      type: String
    },
    routeInfo: {
      type: Array
    },
    routeSelectClick:{
      type: Function
    },
  },
  methods:{
    close: function (){
      this.$emit("closeDialog")
    }
  }
}
</script>

过程中出现的问题小记

明明通过父子组件传参,showPicker(e)能拿到每一个itemid。但document.getElementByID(e)却始终显示对象为null

后来我想着点开这个选择框之后,直接在控制台去看 document.getElementByID(e)能否拿到某个item的对象
果然是可以的!就说明这个id是拿得到的。这个方法也是可行的,就是代码逻辑或许有错。

然后去问同组的姐姐,她说这就说明你的这个组件的dom没有渲染完的时候,你调用了这个方法,肯定就拿不到。然后让我去判断什么时候整个线路选择组件渲染完了之后,再去获取,就可以了。

我本想问涛哥dom渲染如何判断彻底渲染完成。涛哥说那就长久的把这个dom挂载在页面上面就好。

然后瞬间想到了v-show! 我原本是用的v-if
然后改成了v-show来判断选择框的显示与否之后立马好了!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值