国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 21:53:44
文檔

實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法

實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法:前言 近期產(chǎn)品小哥哥給我提了一個新需求,在一個頁面的滾動區(qū)中添加一組錨點(diǎn)定位按鈕,點(diǎn)擊按鈕將對應(yīng)的元素顯示在頁面的可視區(qū)中。當(dāng)按鈕組超出頁面可視區(qū)的時候?qū)⑵涔潭ㄔ跐L動區(qū)域的頭部,當(dāng)滾動區(qū)滾動時,高亮距離滾動區(qū)頂部最近的元素所匹配的錨點(diǎn)按鈕。
推薦度:
導(dǎo)讀實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法:前言 近期產(chǎn)品小哥哥給我提了一個新需求,在一個頁面的滾動區(qū)中添加一組錨點(diǎn)定位按鈕,點(diǎn)擊按鈕將對應(yīng)的元素顯示在頁面的可視區(qū)中。當(dāng)按鈕組超出頁面可視區(qū)的時候?qū)⑵涔潭ㄔ跐L動區(qū)域的頭部,當(dāng)滾動區(qū)滾動時,高亮距離滾動區(qū)頂部最近的元素所匹配的錨點(diǎn)按鈕。

前言

近期產(chǎn)品小哥哥給我提了一個新需求,在一個頁面的滾動區(qū)中添加一組錨點(diǎn)定位按鈕,點(diǎn)擊按鈕將對應(yīng)的元素顯示在頁面的可視區(qū)中。當(dāng)按鈕組超出頁面可視區(qū)的時候?qū)⑵涔潭ㄔ跐L動區(qū)域的頭部,當(dāng)滾動區(qū)滾動時,高亮距離滾動區(qū)頂部最近的元素所匹配的錨點(diǎn)按鈕。

拆分功能點(diǎn)

