Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一级黄色录像在线观看,精品视频亚洲,小草社区在线视频

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線:

          「Vue項(xiàng)目」中的滾動(dòng)組件&聯(lián)動(dòng)效果從0到1(建議收藏)


          最近的一個(gè)項(xiàng)目做的是vue組件中的一個(gè)應(yīng)用,「處理滾動(dòng)列表」,這個(gè)應(yīng)該是很常見(jiàn)的需求了,在項(xiàng)目中遇到的痛點(diǎn),難點(diǎn),如何一步步解決的,以及小細(xì)節(jié)一些優(yōu)化。

          借鑒某課的思路,仿QQ音樂(lè)效果,記錄一下,自己字母解決這個(gè)難題,分享給你們,「希望對(duì)你們做移動(dòng)端滾動(dòng)列表問(wèn)題有所幫助」


          GitHub倉(cāng)庫(kù)

          效果

          處理滾動(dòng)列表最終效果

          從最終效果來(lái)看,實(shí)現(xiàn)了三個(gè)我的難點(diǎn)

          • 第一個(gè)就是右側(cè)快速入口,點(diǎn)擊一個(gè)字母跳轉(zhuǎn)到相應(yīng)的部分
          • 左上角的那個(gè)title是跟隨字母一起修改內(nèi)容的
          • 向下滾動(dòng)的話,會(huì)隨時(shí)刷新右側(cè)快速路口以及左上角字母title

          接下來(lái)就是一步步去實(shí)現(xiàn),優(yōu)化上面的效果


          第三方庫(kù)介紹

          better-scroll 移動(dòng)端滾動(dòng)的解決方案

          vue-lazyload 圖片懶加載

          基本上實(shí)現(xiàn)上面的效果就是基于這兩個(gè)第三方庫(kù)

          「better-scroll基本使用」

          經(jīng)常會(huì)遇到的問(wèn)題就是初始化了,「還是不能滾動(dòng)」。那么對(duì)于這個(gè)而言,我最近用到一些經(jīng)驗(yàn)是什么呢?

          我們先看常見(jiàn)的html結(jié)果

          <div class="wrapper">
            <ul class="content">
              <li>...</li>
              <li>...</li>
              ...
            </ul>
            <!-- you can put some other DOMs here, it won't affect the scrolling
          </div>
          復(fù)制代碼

          滾動(dòng)的原理是什么

          better-scroll原理說(shuō)明

          wrapper是父容器,它一定要有「固定高度」,content是內(nèi)容區(qū)域,它是父元素的第一個(gè)元素,它c(diǎn)ontent會(huì)隨著內(nèi)容的大小撐開(kāi)而撐高,只有這個(gè)高度大于wrapper父容器高度時(shí),才會(huì)出現(xiàn)滾動(dòng),也就是它的原理。

          那么我們?cè)趺慈コ跏蓟?/p>

          import BScroll from '@better-scroll/core'
          let wrapper = document.querySelector('.wrapper')
          let scroll = new BScroll(wrapper,{})
          //{}配置一些信息
          復(fù)制代碼

          點(diǎn)這里有文檔

          接下來(lái)就開(kāi)始把


          從0到1完成

          scroll組件

          這個(gè)scroll組件是子組件,也可以算是個(gè)base組件,完成日常滾動(dòng)的效果

          <template>
            <div ref="wrapper">
              <slot></slot>
            </div>
          </template>
          
          <script type="text/ecmascript-6">
            import BScroll from 'better-scroll'
          
            export default {
              props: {
                probeType: {
                  type: Number,
                  default: 1
                },
                click: {
                  type: Boolean,
                  default: true
                },
                listenScroll: {
                  type: Boolean,
                  default: false
                },
                data: {
                  type: Array,
                  default: null
                },
                pullup: {
                  type: Boolean,
                  default: false
                },
                beforeScroll: {
                  type: Boolean,
                  default: false
                },
                refreshDelay: {
                  type: Number,
                  default: 20
                }
              },
              mounted() {
                setTimeout(() => {
                  this._initScroll()
                }, 20)
              },
              methods: {
                // 初始化Scroll
                _initScroll() {
                  // 判斷是否初始化
                  if (!this.$refs.wrapper) {
                    return
                  }
                  // 調(diào)用Scroll實(shí)例,表現(xiàn)可以滑動(dòng)
                  this.scroll = new BScroll(this.$refs.wrapper, {
                    probeType: this.probeType,
                    click: this.click
                  })
                  if (this.listenScroll) {
                    let me = this
                    this.scroll.on('scroll', (pos) => {
                      me.$emit('scroll', pos)
                    })
                  }
                  if (this.pullup) {
                    this.scroll.on('scrollEnd', () => {
                      if (this.scroll.y <= (this.scroll.maxScrollY + 50)) {
                        this.$emit('scrollToEnd')
                      }
                    })
                  }
                  if (this.beforeScroll) {
                    this.scroll.on('beforeScrollStart', () => {
                      this.$emit('beforeScroll')
                    })
                  }
                },
                disable() {
                  this.scroll && this.scroll.disable()
                },
                enable() {
                  this.scroll && this.scroll.enable()
                },
                refresh() {  // 刷新scroll,重新計(jì)算高度
                  this.scroll && this.scroll.refresh()
                },
                scrollTo() {
                  this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
                },
                scrollToElement() {
                  this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
                }
              },
              watch: {
                // 監(jiān)聽(tīng)到數(shù)據(jù)的變化,就會(huì)重新去refresh數(shù)據(jù),重新去計(jì)算響應(yīng)的數(shù)據(jù)
                data() {
                  setTimeout(() => {
                    this.refresh()
                  }, this.refreshDelay)
                }
              }
            }
          </script>
          <style scoped lang="stylus" rel="stylesheet/stylus">
          </style>
          復(fù)制代碼

          在父組件中導(dǎo)入即可

          完成列表滾動(dòng)

          listview組件導(dǎo)入

          <template>
            <scroll
              :listen-scroll="listenScroll"
              :probe-type="probeType"
              :data="data"
              class="listview"
              ref="listview"
            >
              <ul>
                <li v-for="(group,index) in data" class="list-group" ref="listGroup" :key="index">
                  <h2 class="list-group-title">{{group.title}}</h2>
                  <uL>
                    <li
                      @click="selectItem(item)"
                      v-for="(item, index) in group.items"
                      class="list-group-item"
                      :key="index"
                    >
                      <img class="avatar" v-lazy="item.avatar" />
                      <span class="name">{{item.name}}</span>
                    </li>
                  </uL>
                </li>
              </ul>
            </scroll>
          </template>
          復(fù)制代碼

          然后導(dǎo)入scroll組件即可,看看效果

          處理滾動(dòng)列表-實(shí)現(xiàn)列表滾動(dòng)

          上面在listview組件中導(dǎo)入scroll組件,完成基本的列表滾動(dòng)效果,接下來(lái),完善一步一步效果吧。

          右側(cè)快速入口

          <div
                class="list-shortcut"
                @touchstart="onShortcutTouchStart"
                @touchmove.stop.prevent="onShortcutTouchMove"
              >
              <!-- data-index方便獲取一個(gè)列表中的index -->
                <ul>
                  <li
                    v-for="(item, index) in shortcutList"
                    :data-index="index"
                    class="item"
                    :class="{'current':currentIndex===index}"
                    :key="index"
                  >{{item}}</li>
                </ul>
              </div>
          復(fù)制代碼

          點(diǎn)擊右側(cè)快速路口的話,會(huì)跳轉(zhuǎn)到相應(yīng)的title去,使用的方法就是

          scrollElement

          scrollToElement(el, time, offsetX, offsetY, easing)

          「這個(gè)方法很方便的解決了我們第一個(gè)難點(diǎn)」,現(xiàn)在就差獲取右側(cè)快速路口的索引值了

          給每一個(gè)li增加一個(gè)data-index屬性名稱(chēng),值為index下

          :data-index="index"
          復(fù)制代碼

          這樣子每次就可以獲取當(dāng)前的索引值

          有了索引值,我們就可以直接調(diào)用srcollToElement()方法,完成左側(cè)的跳轉(zhuǎn)效果。

          this.$refs.listview.scrollToElement(this.$refs.listGroup[index], 0);
          // 這個(gè)index就是獲取到下標(biāo)索引值,然后通過(guò)這個(gè)
          // 這個(gè)第二個(gè)參數(shù)是滾動(dòng)的動(dòng)畫(huà)的時(shí)間,我們默認(rèn)為0就行,文檔上面也有專(zhuān)門(mén)的說(shuō)明,可以去看看。
          復(fù)制代碼

          我們看看效果吧下

          處理滾動(dòng)列表-實(shí)現(xiàn)點(diǎn)擊右側(cè)跳轉(zhuǎn)相應(yīng)位置

          接下來(lái)完成「touchMove事件」,我們綁定到div上

          @touchmove.stop.prevent="onShortcutTouchMove"
          // 兩個(gè)修飾符阻止冒泡以及默認(rèn)的事件
          復(fù)制代碼

          思路

          • 首先要監(jiān)聽(tīng)touchStart事件一開(kāi)始錨點(diǎn),也就是anchorIndex,還有保存e.touches[0].pageY, y軸上的位置信息,記作y1
          • 監(jiān)聽(tīng)touchuMove事件,保存y軸距離,記為y2,這個(gè)時(shí)候y2-y1就是y軸上的距離變化dataChange
          • 將這個(gè)距離dataChange除以高度,這里的高度,我選擇的是每個(gè)li的content+padding高度,這個(gè)高度的話,正好是整個(gè)一個(gè)li元素高度,我覺(jué)得很合理,delta = dataChange/ANCHOR_HEIGHT
          • 最后一開(kāi)始的anchorIndex加上delta,就是最新的錨點(diǎn),這個(gè)anchorIndex一定要取證,因?yàn)楂@取的可能是字符串。

          看代碼

           onShortcutTouchStart(e) {
                  // 獲取到右側(cè)的列表索引值
                let anchorIndex = getData(e.target, "index");
                let firstTouch = e.touches[0];
                this.touch.y1 = firstTouch.pageY;   // 計(jì)入一開(kāi)始y軸上的位置
                this.touch.anchorIndex = anchorIndex;   // 保存了每次點(diǎn)擊的錨點(diǎn)
                this._scrollTo(anchorIndex);
              },
              // 監(jiān)聽(tīng)的是TouchMove事件
              onShortcutTouchMove(e) {
                let firstTouch = e.touches[0];
                this.touch.y2 = firstTouch.pageY;
                // 滾動(dòng)的兩個(gè)差值 也就是y軸上的偏移
                // 除以每個(gè)高度,這樣子的話,就知道偏移了幾個(gè)錨點(diǎn)
                let delta = ((this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT) | 0;
                let anchorIndex = parseInt(this.touch.anchorIndex) + delta;
          
                this._scrollTo(anchorIndex);
              },
              
          復(fù)制代碼

          效果怎么樣呢,基本上點(diǎn)擊和手勢(shì)移動(dòng)都較為完美的實(shí)現(xiàn)了。

          處理滾動(dòng)列表-實(shí)現(xiàn)手勢(shì)移動(dòng)右側(cè)跳轉(zhuǎn)相應(yīng)位置

          左右聯(lián)動(dòng)

          左右聯(lián)動(dòng)的效果指的是左側(cè)點(diǎn)擊到某個(gè)區(qū)域,緊接著右側(cè)快速路口也跳轉(zhuǎn)到相應(yīng)位置,這里其實(shí)指的就是高亮效果。

          效果就是滑動(dòng)列表,右側(cè)的字母會(huì)相應(yīng)的高亮,達(dá)到同步的作用,難點(diǎn)是什么呢?

          ListGroup計(jì)算高度

          從圖片上面看,我們發(fā)現(xiàn)每個(gè)listGroup分組里面的成員是不固定的,所以我們?cè)趺慈カ@取到相應(yīng)的currentIndex呢?

          「我們可以獲取到每次滾動(dòng)的距離,那怎么樣去獲取相應(yīng)的currentIndex呢,比如滑到K分組時(shí),currentIndex是對(duì)應(yīng)的下標(biāo)?」

          有個(gè)不錯(cuò)的思路:

          • 我們?nèi)ゾS護(hù)一個(gè)height[i]數(shù)組,該數(shù)組含義就是第i個(gè)分組的范圍是height[i]~~heigth[i+1]
          • 那么我們獲取到滾動(dòng)Y軸的距離,那么就可以確定它所在的范圍,如果滾動(dòng)的距離在posY>height[i]&&posY<height[i+1],那么currentIndex就可以取值i,這樣子好像行。

          那么我們按照上面的思路來(lái)完善吧

           _calculateHeight() {
                // 這個(gè)方法就是計(jì)算每個(gè)listGroup高度
                this.listHeight = [];
                const list = this.$refs.listGroup;
                let height = 0;
                this.listHeight.push(height);
                for (let i = 0; i < list.length; i++) {
                  let item = list[i];
                  height += item.clientHeight;
                  this.listHeight.push(height);
                }
              },
          復(fù)制代碼

          這個(gè)listHeigth數(shù)據(jù)就是我們維護(hù)的第i個(gè)分組的clientHeight距離

          第二步,我們監(jiān)控這個(gè)scrollY,這個(gè)變量表示的就是滾動(dòng)的距離

          watch: {
              // 每次去watch這個(gè)滾動(dòng)的距離,
              scrollY(newY) {
                const listHeight = this.listHeight;
                // 當(dāng)滾動(dòng)到頂部,newY>0
                if (newY > 0) {
                  this.currentIndex = 0;
                  return;
                }
                // 在中間部分滾動(dòng)
                for (let i = 0; i < listHeight.length - 1; i++) {
                  let height1 = listHeight[i];
                  let height2 = listHeight[i + 1];
                  if (-newY >= height1 && -newY < height2) {
                    this.currentIndex = i;
                    this.diff = height2 + newY;
                    return;
                  }
                }
                // 當(dāng)滾動(dòng)到底部,且-newY大于最后一個(gè)元素的上限
                this.currentIndex = listHeight.length - 2;
              },
          復(fù)制代碼

          這里需要提醒的就是,我們?cè)趺慈ツ玫竭@個(gè)scrollY滾動(dòng)距離呢?

          說(shuō)到這個(gè),我們得看到scroll組件中,閱讀它的API,會(huì)發(fā)現(xiàn)它提供了on方法,該方法可以去監(jiān)聽(tīng)該「實(shí)例的鉤子函數(shù)」,所以我們?nèi)?strong>「監(jiān)聽(tīng)鉤子函數(shù)scroll」

          「scroll鉤子函數(shù)」

          • 參數(shù):{Object} {x, y} 滾動(dòng)的實(shí)時(shí)坐標(biāo)
          • 觸發(fā)時(shí)機(jī):滾動(dòng)過(guò)程中。

          所以我們可以通過(guò)這個(gè)鉤子來(lái)獲取滾動(dòng)的實(shí)時(shí)坐標(biāo)

          if (this.listenScroll) {
                    let me = this
                    this.scroll.on('scroll', (pos) => {
                      // me指的就是實(shí)例
                      // 通過(guò)監(jiān)聽(tīng)scroll事件,有一個(gè)回調(diào),pos是一個(gè)對(duì)象,有x,y軸的具體距離
                      // 去派發(fā)一個(gè)scroll事件,這樣子外部也就是父組件可以拿到我們的pos
                      me.$emit('scroll', pos)
                    })
                  }
          復(fù)制代碼

          這樣子我們?cè)谧咏M件scroll中向外派發(fā)一個(gè)scroll事件,并且把「pos = {Object} {x, y} 滾動(dòng)的實(shí)時(shí)坐標(biāo)」向外傳遞,這樣子的話,父組件通過(guò)@scroll="scroll" 就可以拿到這個(gè)坐標(biāo)pos

          這樣子我們這個(gè)難點(diǎn)就解決了。

          我們來(lái)看看效果

          這樣子基本上問(wèn)題就解決了,但是呢還會(huì)遇到一個(gè)問(wèn)題?


          probeType

          • 類(lèi)型:Number
          • 默認(rèn)值:0
          • 可選值:1、2、3
          • 作用:有時(shí)候我們需要知道滾動(dòng)的位置。當(dāng) probeType 為 1 的時(shí)候,會(huì)非實(shí)時(shí)(屏幕滑動(dòng)超過(guò)一定時(shí)間后)派發(fā)scroll 事件;當(dāng) probeType 為 2 的時(shí)候,會(huì)在屏幕滑動(dòng)的過(guò)程中實(shí)時(shí)的派發(fā) scroll 事件;當(dāng) probeType 為 3 的時(shí)候,不僅在屏幕滑動(dòng)的過(guò)程中,而且在 momentum 滾動(dòng)動(dòng)畫(huà)運(yùn)行過(guò)程中實(shí)時(shí)派發(fā) scroll 事件。如果沒(méi)有設(shè)置該值,其默認(rèn)值為 0,即不派發(fā) scroll 事件。

          這個(gè)是文檔上面的內(nèi)容,我們可以看到這個(gè)配置項(xiàng)還是很重要的,我們listview組件需要通過(guò)props向子組件傳遞probeType值,值為3,這樣子就可以「在滾動(dòng)中實(shí)時(shí)派發(fā) scroll 事件」

           <scroll :probe-type='3'></scroll>
           // 當(dāng)然了,這個(gè)probeTyep會(huì)在data中拿到
          復(fù)制代碼

          總結(jié)

          • 解決難點(diǎn)一,獲取滾動(dòng)的實(shí)時(shí)位置,通過(guò)子組件scroll實(shí)例on方法,去「監(jiān)聽(tīng)鉤子函數(shù)scroll」,然后向外去派發(fā)一個(gè)scroll函數(shù),并且把滾動(dòng)的距離傳給父組件listview
          • 解決難點(diǎn)二,獲取到滾動(dòng)Y軸的距離,就可以進(jìn)一步去判斷,它是落在哪一個(gè)listGroup中,也就是哪一個(gè)分組中,這樣子就確定currentIndex。
          • 通過(guò)watch監(jiān)聽(tīng)scrollY值,表示Y軸滾動(dòng)距離,發(fā)生變化時(shí),更新currentIndex。
          • 有了currentIndex,在判斷currentIndex === index,就可以實(shí)現(xiàn)高亮效果
          • 還有一些BetterScroll 提供的API 比如refresh(),重新計(jì)算 BetterScroll,當(dāng) DOM 結(jié)構(gòu)發(fā)生變化的時(shí)候務(wù)必要調(diào)用確保滾動(dòng)的效果正常scrollToElement(el, time, offsetX, offsetY, easing) 滾動(dòng)到指定的目標(biāo)元素on(type, fn, context) 監(jiān)聽(tīng)當(dāng)前實(shí)例上的鉤子函數(shù)。如:scroll、scrollEnd 等
          • 還有一個(gè)收獲就是用第三方API,「有問(wèn)題一定要查文檔」

          咱給小編:

          1. 點(diǎn)贊+評(píng)論

          2. 點(diǎn)頭像關(guān)注,轉(zhuǎn)發(fā)給有需要的朋友。

          您的支持是小編不斷輸出的動(dòng)力,謝謝!!

          CSS 和 JS 的原生平滑滾動(dòng)

          你想要一個(gè)平滑的滾動(dòng)嗎? 忘記 JQuery,我們已經(jīng)過(guò)去了。 讓我向您介紹我們的原生平滑滾動(dòng)工具。


          CSS 滾動(dòng)行為

          CSS scroll-behavior 屬性接受三個(gè)值之一 - 實(shí)際上是兩個(gè)值,因?yàn)槠渲幸粋€(gè)已被棄用。

          1. scroll-behavior: auto 是我們已經(jīng)習(xí)慣的默認(rèn)即時(shí)滾動(dòng)行為。
          2. scroll-behavior:instant 與 auto 相同,這就是它被棄用的原因。 如果你想要它,只需使用自動(dòng)。
          3. scroll-behavior: smooth 在以編程方式觸發(fā)滾動(dòng)事件時(shí)應(yīng)用平滑過(guò)渡。

          我說(shuō)“以編程方式觸發(fā)”是因?yàn)樗粫?huì)平滑滾動(dòng)鼠標(biāo)滾輪。

          以編程方式觸發(fā)滾動(dòng)事件的一些方法是:

          -    Window.scrollTo()
          -    Window.scrollBy()
          -    Element.scrollTo()
          -    Element.scrollBy()
          -    Element.scrollIntoView()
          -    Element.scrollLeft = x
          -    Element.scrollTop = y

          我們將分別探索這些方法。


          (注)Window.scroll() 和 Element.scroll()

          也許你已經(jīng)注意到我沒(méi)有提到 scroll() 方法。

          這是因?yàn)?Window.scroll() 和 Element.scroll() 實(shí)際上是與 Window.scrollTo() 和 Element.scrollTo() 相同的方法。為避免重復(fù)內(nèi)容,我將僅參考 scrollTo()。在實(shí)踐中,您可以使用任何一種,只需選擇一個(gè)并保持一致。


          Window.scrollTo() 和 Element.scrollTo()

          此方法非常適合滾動(dòng)到絕對(duì)坐標(biāo)。如果您有要將用戶(hù)滾動(dòng)到的位置的 x 和 y 坐標(biāo),您可以簡(jiǎn)單地調(diào)用 window.scrollTo(x, y) ,它會(huì)尊重頁(yè)面的 CSS 滾動(dòng)行為。

          這同樣適用于可滾動(dòng)元素。您只需調(diào)用 element.scrollTo(x, y) ,它就會(huì)尊重元素的 CSS 滾動(dòng)行為。

          這個(gè)方法還有一個(gè)新的簽名,它使用一個(gè)對(duì)象而不是兩個(gè)數(shù)字參數(shù),通過(guò)這個(gè)新的簽名,我們可以顯式地設(shè)置我們的滾動(dòng)行為。

          // For window
          window.scrollTo({
            left: x,
            top: y,
            behavior: 'smooth'
          });
          // For element
          const el = document.querySelector(...);
          el.scrollTo({
            left: x,
            top: y,
            behavior: 'smooth'
          });


          Element.scrollLeft 和 Element.scrollTop

          設(shè)置元素 .scrollLeft 和 .scrollTop 屬性與使用坐標(biāo)調(diào)用 Element.scrollTo() 相同。 它將尊重元素的 CSS 滾動(dòng)行為。

          const el = document.querySelector(...);
          const x = 100;
          const y = 500;
          // Setting .scrollLeft and .scrollTop with smooth scroll
          el.style.scrollBehavior = 'smooth';
          el.scrollLeft = x;
          el.scrollTop = y;
          // Is the same as calling Element.scrollTo()
          el.scrollTo({ left: x, top: y, behavior: 'smooth' });


          (注)負(fù)元素.scrollLeft

          如果你的元素文本的方向是 rtl,scrollLeft = 0 表示水平滾動(dòng)的最右邊位置,并且隨著你向左移動(dòng),值會(huì)減小。

          對(duì)于寬度為 100px,可滾動(dòng)寬度為 500px,方向?yàn)?rtl 的可滾動(dòng)元素,最左邊的位置是 scrollLeft = -400。

          <div id="scrollable" style="width: 100px; overflow: auto" dir="rtl">
            <div style="width: 500px; height: 100px; background: green"></div>
          </div>
          <p id="output"></p>
          const scrollable = document.querySelector('#scrollable');
          const output = document.querySelector('#output');
          const updateOutput = () => {
            output.textContent = `scrollLeft: ${scrollable.scrollLeft}`;
          };
          updateOutput();
          scrollable.addEventListener('scroll', updateOutput);


          Window.scrollBy() 和 Element.scrollBy()

          此方法與 Window.scrollTo() 或 Element.scrollTo() 具有完全相同的簽名。 它接受 x 和 y 作為兩個(gè)數(shù)字參數(shù)或作為具有可選 left、top 和 behavior 屬性的對(duì)象的單個(gè)參數(shù)。

          這里的區(qū)別是我們不是傳遞絕對(duì)坐標(biāo),而是相對(duì)值。 如果我們 scrollBy({ top: 10 }),我們從當(dāng)前位置向下滾動(dòng) 10 個(gè)像素,而不是從頁(yè)面開(kāi)頭向下滾動(dòng) 10 個(gè)像素。

          // For window
          window.scrollBy({ top: 10 }); // Scroll 10px down
          window.scrollBy({ left: 20 }); // Then 20px to the right
          window.scrollBy({ top: 50 }); // And then 50px down
          // For element
          const el = document.querySelector(...);
          el.scrollBy({ top: 10 }); // Scroll 10px down
          el.scrollBy({ left: 20 }); // Then 20px to the right
          el.scrollBy({ top: 50 }); // And then 50px down


          (注) Window.scrollByLines() 和 Window.scrollByPages()

          Firefox 更進(jìn)一步,實(shí)現(xiàn)了滾動(dòng)多行或多頁(yè)的方法。 這是一個(gè)僅適用于 Firefox 的非標(biāo)準(zhǔn)功能,因此您可能不想在生產(chǎn)中使用它。

          通過(guò)將 100vh(用于頁(yè)面)和 1rem(用于行)轉(zhuǎn)換為像素并將該值傳遞給 Window.scrollBy(),您可以在所有主要瀏覽器中實(shí)現(xiàn)類(lèi)似的效果。

          const toPixels = require('to-px'); // From NPM
          const page = toPixels('100vh');
          window.scrollBy(0, page); // window.scrolByPages(1)
          const line = toPixels('1rem');
          window.scrollBy(0, line); // window.scrolByLines(1)


          Element.scrollIntoView()

          但大多數(shù)時(shí)候,我們并不關(guān)心任何硬編碼的坐標(biāo),我們只想將用戶(hù)滾動(dòng)到屏幕上的特定元素。 這可以通過(guò) Element.scrollIntoView() 輕松(更明確地)完成。

          可以不帶參數(shù)調(diào)用此方法,它將滾動(dòng)頁(yè)面(尊重 CSS 滾動(dòng)行為)直到元素在頂部對(duì)齊(除非元素在頁(yè)面底部,在這種情況下,它會(huì) 盡可能滾動(dòng))。

          <div style="height: 2000px">Some space</div>
          <div id="target" style="background: green">Our element</div>
          <div style="height: 500px">More space</div>
          const target = document.querySelector('#target');
          target.scrollIntoView();

          您可以通過(guò)傳遞布爾值或?qū)ο髞?lái)進(jìn)一步自定義元素在視圖中的位置。

          const el = document.querySelector(...);
          // Default, aligns at the top
          el.scrollIntoView(true);
          // Aligns at the bottom
          el.scrollIntoView(false);
          // Aligns vertically at the center
          el.scrollIntoView({ block: 'center' });
          // Vertical top and horizontal center
          el.scrollIntoView({ block: 'start', inline: 'center' });
          // Vertical bottom and horizontal right
          el.scrollIntoView({ block: 'end', inline: 'end' });
          // Vertical center and smooth
          el.scrollIntoView({ block: 'center', behavior: 'smooth' });
          // Vertical nearest
          el.scrollIntoView({ block: 'nearest' });

          當(dāng)使用一個(gè)對(duì)象來(lái)定義元素的位置時(shí),注意 block 是指垂直放置,而 inline 是指水平放置。此外,“最近”的位置可以是頂部/左側(cè)或底部/右側(cè),以最近的為準(zhǔn),如果元素已經(jīng)在視圖中,它也可以是空的。


          瀏覽器支持

          {關(guān)于瀏覽器支持} 在撰寫(xiě)本文時(shí),所有主流瀏覽器(Safari 除外)都支持平滑滾動(dòng)和本文中描述的滾動(dòng)方法。

          如果你需要更多的保證,我在我的項(xiàng)目中使用了一個(gè)非常好的平滑滾動(dòng) polyfill。它填充了 scroll()、scrollTo()、scrollBy()、scrollIntoView() 和 CSS 滾動(dòng)行為。它不支持通過(guò)設(shè)置 scrollLeft/scrollTop 來(lái)平滑滾動(dòng),也不支持 scrollIntoView() 選項(xiàng)(它總是在頂部對(duì)齊元素)。

          如果你有更多的好奇心,我強(qiáng)烈建議你研究一下 polyfill 的源代碼,總共不到 500 行。我做了一個(gè) PR 來(lái)稍微改進(jìn)文檔,你可能會(huì)發(fā)現(xiàn)代碼更容易理解。


          祝你有美好的一天,很快見(jiàn)到你。

          extarea內(nèi)容某個(gè)高度之內(nèi)自適應(yīng),超過(guò)時(shí)候指定高度固定然后出現(xiàn)滾動(dòng)條!

          效果如下:當(dāng)你輸入超過(guò)設(shè)置的高度后,就會(huì)固定此高度不變。


          主站蜘蛛池模板: 亚洲色偷偷偷网站色偷一区| 中文字幕日本一区| 无码精品不卡一区二区三区| 国产一区二区三区美女| 亚洲毛片αv无线播放一区| 日韩AV片无码一区二区不卡 | 人妻少妇精品视频三区二区一区| 一区二区三区中文字幕| 亚洲国产AV一区二区三区四区| 亚洲国产成人一区二区三区| 一区二区三区免费高清视频| 国产精品成人免费一区二区| 精品日韩亚洲AV无码一区二区三区| 中文字幕在线视频一区| 无码人妻精品一区二区蜜桃AV| 日韩成人一区ftp在线播放| 国产日韩一区二区三区在线播放| 色窝窝无码一区二区三区成人网站| 无码av不卡一区二区三区| 国产成人精品一区二区A片带套 | 久久国产午夜精品一区二区三区 | 综合久久一区二区三区| AV无码精品一区二区三区宅噜噜| 一级毛片完整版免费播放一区| 国产乱码精品一区二区三区四川| 日本精品视频一区二区| 国产主播一区二区三区| 精品女同一区二区三区在线| 狠狠做深爱婷婷综合一区 | 中文字幕亚洲一区| 国产一区二区视频在线观看| 国产精品亚洲产品一区二区三区 | 亚洲av乱码一区二区三区香蕉| 久久综合精品不卡一区二区| 2020天堂中文字幕一区在线观| 蜜臀AV免费一区二区三区| 亚洲欧美日韩中文字幕在线一区| 亚洲av综合av一区二区三区| 色窝窝免费一区二区三区| 成人精品一区久久久久| 国产精品自在拍一区二区不卡|