iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue实现列表左右联动效果
  • 224
分享到

vue实现列表左右联动效果

2024-04-02 19:04:59 224人浏览 安东尼
摘要

本文实例为大家分享了Vue实现列表左右联动效果的具体代码,供大家参考,具体内容如下 先谈需求:左侧为分类列表,点击分类名右侧商品列表会滑动对应分类到顶部;右侧商品列表滑动到某一分类时

本文实例为大家分享了Vue实现列表左右联动效果的具体代码,供大家参考,具体内容如下

先谈需求:左侧为分类列表,点击分类名右侧商品列表会滑动对应分类到顶部;右侧商品列表滑动到某一分类时左侧分类列表对应分类会滑动到顶部高亮显示。

再来说说思路:

1、引用swiper插件,这种方法冲突和不适配可能性太多,会越改越麻烦所以弃用。
2、使用页面滑动scroll事件,引入better-scroll组件。这个较为轻便,可自定义性较大,可以使用。

实现步骤:

1、左右两侧均使用v-for循环列表,使用index来索引目录。js中使用数组下标来和列表index对应,实现左右互通功能。
2、左右列表都在循环列表的父层增加ref绑定,获取对应的列表滚动,以及对应元素高度,从而根据高度来判断需要滑动的距离。

效果图:

页面基础代码:

<template>
  <div class="wrap">
    <!-- 顶部搜索 -->
    <div class="topMenu">
      <img class="back_l" @click="GoBack" src="./img/backicon@2x.png">
      <div class="section">
        <img class="saleR" src="./img/sub.png">
        <input placeholder="搜索商家和商品" auto-focus @keyup.enter="submitTop"/>
      </div>
      <img class="saleR" @click="goMap" src="./img/citydw.png">
    </div>
    <div class='no_sroll' v-if="navList">
      <aside class="tabNav" ref="l_list">
        <ul>
          <li ref="l_item" class="nav_li" :class="(TabNavList == index) ? 'checkIn' : ''" :index="index" :id="index" @click="checkNavList(item, index)" v-for="(item, index) in navList" :key="index">
            <img class="imgLi" src="./img/shu@2x.png" v-if="TabNavList == index" />{{item.GCName}}
          </li>
        </ul>
      </aside>
      <!-- 增加浮动层 -->
      <div class="theFixed" :class="(TabNavList == index) ? 'isFixed' : 'isHide'" v-if="scrollTrue">
        <div class="leftName">{{scrollTrue.gcName}}</div>
        <div class="rightBtn" @click="goTwoClass(scrollTrue)">全部分类<img class="r_img_btn" src="./img/jiantou.png"></div>
      </div>
      <section class="newHeight" ref="r_list">
        <div >
          <div class="proList" v-for="(item, index) in navList" :key="index" ref="good">
            <div class="r_top">
              <div class="leftName">{{item.gcName}}</div>
              <div class="rightBtn" @click="goTwoClass(item)">全部分类<img class="r_img_btn" src="./img/jiantou.png"></div>
            </div>
            <div class="r_cont">
              <div class="cu-items" v-for="(item, index) in (item.childList)" :key="index" @click="goThreeCalss(item)">
                <div class="storeL">
                  <img v-if="item.classImg" :src="item.classImg" alt=""/>
                  <img v-else src="../../carManage/img/zwt.png"/>
                </div>
                <div class="text">{{item.gcName}}</div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>