現(xiàn)在我們已經(jīng)明確需求了,接下來我們總結(jié)一下這個需求有哪些功能點(diǎn):

  • 按鈕組要有吸頂效果
  • 點(diǎn)擊按鈕要有錨點(diǎn)定位功能
  • 滾動內(nèi)容區(qū)需要找到對應(yīng)的按鈕并高亮
  • 吸頂組件

    要做一個吸頂效果最簡單的方式是將 css 的 position 屬性設(shè)置為 sticky, 這樣就實(shí)現(xiàn)粘性布局。

    .sticky-container {
     position: sticky;
     top: 0px;
    }

    上面的示例僅僅用了兩行 css 的代碼就實(shí)現(xiàn)了粘性布局,但由于 IE 瀏覽器完全不支持粘性布局,而我的項(xiàng)目又需要支持一部分的 IE 瀏覽器,所以就需要手動去實(shí)現(xiàn)這樣一個功能。

    MDN 官方對粘性布局的解釋是這樣的,粘性布局元素默認(rèn)是相對定位的,當(dāng)粘性元素超出父元素的指定值(如 `top` 、`left` 等),例如上面的示例,當(dāng)元素粘性元素改為固定定位。關(guān)于父級元素 MDN 描述的不是很精確,這里的父級元素指的是父級滾動元素,如果沒有父級滾動元素則將 `body` 元素作為父級元素。

    既然需要自己實(shí)現(xiàn)一個吸頂?shù)男Ч伎嫉狡渌撁婵赡芤矔褂玫奈數(shù)墓δ埽詻Q定將其單獨(dú)抽離成一個通用組件。首先我們知道粘性布局是對父級滾動元素定位,所以我們要先找到父級滾動元素,這個功能我們可以通過兩種方式實(shí)現(xiàn),一種是向上查找,一種是通過 props 傳遞一個唯一標(biāo)識的 css 選擇器。

    我覺得其他項(xiàng)目可能也會遇到這個功能,所以我定義組件 盡量向著開源靠攏,所以我這里同時支持兩種方案。首先我們要實(shí)現(xiàn)一個查找父級滾動元素的功能,如何判斷一個元素是滾動元素呢?很簡單判斷其 `overflow` 是否是 `auto` 或者 `scroll`。

    // util.js 文件
    // 判斷一個元素是否是滾動元素
    const scrollList = ['auto', 'scroll']
    
    export function hasScrollElement(el, direction = 'vertical') {
     if (!el) return
     const style = window.getComputedStyle(el)
     if (direction === 'vertical') {
     return scrollList.includes(style.overflowY)
     } else if (direction === 'horizontal') {
     return scrollList.includes(style.overflowX)
     }
    }
    
    // 獲取第一個滾動元素
    export function getFirstScrollElement(el, direction = 'vertical') {
     if (!el) return
     if (hasScrollElement(el, direction)) {
     return el
     } else {
     return getFirstScrollElement(el && el.parentElement, direction)
     }
    }

    這里說下實(shí)現(xiàn)吸頂效果所需要的一些基礎(chǔ)知識:

  • fixed 定位是相對于瀏覽器的可視區(qū)進(jìn)行定位,這意味著即使頁面滾動,它還是會固定在相同的位置
  • offsetTop 是一個只讀的屬性,它返回當(dāng)前元素相對于距離它最近的父級定位元素頂部的距離。
  • scrollTop 屬性可以獲取或設(shè)置一個元素的內(nèi)容垂直滾動的像素值,`scrollTop` 表示這個元素達(dá)到父級滾動元素頂部的距離。
  • <template>
     <div class="cpt-sticky" :class="fixedClass" :style="{ top: top + 'px', zIndex }">
     <slot></slot>
     </div>
    </template>
    
    <script>
    export default {
     props: {
     top: Number,
     parent: String,
     zIndex: Number
     },
    
     data() {
     return {
     fixedClass: '',
     scrollElement: null
     }
     },
    
     mounted() {
     this.initScrollElement()
     },
    
     destroyed() {
     this.removeScrollEvent()
     },
    
     methods: {
     handleScroll() {
     const scrollOffsetTop = this.$el.offsetTop - this.top
     if (this.scrollElement.scrollTop >= scrollOffsetTop) {
     this.fixedClass = 'top-fixed'
     } else {
     this.fixedClass = ''
     }
     },
    
     initScrollElement() {
     const element = document.querySelector(this.parent)
     if (element) {
     this.removeScrollEvent()
     this.scrollElement = element
     this.scrollElement.addEventListener('scroll', this.handleScroll)
     }
     },
    
     removeScrollEvent() {
     if (this.scrollElement) {
     this.scrollElement.removeEventListener('scroll', this.handleScroll)
     }
     }
     }
    }
    </script>
    
    <style lang="scss">
    .cpt-sticky {
     .top-fixed {
     position: fixed;
     width: 100%;
     background: #fff;
     }
    }
    </style>

    就像上面的示例代碼一樣,短短幾十行就實(shí)現(xiàn)了一個吸頂組件,不過它實(shí)現(xiàn)了吸頂?shù)墓δ埽沁€有一些缺陷。

    1. 在慢速滾動頁面,吸頂組件在固定與非固定的時候有明顯的卡頓現(xiàn)象。
    2. 由于我的需求有一些是需要做錨點(diǎn)定位功能,但是直接用錨點(diǎn)定位會改變路由所以改為了滾動定位(后面會細(xì)說)。但是由于吸頂組件在 `fixed` 之后會脫離文檔流,導(dǎo)致定位的元素會有一部分(吸頂組件高度 )被卡在吸頂組件下方。就像下面這張圖的效果,右邊的錨點(diǎn)定位2區(qū)域的標(biāo)題被隱藏了。

    這些問題也很好解決,使用一個和吸頂組件相同大小的占位元素,當(dāng)吸頂組件脫離文檔流之后,占位元素插入吸頂組件原來的 DOM 位置中,然后順便帶上一些小優(yōu)化。由于占位元素需要和組件高度一致,所以必須要保證 `slot` 插槽中的 DOM 元素已經(jīng)被加載完成,另外放在 slot 元素中可能發(fā)生變更,所以我在吸頂狀態(tài)變更之前獲取其高度。

    <template>
     <div class="cpt-sticky">
     <div class="sticky-container" :class="fixedClass" :style="{ top: top + 'px', zIndex }">
     <slot></slot>
     </div>
     <div v-if="showPlaceholder" class="sticky-placeholder" :style="{ height: offsetHeight + 'px' }"></div>
     </div>
    </template>
    
    <script>
    import { getFirstScrollElement } from 'util.js'
    
    export default {
     props: {
     top: {
     type: Number,
     default: 0
     },
     zIndex: {
     type: Number,
     default: 0
     },
     parent: {
     type: String,
     default: ''
     }
     },
    
     data() {
     return {
     isMounted: false,
     fixedClass: '',
     offsetHeight: 0,
     scrollElement: null,
     showPlaceholder: false
     }
     },
    
     mounted() {
     this.isMounted = true
     this.initScrollElement()
     },
    
     watch: {
     parent: {
     immediate: true,
     handler: 'getScrollElement'
     },
    
     fixedClass(v) {
     if (v && !this.offsetHeight) {
     this.offsetHeight = this.$el.offsetHeight
     }
     this.showPlaceholder = !!v
     }
     },
    
     destroyed() {
     this.removeScrollEvent()
     },
    
     methods: {
     handleScroll(e) {
     const scrollOffsetTop = this.$el.offsetTop - this.top
     if (this.scrollElement.scrollTop >= scrollOffsetTop) {
     this.fixedClass = 'top-fixed'
     } else {
     this.fixedClass = ''
     }
     },
    
     initScrollElement() {
     if (!this.isMounted) return
     const parent = this.parent
     let element = null
     if (parent) {
     element = document.querySelector(parent)
     if (element === this.scrollElement) return
     } else if (this.$el) {
     element = getFirstScrollElement(this.$el)
     }
     if (element) {
     this.removeScrollEvent()
     this.scrollElement = element
     this.scrollElement.addEventListener('scroll', this.handleScroll)
     }
     },
    
     removeScrollEvent() {
     if (this.scrollElement) {
     this.scrollElement.removeEventListener('scroll', this.handleScroll)
     }
     }
     }
    }
    </script>
    
    <style lang="scss">
    .cpt-sticky {
     .top-fixed {
     position: fixed;
     width: 100%;
     background: #fff;
     }
    }
    </style>

    錨點(diǎn)定位

    網(wǎng)頁中經(jīng)常會有用到錨點(diǎn)定位的場景,例如百度知道的目錄,我目前知道有三種方式可以實(shí)現(xiàn)這種功能。

    1. 使用 a 標(biāo)簽定位
    2. 使用 js 定位

    使用 a 標(biāo)簽定位

    先說說 a 標(biāo)簽定位,這是一種最常用的定位方式。它有兩種實(shí)現(xiàn)方式,一種是通過 herf 屬性鏈接的指定元素的 id。另一種是添加一個 a 標(biāo)簽,再將 href 屬性鏈接到這個 a 標(biāo)簽的 name 屬性。

    <a href="#view1">按鈕1</a>
    <a href="#view2">按鈕1</a>
    ...
    <div id="view1">視圖1</div>
    <div><a name="view2">視圖2</a></div>

    這種定位方式很簡單,它支持任意標(biāo)簽定位。不過它也存在一些問題,例如如果滾動區(qū)內(nèi)有固定或絕對定位,會出現(xiàn)遮罩問題,還有瞬間滾動到頂部,交互不是很好,當(dāng)然這些都可以通過 css 解決。但最主要問題是,a 標(biāo)簽定位會改變路由的 hash,如果有相應(yīng)的路由的話會進(jìn)行路由跳轉(zhuǎn)。

    通過 js 模擬錨點(diǎn)定位

    通過 js 去操作元素的 `scrollTop` 等屬性,使其滾動到父級滾動元素指定的位置,就能實(shí)現(xiàn)定位效果。這里簡單提一下 `scrollIntoView()` 這個方法,根據(jù)MDN 的描述,`Element.scrollIntoView()` 方法讓當(dāng)前的元素滾動到瀏覽器窗口的可視區(qū)域內(nèi)。`scrollIntoView()` 還支持動畫的選項(xiàng),通過 `behavior` 設(shè)置,不過遺憾的是它遇到固定定位也會出現(xiàn)遮蓋的問題,所以最終選擇手動去擼碼,不過 `scrollIntoView()` 倒是很適合做回到頂部這種功能。

    首先我們需要讓按鈕和滾動區(qū)內(nèi)容元素建立對應(yīng)關(guān)系,在按鈕的值中放入對應(yīng)的內(nèi)容區(qū)元素的 css 選擇器,根據(jù)點(diǎn)擊按鈕的值找到對應(yīng)的元素。所以計(jì)算規(guī)則是這個元素距離滾動區(qū)的高度加上這個元素上邊距的高度(我在內(nèi)容區(qū)加了外邊距,我希望顯示它),減去滾動區(qū)距離可視區(qū)的高度(我的頁面沒有定位,所以 offsetTop 對應(yīng)可視區(qū)),再減去按鈕組件的高度,就可以得出需要滾動的位置。

    <template>
     <div class="cpt-anchor">
     <el-radio-group
     v-model="selector"
     size="mini"
     @change="handleMenuChange">
     <el-radio-button
     v-for="menu in menus"
     :key="menu.value"
     :label="menu.value">
     {{ menu.label }}
     </el-radio-button>
     </el-radio-group>
     </div>
    </template>
    
    <script>
    // 添加緩動函數(shù)
    import { tween } from 'shifty'
    // 類似 lodash.get 但處理了 null 類型
    import { get as _get } from 'noshjs'
    import { getFirstScrollElement } from 'util.js'
    
    export default {
     props: {
     // 滾動區(qū)距離可視區(qū)頂部的高度
     top: {
     type: Number,
     default: 0
     },
     menus: {
     type: Array,
     default: []
     }
     },
    
     data() {
     return {
     selector: ''
     }
     },
    
     watch: {
     menus: {
     immediate: true,
     handler(list) {
     this.selector = _get(list, [0, 'value'], '')
     }
     }
     },
    
     methods: {
     handleMenuChange(selector) {
     const scrollElement = document.querySelector(select)
     const rootScrollElement = getFirstScrollElement(scrollElement)
     if (scrollElement && rootScrollElement) {
     const offsetTop = scrollElement.offsetTop + scrollElement.clientTop
     const offsetHeight = _get(this.$el, ['parentElement', 'offsetHeight'], 0)
     const top = offsetTop - this.top - offsetHeight
    
     // 做一個緩動處理
     tween({
     from: { x: rootScrollElement.scrollTop },
     to: { x: top },
     duration: 500,
     easing: 'easeOutQuint',
     step: ({ x }) => {
     rootScrollElement.scrollTop = x
     }
     }).then(({ x }) => {
     rootScrollElement.scrollTop = x
     })
     }
     }
     }
    }
    </script>

    錨點(diǎn)與視圖聯(lián)動

    接下來我們來看看最后一個功能,當(dāng)用戶滾動內(nèi)容區(qū)時,高亮距離按鈕組件最近的那個元素所對應(yīng)的按鈕。這個功能我可以看成是目錄導(dǎo)航,當(dāng)我們查看不同內(nèi)容時高亮對應(yīng)的目錄。

    這個功能如何實(shí)現(xiàn)呢,我們來分析一下,當(dāng)查看不同內(nèi)容時會滾動屏幕,所以我們要給按鈕的父級滾動元素綁定 `scroll` 事件。判斷當(dāng)前滾動區(qū)距離按鈕最近的元素,我們需要在這個元素上添加與按鈕中的值對應(yīng)的 css 選擇器。當(dāng)內(nèi)容區(qū)發(fā)生滾動時根據(jù)按鈕獲取內(nèi)容區(qū)中所有的元素,然后將滾動區(qū)元素的 `scrollTop` 減去按鈕元素的高度,即得出按鈕下方的滾動高度,然后再遍歷這些元素頭部和尾部是否包含了這個滾動高度,然后找到這個元素對應(yīng)的按鈕。

    上面的結(jié)論已經(jīng)可以完成,但存在一些問題,先說第一個問題導(dǎo)致按鈕導(dǎo)航失效,只導(dǎo)航到下一個按鈕邊結(jié)束。這個問題不一定會所有人都遇到,之所以我會遇到這個問題,是因?yàn)槲矣昧?`Element` 的 `Radio` 組件,要高亮的時候變更了 v-model 的值導(dǎo)致。而點(diǎn)擊按鈕時會觸發(fā)滾動,就會和聯(lián)動高亮的事件沖突了,所以用一個 `isScroll` 變量標(biāo)記當(dāng)前是否是錨點(diǎn)定位狀態(tài),定位狀態(tài)不觸發(fā)滾動操作。

    <template>
     <div class="cpt-anchor">
     <el-radio-group
     v-model="selector"
     size="mini"
     @change="handleMenuChange">
     <el-radio-button
     v-for="menu in menus"
     :key="menu.value"
     :label="menu.value">
     {{ menu.label }}
     </el-radio-button>
     </el-radio-group>
     </div>
    </template>
    
    <script>
    import { tween } from 'shifty'
    import { get as _get } from 'noshjs'
    import { getFirstScrollElement } from 'util.js'
    
    import TabMenus from 'components/tab-menus.vue'
    
    export default {
     props: {
     top: {
     type: Number,
     default: 0
     },
     menus: {
     type: Array,
     default: []
     },
     parent: {
     type: String,
     default: ''
     }
     },
    
     data() {
     return {
     menu: '',
     isScroll: true,
     isMounted: false,
     scrollTop: 0,
     anchorChange: false,
     rootScrollElement: ''
     }
     },
    
     mounted() {
     this.isMounted = true
     this.getScrollElement()
     },
    
     watch: {
     parent: {
     immediate: true,
     handler: 'getScrollElement'
     },
    
     menus: {
     immediate: true,
     handler(list) {
     this.menu = _get(list, [0, 'prop'], '')
     }
     },
    
     scrollTop(v) {
     if (this.anchorChange) {
     // 切換按鈕會滾動視圖,$nextTick 之后按鈕值改變了,但滾動可能還沒有結(jié)束,所以需要打個標(biāo)記。
     this.isScroll = true
     }
     }
     },
    
     methods: {
     handleMenuChange(select) {
     this.isScroll = false
     this.anchorChange = false
     // 滾動高度等于元素距離可視區(qū)頭部高度減去元素自身高度與元素上邊框高度以及滾動區(qū)距離可視區(qū)頭部的高度。
     const scrollElement = document.querySelector(select)
     if (scrollElement && this.rootScrollElement) {
     const offsetTop = scrollElement.offsetTop + scrollElement.clientTop
     const offsetHeight = _get(
     this.$el,
     ['parentElement', 'offsetHeight'],
     0
     )
     const top = offsetTop - this.top - offsetHeight
    
     // 做一個緩動處理
     tween({
     from: { x: this.rootScrollElement.scrollTop },
     to: { x: top },
     duration: 500,
     easing: 'easeOutQuint',
     step: ({ x }) => {
     this.rootScrollElement.scrollTop = x
     }
     }).then(({ x }) => {
     this.rootScrollElement.scrollTop = x
     })
    
     this.$nextTick(() => {
     this.anchorChange = true
     })
     }
     },
    
     getScrollElement() {
     if (!this.isMounted) return
     // 如果沒有傳入 parent 默認(rèn)取第一個父級滾動元素
     const parent = this.parent
     let element = null
     if (parent) {
     element = document.querySelector(parent)
     // mount 之后 rootScrollElement 可能已經(jīng)存在了,如果和上次一樣就不做任何操作。
     if (element === this.rootScrollElement) return
     } else if (this.$el) {
     element = getFirstScrollElement(this.$el.parentElement)
     }
     if (element) {
     this.removeScrollEvent()
     this.rootScrollElement = element
     this.rootScrollElement.addEventListener('scroll', this.handleScroll)
     }
     },
    
     removeScrollEvent() {
     if (this.rootScrollElement) {
     this.rootScrollElement.removeEventListener('scroll', this.handleScroll)
     }
     },
    
     handleScroll(event) {
     const scrollTop = this.rootScrollElement.scrollTop
     this.scrollTop = scrollTop
     if (!this.isScroll) return
     const { data, top } = this
     const offsetHeight = _get(this.$el, ['parentElement', 'offsetHeight'], 0)
     const scrollList = []
     data.forEach(item => {
     const element = document.querySelector(item.prop)
     if (element) {
     const top = element.offsetTop
     const rect = {
     top: top + element.clientTop - top - offsetHeight,
     bottom: top + element.offsetHeight - top - offsetHeight
     }
     scrollList.push(rect)
     }
     })
     // 遍歷按鈕元素的 top 和 bottom,查看當(dāng)前滾動在那個元素的區(qū)間內(nèi)。
     scrollList.some((it, index) => {
     if (index && scrollTop >= it.top && top < it.bottom) {
     const menu = _get(data, [index, 'prop'], '')
     if (menu) this.menu = menu
     return true
     } else {
     // 當(dāng)小于最小高度時,就等于最小高度
     if (scrollTop >= 0 && scrollTop < it.bottom) {
     const menu = _get(data, [index, 'prop'], '')
     if (menu) this.menu = menu
     return true
     }
     }
     })
     }
     }
    }
    </script>
    
    <style lang="scss">
    .cpt-anchor {
     padding-top: 4px;
     .cpt-tab-menus {
     margin: 0;
     .el-radio-button {
     margin-left: 10px;
     .el-radio-button__inner {
     border: none;
     border-radius: 5px 5px 0 0;
     border-bottom: 2px solid #e4e7ed;
     background-color: #f6f6f8;
     font-size: 16px;
    
     &:hover {
     border-bottom: 2px solid #409eff;
     }
     }
    
     &.is-active {
     .el-radio-button__inner {
     color: #fff;
     border: none;
     border-radius: 5px 5px 0 0;
     background-color: #409eff;
     border-bottom: 2px solid #409eff;
     box-shadow: none;
     }
     }
     }
     }
    }
    </style>

    吸頂錨點(diǎn)組件

    最后將上面兩個組件合并到一起就是我們所需要的吸頂錨點(diǎn)組件了。

    <template>
     <div class="cpt-sticky-anchor">
     <sticky :top="top" :z-index="zIndex">
     <sticky-menu :top="top" :data="menus" :parent="parent"></sticky-menu>
     </sticky>
     // 滾動區(qū)內(nèi)容存放位置
     <slot></slot>
     </div>
    </template>
    
    <script>
    import Sticky from './sticky.vue'
    import StickyMenu from './menu.vue'
    
    export default {
     // 這里簡寫了,因?yàn)樯厦嬉呀?jīng)有了。
     props: {
     top,
     menus,
     parent,
     zIndex,
     offsetHeight
     },
    
     components: {
     Sticky,
     StickyMenu
     }
    }
    </script>

    使用示例

    <template>
     <div class="page-demo">
     ... 其他內(nèi)容
     <sticky-anchor menus="menus" parent=".page-demo">
     <ul>
     <li class="button-1">視圖一</li>
     <li class="button-2">視圖二</li>
     </ul>
     </sticky-anchor>
     </div>
    </template>
    
    <script>
    import StickyAnchor from 'components/sticky-anchor.vue'
    
    export default {
     data() {
     return {
     menus: [
     { label: '按鈕一', value: '.button-1' },
     { label: '按鈕二', value: '.button-2' }
     ]
     }
     },
    
     components: {
     StickyAnchor
     }
    }
    </script>

    總結(jié)

    到這里整個功能已經(jīng)全部實(shí)現(xiàn)了,我們來總結(jié)一下。

    吸頂效果用兩種解決方案,如果瀏覽支持 sticky 布局,使用 css 更加方便。 使用 a 標(biāo)簽做錨點(diǎn)定位更加簡單,但遇到定位布局需要特殊處理,但會改變路由 hash。 做錨點(diǎn)與滾動聯(lián)動時需要注意按鈕點(diǎn)擊事件與滾動事件沖突。

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法

    實(shí)現(xiàn)一個 Vue 吸頂錨點(diǎn)組件方法:前言 近期產(chǎn)品小哥哥給我提了一個新需求,在一個頁面的滾動區(qū)中添加一組錨點(diǎn)定位按鈕,點(diǎn)擊按鈕將對應(yīng)的元素顯示在頁面的可視區(qū)中。當(dāng)按鈕組超出頁面可視區(qū)的時候?qū)⑵涔潭ㄔ跐L動區(qū)域的頭部,當(dāng)滾動區(qū)滾動時,高亮距離滾動區(qū)頂部最近的元素所匹配的錨點(diǎn)按鈕。
    推薦度:
    標(biāo)簽: 一個 VUE 實(shí)現(xiàn)
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 120秒免费试看 | 国产一区二区在线观看视频 | 国产日韩欧美精品 | 欧美成人一区二区三区 | 最新大黄网站免费 | 伊人网中文字幕 | 亚洲一区有码 | 国产视频第一页 | 日韩欧美偷拍 | 精品视频在线观看一区二区三区 | 日本一区二区三区免费观看 | 久久综合精品国产一区二区三区 | 亚洲国产 | 一区二区三区在线 | 国产在线成人一区二区 | 欧美日韩国产在线 | 精品久久久久久综合网 | 一级成人a免费视频 | 91精品久久久久久久久久 | 欧美啊v在线观看 | 国产午夜电影在线观看 | 国产网站视频 | 香蕉久久一区二区不卡无毒影院 | 国产资源免费 | 国产福利二区 | 国产一区二区三区高清 | 国产精品久久久久久久 | 国产精品久久久久久久午夜片 | 欧美视频精品一区二区三区 | 一区二区三区视频在线 | 国产精品亚洲精品日韩动图 | 国产最新网站 | 91视频国产91久久久 | 全免费a级毛片免费毛视频 情侣国产在线 | 最新国产小视频在线播放 | 久久久这里有精品999 | 国产精品视_精品国产免费 国产精品视频第一区二区三区 | a男人的天堂久久a毛片 | 69国产成人综合久久精品 | 欧美国产日韩在线观看 | 亚洲精品一二三四区 |