页面布局和样式就不浪费时间了,直接上代码了
ref="foodwrapper"
,然后在函数内用this.$refs.menuwrapper
获取到dom。 然后在Ajax内执行_initScroll() 函数,这个时候需要注意两点,第一使用bs插件的时候子容器的高度一定要大于父容器的高度,才会产生滚动效果。第二,我们要等dom结构完全加载结束在调用_initScroll()方法才会生效,vue的作者也为我们提供了方法,来判断dom结构是否完全加载this.$nextTick(() => {})
,click: true
属性用来设置可以进行点击事件。 _initScroll() { this.meunScroll = new BScroll(this.$refs.menuwrapper, { click: true }); this.foodScroll = new BScroll(this.$refs.foodwrapper, { click: true }); }这时候created应改为 created() { this.classMap = ['decrease', 'discount', 'guarantee', 'invoice', 'special']; this.$http.get('./data.json').then((res) => { if(res.status === ERR_OK) { res = res.body.goods; this.goods = res; //dom结构加载结束 this.$nextTick(() => { this._initScroll(); }) } }); }, 下面实现左右联动并且实现文本的高亮,左右联动的基本原理其实我们计算出右侧实时变化的y值,落到哪一个区间,我们就显示那一个区间。首先我们要计算整体区间的一个高度,然后分别计算第一个区间的高度,第二个区间的高度,以此类推。然后将区间数存入一个定义好的数组。当我们在滚动的时候实时拿到y轴的高度,然后对比在哪一个区间,这样我们就会得到一个区间的索引值去对应左侧的菜品类别,最后我们用一个vue的class去绑定高亮文本。 定义一个方法在_initScroll下面,作为计算高度的方法叫做_calculateHeight () ,在定义一个listHeight:[]数组,存放获取的高度。我们在定义一个food-list-hook类,用来被js选择。不要忘记在created内调用函数。_calculateHeight () { let foodList = this.$refs.foodwrapper.getElementsByClassName('food-list-hook'); let height = 0; //把第一个高度送入数组 this.listHeight.push(height); //通过循环foodList下的dom结构,将每一个li的高度依次送入数组 for(let i=0; i<foodList.length; i++){ let item = foodList[i] height += item.clientHeight this.listHeight.push(height); } },我们获取到区间高度数组后,我们要实时获取到右侧的y值,和左侧的索引值做一个对比,定义一个scrollY变量用来存放实时获取的y值。bs插件为我们提供了一个实时获取y值的方法,我们在初始化this.foodScroll
的时候加一个·属性probeType: 3
,其作用就是实时获取y值,相当于探针的作用。 我们在添加一个方法this.foodScroll.on('scroll',(pos) => {})
,作用是实时滚动的时候把获取到的位置给暴露出来。代码如下。 methods: { _initScroll() { this.meunScroll = new BScroll(this.$refs.menuwrapper, { click: true }); this.foodScroll = new BScroll(this.$refs.foodwrapper, { click: true, //探针作用,实时监测滚动位置 probeType: 3 }); //设置监听滚动位置 this.foodScroll.on('scroll', (pos) => { //scrollY接收变量 this.scrollY = Math.abs(Math.round(pos.y)); }) }, _calculateHeight() { let foodList = this.$refs.foodwrapper.getElementsByClassName('food-list-hook'); let height = 0; //把第一个高度送入数组 this.listHeight.push(height); //通过循环foodList下的dom结构,将每一个li的高度依次送入数组 for(let i = 0; i < foodList.length; i++) { let item = foodList[i] height += item.clientHeight this.listHeight.push(height); } }, }定义一个计算属性computed,用来计算左侧对应的i值,从而定位到左侧边栏的位置 computed:{ currentIndex () { for(let i=0; i<this.listHeight.length; i++){ //判断当currentIndex在height1和height2之间的时候显示 let height1 = this.listHeight[i]; let height2 = this.listHeight[i+1]; //最后一个区间没有height2 if(!height2 || (this.scrollY >= height1 && this.scrollY < height2)){ return i; } } return 0; },获取到i后,在menu-item绑定一个class:class="{'current':currentIndex === index}"
,当currentIndex和menu-item对应的index相等时,设置current的样式。这样就可以左右联动了。 最后实现左侧点击的功能。在左侧的li下绑定一个selectMenu的点击事件,并传入索引值,这样我们就可以知道点击的是哪一个li selectMenu (index,event) {// 自己默认派发事件时候(BScroll),_constructed被置为true,但是浏览器原生并没有这个属性 if (!event._constructed){ return; } //运用BScroll接口,滚动到相应位置 let foodList = this.$refs.foodwrapper.getElementsByClassName('food-list-hook'); //获取对应元素的列表 let el = foodList[index]; //设置滚动时间 this.foodScroll.scrollToElement(el, 300); },至此,我们就用bs插件完成了这个左右页面联动的效果,代码会上传到github,有兴趣的可以下载下来看一看,大神务喷!完整的js代码 <script type="text/javascript"> var ERR_OK = 200; new Vue({ el: '.goods', data() { return { msg: 'goods', goods: [], listHeight: [], scrollY: 0, } }, created() { this.classMap = ['decrease', 'discount', 'guarantee', 'invoice', 'special']; this.$http.get('./data.json').then((res) => { if(res.status === ERR_OK) { res = res.body.goods; this.goods = res; //dom结构加载结束 this.$nextTick(() => { this._initScroll(); //计算高度 this._calculateHeight(); }) } }); }, computed: { currentIndex() { for(let i = 0; i < this.listHeight.length; i++) { //判断当currentIndex在height1和height2之间的时候显示 let height1 = this.listHeight[i]; let height2 = this.listHeight[i + 1]; // console.log('height1:'+height1+','+'height2:'+height2) //最后一个区间没有height2 if(!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { return i; } } return 0; } }, methods: { selectMenu(index, event) { // 自己默认派发事件时候(BScroll),_constructed被置为true,但是浏览器原生并没有这个属性 if(!event._constructed) { return; } //运用BScroll接口,滚动到相应位置 let foodList = this.$refs.foodwrapper.getElementsByClassName('food-list-hook'); //获取对应元素的列表 let el = foodList[index]; this.foodScroll.scrollToElement(el, 300); }, _initScroll() { this.meunScroll = new BScroll(this.$refs.menuwrapper, { click: true }); this.foodScroll = new BScroll(this.$refs.foodwrapper, { click: true, //探针作用,实时监测滚动位置 probeType: 3 }); //设置监听滚动位置 this.foodScroll.on('scroll', (pos) => { //scrollY接收变量 this.scrollY = Math.abs(Math.round(pos.y)); }) }, _calculateHeight() { let foodList = this.$refs.foodwrapper.getElementsByClassName('food-list-hook'); let height = 0; //把第一个高度送入数组 this.listHeight.push(height); //通过循环foodList下的dom结构,将每一个li的高度依次送入数组 for(let i = 0; i < foodList.length; i++) { let item = foodList[i] height += item.clientHeight this.listHeight.push(height); } }, } }) </script>新闻热点
疑难解答