IScroll中文文檔css
第一個問題: 邊界留白vue
就是這種,上邊界(最小),下邊界(最大)有兩個列表的位置是不能選擇的。解決的辦法是:es6
在HTML中,添加空白節點就好了。app
第二個問題:初始化以後的滾動中止的事件的第二個參數問題。 函數
var myScroll = new IScroll('#wrapper'); myScroll.on('scrollEnd', function(){ //這裏必定不要寫成es6箭頭函數 //要執行的代碼 //這個函數沒有參數 });
(1) 第二的個參數,是個函數。它沒有參數,並且不要寫成,不要寫成,不要寫成箭頭的形式。由於這函數裏面的this,是綁定的一些有用信息,好比:this.y是當前滾動的距離等。還有哪些信息能夠看 文檔中的 滾動條信息 這一欄。若是寫成ES6的形式,那this指向就變了,這樣就獲取不了所需的信息。this
(2) 第二個參數是沒有形參的。即沒有任何可以使用的參數。spa
第三個問題:定義了snap選項,可是滾動有誤差code
開發的日曆選擇組件picker是使用rem單位自適應的,雖然在配置項中 有個options.snap,官方說能夠對齊到固定的位置和元素,可是在使用自適應單位的狀況中,這個配置並無展示出真正的效果,滾動的時候必定會出現誤差。對象
那怎麼解決這個自適應的問題呢?因爲是在滾動結束以後,位置纔出現的誤差。那麼我就在滾動結束以後立馬調用修正位置的函數就好了。blog
我是在vue中使用的。因此定義下面的函數,由於有 年,月,日,時四個滾動項。因此須要判斷是哪個正在滾動
fixPos: function(target,num) { var step = Math.abs(Math.round(target.y / this.itemHeight)); var maxYearLen = this.yearArr.length; var maxMonthLen = this.monthArr.length; var maxDayLen = this.dayArr.length; var maxHourLen = this.hourArr.length; switch(num){ case 0: step = step > maxYearLen ? maxYearLen - 1 : step; break; case 1: step = step > maxMonthLen ? maxMonthLen - 1 : step; break; case 2: step = step > maxDayLen ? maxDayLen - 1 : step; break; case 3: step = step > maxHourLen ? maxHourLen - 1 : step; break; } var fixPos = step * this.itemHeight;//從新計算較爲精確的位置 target.y = fixPos;//重置原來的滾動距離 this.selectArr[num] = step;//這是保存每一個列表滾動的索引值 target.scrollTo(0, -fixPos);//這是滾動到修正後的位置 },
(1) 大體的思路就是:首先用當前滾動的距離,來除以滾動內容中,每一個列表的高度。而後取最近似的值,就是當前應該滾動的列表的個數。
(2) 若是出現忽然滾動到最底部,這時候須要滾動的個數大於了滾動內容的最大列表個數,那麼就糾正一下個數爲最大列表數 - 1。
(3) 而後設置較爲精確的滾動距離。再滾動到指定的位置。
(4) this.itemHeight是在created生命週期的時候就聲明的 this.itemHeight = (document.body.offsetWidth / 750) * 100 * 0.8; 至關於在375px寬度下,每一個列表就是40px的高度。在iPhone5 320px下,就是34.133334了。
調用的時候:
var yearScroll = new IScroll('#calendarYear'); var that = this; yearScroll.on('scrollEnd', function() { that.fixPos(this, 0); })
第四個問題:使用自適應單位時最大滾動距離不許確
這個問題和第二個問題相似,解決的方法:
fixMaxScrollY: function(target, num) { var yearLen = this.yearArr.length - 1; var monthLen = this.monthArr.length - 1; var dayLen = this.dayArr.length - 1; var hourLen = this.hourArr.length - 1; switch(num) { case 0: target.maxScrollY = -(Math.round(yearLen * this.itemHeight)); break; case 1: target.maxScrollY = -(Math.round(monthLen * this.itemHeight)); break; case 2: target.maxScrollY = -(Math.round(dayLen * this.itemHeight)); break; case 3: target.maxScrollY = -(Math.round(hourLen * this.itemHeight)); break; } },
(1) 實例化後的滾動對象,有個最大滾動值maxScrollY,主要也是根據滾動內容的列表長度來重置最大滾動距離
(2) 由於有四個滾動的內容項,因此須要傳入當前是第幾個滾動的內容。
調用的時候:
var yearScroll = new IScroll('#calendarYear'); this.fixMaxScrollY(yearScroll, 0);
第五個問題: 日曆組件的內容是在點擊某個按鈕以後再觸發顯示的,最初是隱藏。但就是這個緣由,致使顯示出來的內容滾動不了。
解決的辦法是:使用 xxx.refresh() 刷新函數。這個函數具體的說明能夠看文檔中 刷新 這個選項內容
在控制組件顯示的函數中,調用刷新的方法。
this.$nextTick(function(){ this.scrollTarget[0].refresh(); this.scrollTarget[1].refresh(); this.scrollTarget[2].refresh(); this.scrollTarget[3].refresh(); //若是默認隱藏,則必須修復滾動的位置 this.scrollTarget[0].scrollTo(0, -this.itemHeight * this.selectArr[0]); this.scrollTarget[1].scrollTo(0, -this.itemHeight * this.selectArr[1]); this.scrollTarget[2].scrollTo(0, -this.itemHeight * this.selectArr[2]); this.scrollTarget[3].scrollTo(0, -this.itemHeight * this.selectArr[3]); })
(1) scrollTarget 是初始化滾動實例以後,保存的滾動實例。由於屢次會用到。
(2) 由於有年,月,日,時四個滾動內容,因此要刷新四個滾動器。
(3) 若是日曆有最初的滾動位置,那麼也會出現不能跳到指定的位置的問題。因此,也須要初始化最初始的位置。
(4) selectArr 是滾動器滾動的索引值。好比我月份是1月到12月,當前滾動到了6月,那麼此時selectArr[1] 就是5 。
(5) 官方是推薦用setTimeout來使用刷新,可是我使用的是vue來開發的,因此,這裏用vm.$nextTick()來代替setTimeout。
第六個問題: 日曆組件複用時,只能初始化滾動第一個日曆組件,並且第一個日曆組件滾動仍是有問題。
這個問題產生的緣由很簡單:由於 IScroll 在初始化實例的時候, var myScroll = new IScroll('.wrapper'); 它這個css選擇器使用的是querySelector
而不是 querySelectorAll
,因此iScroll只會做用到選擇器選中元素的第一個。若是你須要對多個對象使用iScroll,你須要構建本身的循環機制。這是官方的說法。那麼怎樣創建循環機制呢?難道我要在初始化的時候還要循環去 new IScroll(xxx)建立實例嗎?
其實不必。只須要改一改源碼就好了。
我使用的是 iscroll-lite 這個版本。這裏面 在定義 IScroll 這個函數的時候有這段代碼
this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
它每次初始化時,只選擇了 el 滾動對象的第一個元素,那麼,我只須要傳入當前是第幾個日曆組件,再改爲querySelectorAll就好了。即:
this.wrapper = typeof el == 'string' ? document.querySelectorAll(el)[childIndex] : el;
而後在這個定義的 IScroll 函數的參數中,再增長一個參數,表示第幾個元素。
而後在初始化滾動實例的時候:
var options = { snap: '.calendar-scroll-item', //對齊的位置,至關於自動糾正每次移動的距離 //scrollbars: true,//是否顯示滾動條 } //初始化滾動 var yearScroll = new IScroll('.calendar-scroll>.calendarYear', options , this.curIndex);
固然這個時候,css選擇器就不要用 id 了。
而後在 組件的 prop 裏面添加一個屬性。
curIndex:{ type:Number, default:0 }
(1) 默認只使用一個組件,即不傳這個prop 的話就是默認初始化第一個組件的滾動內容。
使用組件的時候:引入,註冊等步驟就省略了
<calendar :cur-index='0'/> <calendar :cur-index='1'/> <calendar :cur-index='2'/>
這樣無論使用多少個,都能正常初始化滾動了。並且互不影響 。注意,若是傳的是數字,須要v-bind 告訴vue這不是字符串,是表達式。否則傳過去的是字符串