<script>
  // import {baseUrl} from '@/common/js/paths'
  import Better from 'better-scroll'
  export default {
    name: 'allStoreClass',
    components: {
      Better
    },
    data () {
      return {
        loadStatus: true,
        bodyHeight: window.innerHeight + 'px',
        storeName: '',
        distance: '',
        positionArea: '',
        positionPoint: {
          lng: '',
          lat: ''
        },
        center: {
          lng: '',
          lat: ''
        },
        zoom: 15,
        index: 0,
        gcName: '',
        gcParentId: '',
        searchBarFixed: false,
        scrollY: 0, // 定义的Y滚动轴及初始值
        TabNavList: 0, // 左右联动取值
        scrollTrue: '', // 右侧吸顶
        navList: [], // 全局列表
        isScroll: false,
        pageIndex: 1,
        pageSize: 20,
        markerPoint: {
          'lng': '',
          'lat': ''
        },
        arr: [0],
        flag: true,
        obj: null,
        show: false,
        iOS: /iphone os/g.test(window.navigator.userAgent.toLowerCase())
      }
    },
    computed: {
      // 001
    },
    created () {
      // this.$store.commit('setTopDisplay', false)
      // this.$store.commit('setPageTitle', '分类列表')
      if (this.$store.state.platfORM === 'app') {
        // eslint-disable-next-line no-undef
        let location = JSON.parse(native.getLocation())
        this.positionPoint.lng = location.longitude
        this.positionPoint.lat = location.latitude
        this.positionArea = location.city
        this.getList()
      } else if (this.$store.state.from === 'bjsh') { // 更改北京石化来源
        this.getList()
      } else {
        this.getPositionJs()
        this.getList()
      }
    },
    mounted () {
      this.$nextTick(() => {
        this._initScroll()
        this._getHeight()
      })
      if (this.$store.state.platform === 'app') {
        // eslint-disable-next-line no-undef
        native.ifShowTitleBarView(false)
      } else if (this.$store.state.platform === 'WEB') {
        this.$store.commit('setTopDisplay', false)
      }
    },
    methods: {
      goBack () {
        if (this.$store.state.platform === 'app') {
          // eslint-disable-next-line no-undef
          native.goBack()
        } else if (this.$store.state.from === 'hnsh') { // 更改与北京石化交互
          // 河南石化交互
          let params = {
            type: 'turnback',
            index: -1
          }
          this.$bridge.callhandler('phonebridge', params, (data) => {
          })
        } else {
          history.go(-1)
        }
      },
      _initScroll () {
        this.left = new Better(this.$refs.l_list, {
          click: true,
          probeType: 3
        })
        this.rgt = new Better(this.$refs.r_list, {
          probeType: 3,
          click: true
        })
        this.rgt.on('scroll', (res) => {
          if (this.flag) {
            this.scrollY = Math.abs(res.y) + 16 // 页面内有一个16像素的顶部状态栏
            for (let i = 0; i < this.arr.length; i++) {
              if (this.scrollY > this.arr[i] && this.scrollY < this.arr[i + 1]) {
                this.TabNavList = i - 1 // 左右联动取值
                // console.log(this.navList[this.TabNavList].gcName) // 取出元素的gcName
                this.scrollTrue = this.navList[this.TabNavList]
                this.isScroll = true
                // document.getElementById(this.TabNavList).scrollIntoView()
                this.left.scrollToElement(this.$refs.l_list, 100, 0, this.TabNavList * 60)
              }
            }
          }
        })
        this.left.on('scroll', (res) => {
          if (this.flag) {
            this.scrollY = Math.abs(res.y) + 16
            this.left.scrollToElement(this.$refs.l_list[this.TabNavList], 100, 0, 0)
          }
        })
      },
      _getHeight () {
        // // 开始改造
        let rightItems = this.$refs.r_list.getElementsByClassName('proList')
        setTimeout(() => { // 根据betterScroll定义滚动
          console.log(rightItems) // 右侧列表数组内容
          console.log(rightItems.length) // 右侧列表数组长度
          if (rightItems && (rightItems.length > 0)) {
            let height = 0
            this.arr.push(height)
            for (let i = 0; i < rightItems.length; i++) {
              let item = rightItems[i]
              height += item.clientHeight
              this.arr.push(height)
            }
          }
        }, 600)
      },
      getList (e) {
        this.axios.get(`v4/goodsManage/goodsClass`, {
          params: {
            keyWords: e || '', // 关键词
            pageNo: this.pageIndex,
            pageSize: this.pageSize
          }
        }).then((res) => {
          if (res.data.isSuccess) {
            // console.log(res.data.resultData)
            this.navList = res.data.resultData
            // this.scrollTrue = res.data.resultData[0]
          } else {
            this.$toast(res.data.message)
          }
        }).catch(err => {
          console.log(err)
          this.$toast('请求失败,请稍后重试')
        })
      },
      getPositionJs () {
        let _this = this
        // eslint-disable-next-line no-undef
        var geolocation = new BMap.Geolocation()
        geolocation.getCurrentPosition(function (r) {
          // eslint-disable-next-line no-undef
          if (this.getStatus() === BMAP_STATUS_SUCCESS) {
            console.log('是否成功定位')
            _this.positionPoint.lng = r.point.lng
            _this.positionPoint.lat = r.point.lat
            _this.positionArea = r.address.city
          } else {
            var info = '未能获取当前地理定位, 请检查手机是否已打开位置服务! ' + '\n' + '失败: ' + this.getStatus()
            alert(info)
          }
        }, {enableHighAccuracy: true})
      },
      getDetails (it) {
        this.show = !this.show
        this.obj = it
      },
      // 顶部搜索
      submitTop (e) {
        console.log(e.target.value)
        let obj = e.target.value
        this.getList(obj)
      },
      // 顶部跳地图
      goMap () {
        this.$router.push({name: 'nearStore', query: {from: 'storeIndex', sortFlag: this.curSort, gcName: this.gcName, gcParentId: this.gcParentId, lat1: this.positionPoint.lat, lon1: this.positionPoint.lng}})
      },
      // 左侧选择TAB
      checkNavList (e, v) {
        console.log(e, v)
        this.gcName = e.gcName
        this.gcParentId = e.gcParentId
        this.flag = false
        this.TabNavList = v // 左右联动取值
        this.rgt.scrollToElement(this.$refs.good[v], 100, 0, 0)
        setTimeout(() => {
          this.flag = true
        }, 100)
        // document.getElementById(v).scrollIntoView()
        // this.searchBarFixed = true
      },
      // 一级分类查看全部
      goTwoClass (e) {
        console.log(e)
        this.$router.push({name: 'classProList', query: {gcName: e.gcName, gcParentId: e.gcId, gcId: ''}})
      },
      // 去二级分类详情
      goThreeCalss (e) {
        console.log(e)
        this.$router.push({name: 'classProList', query: {gcName: e.gcName, gcParentId: '', gcId: e.gcId}})
      },
      mapClick (item) { // item.storeName, item.distance, item.storeWd, item.storeJd
        let lng = item.storeJd
        let lat = item.storeWd
        let name = item.storeName
        if (this.$store.state.platform === 'app') {
          if (typeof (native) !== 'undefined') {
            // eslint-disable-next-line no-undef
            native.daoHangWithLat(lat, lng, name)
          }
        } else if (this.$store.state.from === 'hnsh') {
          let params = {
            startlat: this.positionPoint.lat,
            startlong: this.positionPoint.lng,
            endlat: lat,
            endlong: lng,
            type: 'nav'
          }
          this.$bridge.callhandler('phonebridge', params, (data) => {
          })
        } else {
          location.href = 'https://api.map.baidu.com/marker?location=' + lat + ',' + lng + '&title=目的位置&content=' + name + '&output=html&hidjhnavigation=1&jhWebView=1'
        }
      },
      mapModalClick (lng, lat, name, distance, address) {
        this.mapModal = true
        this.$router.push({name: 'bdMap', query: {lng: lng, lat: lat, name: name, distance: distance, address: address}})
        
        
        // eslint-disable-next-line no-undef
        map.centerAndZoom(new BMap.Point(lng, lat), 18)
      },
      syncCenterAndZoom (e) {
        const {lng, lat} = e.target.getCenter()
        this.center.lng = lng
        this.center.lat = lat
        this.zoom = e.target.getZoom()
      },
      draw ({el, BMap, map}) {
        const pixel = map.pointToOverlayPixel(new BMap.Point(116.404, 39.915))
        el.style.left = pixel.x - 60 + 'px'
        el.style.top = pixel.y - 20 + 'px'
      },
      destroyed () {
        window.removeEventListener('scroll', this.handleScroll, true)
      }
    }
  }
