頁面布局和樣式就不浪費時間了,直接上代碼了
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>新聞熱點
疑難解答