</script>
<style scoped>
.wrap{ margin: 0 auto; width: 100%;height:100%;overflow:hidden;}
.topMenu{
  width: 100%;
  position: absolute;
  margin: 0 auto;
  padding:7.5px 15px;
  background:#fff;
  z-index:19;
  display: flex;
  justify-content: space-between;
}
.section {
  width:80%;
  height:30px;
  background:rgba(242,242,242,1);
  border-radius:15px;
  display: flex;
  margin-left:15px;
  margin-right:15px;
}
.section input{
  font-size:12px;
  font-weight:400;
  color:rgba(153,153,153,1);
  line-height:20px;
  border: none;
  background:rgba(242,242,242,1);
  outline:none;
}
.back_l{
  width:30px;
  height:30px;
}
.saleR{
  width:30px;
  height:30px;
}
.no_sroll {margin:0 auto; width:100%;height:100%;padding-top:45px; overflow:hidden; position:relative; display:flex;}
.main { display: -webkit-flex; display: flex; flex-flow: column nowrap;justify-content: center;align-items: center; height: 100%;text-align: center;margin-bottom: 20px;}
.top_top { margin-top:-50px; position:relative; z-index:999;}
.marginTop{margin-top:45px;}
.goback {position: absolute; left: 0; top: 0; width: .9rem; padding-left: .3rem; text-align: left;}
.newHeight {display:block; overflow: hidden; background:#fff; position:relative; width:75%;padding:0 10px;overflow-y:scroll;overflow-x:hidden;-webkit-overflow-scrolling: touch;}
.newHeight .cu-items { position: relative; display: flex; float:left; flex-direction:column; align-items: center; width:30%; height:110px; margin-left: 4.5%; margin-bottom:10px;}
.newHeight .cu-items:nth-of-type(3n-2) { margin-left:0;}
.cu-items .storeL { width: 80px; height: 80px; position: relative; border-radius: 4px; }
.cu-items .storeL img { width: 80px; height: 80px;}
.cu-items .text {font-size:14px; line-height:18px; margin-top:5px; color:#666;}
.newHeight .proList { width:100%; display:flex; flex-direction:column; position:relative;}
.newHeight .proList .r_top { height:60px;display:flex;justify-content:space-between;align-items:center;}
.newHeight .proList .r_top .leftName { line-height:60px; font-size:16px; text-align:left; color:#666; margin-left:10px;}
.newHeight .proList .r_top .rightBtn {font-size:12px;line-height:60px;color:#2CBF64;}
.newHeight .proList .r_top .rightBtn .r_img_btn {width:11px;height:11px;margin-left:5px;transform:rotate(270deg);}
.theFixed {height:60px;display:flex;justify-content:space-between;align-items:center;}
.theFixed .rightBtn {font-size:12px;line-height:60px;color:#2CBF64;}
.theFixed .rightBtn .r_img_btn {width:11px;height:11px;margin-left:5px;transform:rotate(270deg);}
.theFixed .leftName {line-height:60px; font-size:16px; text-align:left; color:#666; margin-left:10px;}

.tabNav { display: block;width:25%; background:#F5F5F2;overflow: hidden; position:relative; overflow-y:scroll; overflow-x:hidden; -webkit-overflow-scrolling: touch;}
.tabNav::-webkit-scrollbar { display:none;}
.tabNav::scrollbar { display:nonel}
.tabNav .nav_list { display:flex; width:100%;}
.tabNav .nav_li { font-size:16px; line-height:20px; color:#666; text-align:center; height: 60px; width:100%; flex-shrink: 0; position:relative; display: flex; justify-content: center; align-items: center;}
.tabNav .nav_li .imgLi { height:16px; position: absolute; left:0; top: 22px;}
.checkIn { color:#2CBF64!important; background:#fff!important; font-weight:bold;}
.isFixed { 
  height:60px;
  line-height:60px;
  font-size:16px;
  text-align:left;
  color:#666; 
  position:fixed;
  width:70%;
  left:27%;
  background: #fff;
  z-index: 19;
}
.isHide {
  position: fixed;
  height:60px;
  line-height:60px;
  font-size:16px;
  text-align:left;
  color:#666; 
  width:70%;
  left:27%;
  background: #fff;
  z-index: 19;
}
</style>
<style>
  .BMap_cpyCtrl { display: none; }
  .anchorBL { display: none; }
  .BMap_noprint.anchorBL { display: block; bottom: 259px!important; }
  .BMap_stdMpCtrl { display: block; bottom: 269px!important; }
  .BMap_pop { position: absolute;}
</style>

备注:代码做了二期优化

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: vue实现列表左右联动效果

本文链接: https://www.lsjlt.com/news/146084.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue实现列表左右联动效果
    本文实例为大家分享了vue实现列表左右联动效果的具体代码,供大家参考,具体内容如下 先谈需求:左侧为分类列表,点击分类名右侧商品列表会滑动对应分类到顶部;右侧商品列表滑动到某一分类时...
    99+
    2022-11-13
  • vue实现左右点击滚动效果
    本文实例为大家分享了vue实现左右点击滚动,效果如图 涉及功能点 1、在created中使用r e f s 结 合 refs结合refs结合nextTick仍然无法获取到元素的问题...
    99+
    2022-11-13
  • vue实现左右滑动效果实例代码
    前言 个人实际开发中用到的效果问题总结出来便于自己以后开发查看调用,如果也适用其他人请随意拿走勿喷就行! vue.js是现在流行的js框架之一,vue 是一套用于构建用户界面的渐进式...
    99+
    2022-11-12
  • 使用vue怎么实现左右滑动效果
    使用vue怎么实现左右滑动效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。HTML代码<template>    &l...
    99+
    2023-06-15
  • 微信小程序实现菜单左右联动效果
    本文实例为大家分享了微信小程序实现菜单左右联动效果的具体代码,供大家参考,具体内容如下 原理 首先是获取数据,并且获取数据的长度(需要根据长度来计算元素的高度),通过遍历数据的内容通...
    99+
    2022-11-13
  • 微信小程序scroll-view实现左右联动效果
    微信小程序利用scroll-view实现左右联动,供大家参考,具体内容如下 点击左边的按钮时,右边可以跳动到指定的位置 首先要注意使用scroll-view竖屏滚动,需要给...
    99+
    2022-11-12
  • React实现二级联动(左右联动)
    本文实例为大家分享了React实现二级联动的具体代码,供大家参考,具体内容如下 js代码 import { Component } from 'react' import './...
    99+
    2022-11-12
  • uni-app制作小程序实现左右菜单联动效果
    目录前言一、示意图二、实现步骤与思路讲解1.静态页面的布局2.模拟数据格式3.左侧菜单的点击效果4.右侧菜单的联动效果三、具体实现代码1.页面结构2.相关样式3.业务逻辑部分前言 今...
    99+
    2022-11-16
    uni-app左右菜单联动 uni-app菜单联动 uni-app左右联动 uniapp 小程序菜单
  • Android实现图片左右滑动效果
    关于滑动效果,在Android中用得比较多,本示例实现的滑动效果是使用ViewFlipper来实现的,当然也可以使用其它的View来实现。接下来就让我们开始实现这种效果。 接...
    99+
    2022-06-06
    图片 动效 Android
  • swiper+echarts实现多个仪表盘左右滚动效果
    本文实例为大家分享了swiper+echarts实现仪表盘左右滚动效果的具体代码,供大家参考,具体内容如下 1、swiper的使用 a.首先加载插件 <!DOCTYPE h...
    99+
    2022-11-12
  • 如何用css实现左右运动效果
    本篇内容介绍了“如何用css实现左右运动效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2022-10-19
  • Jquery实现多选下拉列表左右移动
    本文实例为大家分享了Jquery实现多选下拉列表左右移动的具体代码,供大家参考,具体内容如下 jquery实现核心代码 //需求:实现下拉列表选择条目左右选择功能         ...
    99+
    2022-11-13
  • Android实现左右摆动的球体动画效果
    首先,看一下效果   可能各位在别处看到过类似的东西,我在微信的文章末尾看到有个玩意,感觉有意思,就用代码实现一下。这篇文章主要把握写代码的思路展示一下。 ...
    99+
    2022-06-06
    动画 Android
  • swiper+echarts如何实现多个仪表盘左右滚动效果
    这篇文章将为大家详细讲解有关swiper+echarts如何实现多个仪表盘左右滚动效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、swiper的使用a.首先加载插件<!DOCTYPE ...
    99+
    2023-06-20
  • android左右滑动切换效果怎么实现
    在Android中,可以通过使用ViewPager组件来实现左右滑动切换效果。 首先,在XML布局文件中添加一个ViewPager组...
    99+
    2023-10-23
    android
  • css3如何实现左右伸缩动画效果
    这篇文章主要为大家展示了“css3如何实现左右伸缩动画效果”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“css3如何实现左右伸缩动画效果”这篇文章吧。 ...
    99+
    2022-10-19
  • 怎么用uni-app制作小程序实现左右菜单联动效果
    这篇文章主要介绍“怎么用uni-app制作小程序实现左右菜单联动效果”,在日常操作中,相信很多人在怎么用uni-app制作小程序实现左右菜单联动效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用uni-...
    99+
    2023-07-04
  • vue实现列表无缝滚动效果
    本文实例为大家分享了vue实现列表无缝滚动效果的具体代码,供大家参考,具体内容如下 1.安装 npm install vue-seamless-scroll --save 2.在需要...
    99+
    2022-11-13
  • 微信小程序实现左右联动
    本文实例为大家分享了微信小程序实现左右联动的具体代码,供大家参考,具体内容如下 最近学校课程系统分析项目使用了微信小程序来进行搭建,在选择了点餐项目后,对主页进行实现时,想要实现像麦...
    99+
    2022-11-12
  • Android实现左右滑动效果的方法详解
    本示例演示在Android中实现图片左右滑动效果。关于滑动效果,在Android中用得比较多,本示例实现的滑动效果是使用ViewFlipper来实现的,当然也可以使用其它的Vi...
    99+
    2022-06-06
    方法 动效 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作