怎么在Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)怎么在 Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

成都創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站建設(shè)、成都網(wǎng)站制作與策劃設(shè)計(jì),隴西網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:隴西等地區(qū)。隴西做網(wǎng)站價(jià)格咨詢:13518219792

拆分功能點(diǎn)

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

  • 按鈕組要有吸頂效果

  • 點(diǎn)擊按鈕要有錨點(diǎn)定位功能

  • 滾動(dòng)內(nèi)容區(qū)需要找到對(duì)應(yīng)的按鈕并高亮

吸頂組件

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

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

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

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

既然需要自己實(shí)現(xiàn)一個(gè)吸頂?shù)男Ч?,思考到其他?yè)面可能也會(huì)使用的吸頂?shù)墓δ?,所以決定將其單獨(dú)抽離成一個(gè)通用組件。首先我們知道粘性布局是對(duì)父級(jí)滾動(dòng)元素定位,所以我們要先找到父級(jí)滾動(dòng)元素,這個(gè)功能我們可以通過(guò)兩種方式實(shí)現(xiàn),一種是向上查找,一種是通過(guò) props 傳遞一個(gè)唯一標(biāo)識(shí)的 css 選擇器。

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

// util.js 文件
// 判斷一個(gè)元素是否是滾動(dòng)元素
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)
 }
}

// 獲取第一個(gè)滾動(dòng)元素
export function getFirstScrollElement(el, direction = 'vertical') {
 if (!el) return
 if (hasScrollElement(el, direction)) {
 return el
 } else {
 return getFirstScrollElement(el && el.parentElement, direction)
 }
}

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

  • fixed 定位是相對(duì)于瀏覽器的可視區(qū)進(jìn)行定位,這意味著即使頁(yè)面滾動(dòng),它還是會(huì)固定在相同的位置

  • offsetTop 是一個(gè)只讀的屬性,它返回當(dāng)前元素相對(duì)于距離它最近的父級(jí)定位元素頂部的距離。

  • scrollTop 屬性可以獲取或設(shè)置一個(gè)元素的內(nèi)容垂直滾動(dòng)的像素值,`scrollTop` 表示這個(gè)元素達(dá)到父級(jí)滾動(dòng)元素頂部的距離。

<template>
 <div class="cpt-sticky" :class="fixedClass" :>
 <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)了一個(gè)吸頂組件,不過(guò)它實(shí)現(xiàn)了吸頂?shù)墓δ?,但是還有一些缺陷。

  1. 在慢速滾動(dòng)頁(yè)面,吸頂組件在固定與非固定的時(shí)候有明顯的卡頓現(xiàn)象。

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

怎么在 Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件

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

<template>
 <div class="cpt-sticky">
 <div class="sticky-container" :class="fixedClass" :>
  <slot></slot>
 </div>
 <div v-if="showPlaceholder" class="sticky-placeholder" :></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)頁(yè)中經(jīng)常會(huì)有用到錨點(diǎn)定位的場(chǎng)景,例如百度知道的目錄,我目前知道有三種方式可以實(shí)現(xiàn)這種功能。

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

  2. 使用 js 定位

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

先說(shuō)說(shuō) a 標(biāo)簽定位,這是一種最常用的定位方式。它有兩種實(shí)現(xiàn)方式,一種是通過(guò) herf 屬性鏈接的指定元素的 id。另一種是添加一個(gè) a 標(biāo)簽,再將 href 屬性鏈接到這個(gè) 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>

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

怎么在 Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件 怎么在 Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件

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

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

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

<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>
// 添加緩動(dòng)函數(shù)
import { tween } from 'shifty'
// 類似 lodash.get 但處理了 null 類型
import { get as _get } from 'noshjs'
import { getFirstScrollElement } from 'util.js'

export default {
 props: {
 // 滾動(dòng)區(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

  // 做一個(gè)緩動(dòng)處理
  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)

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

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

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

<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) {
  // 切換按鈕會(huì)滾動(dòng)視圖,$nextTick 之后按鈕值改變了,但滾動(dòng)可能還沒(méi)有結(jié)束,所以需要打個(gè)標(biāo)記。
  this.isScroll = true
  }
 }
 },

 methods: {
 handleMenuChange(select) {
  this.isScroll = false
  this.anchorChange = false
  // 滾動(dòng)高度等于元素距離可視區(qū)頭部高度減去元素自身高度與元素上邊框高度以及滾動(dòng)區(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

  // 做一個(gè)緩動(dòng)處理
  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
  // 如果沒(méi)有傳入 parent 默認(rèn)取第一個(gè)父級(jí)滾動(dòng)元素
  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)前滾動(dòng)在那個(gè)元素的區(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)小于最小高度時(shí),就等于最小高度
   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)組件

最后將上面兩個(gè)組件合并到一起就是我們所需要的吸頂錨點(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>
 // 滾動(dòng)區(qū)內(nèi)容存放位置
 <slot></slot>
 </div>
</template>

<script>
import Sticky from './sticky.vue'
import StickyMenu from './menu.vue'

export default {
 // 這里簡(jiǎn)寫(xiě)了,因?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>
Vue的優(yōu)點(diǎn)

Vue具體輕量級(jí)框架、簡(jiǎn)單易學(xué)、雙向數(shù)據(jù)綁定、組件化、數(shù)據(jù)和結(jié)構(gòu)的分離、虛擬DOM、運(yùn)行速度快等優(yōu)勢(shì),Vue中頁(yè)面使用的是局部刷新,不用每次跳轉(zhuǎn)頁(yè)面都要請(qǐng)求所有數(shù)據(jù)和dom,可以大大提升訪問(wèn)速度和用戶體驗(yàn)。

關(guān)于怎么在 Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

新聞名稱:怎么在Vue中實(shí)現(xiàn)一個(gè)吸頂錨點(diǎn)組件-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)URL:http://muchs.cn/article30/dhgcpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、虛擬主機(jī)、響應(yīng)式網(wǎng)站、微信公眾號(hào)、網(wǎng)站設(shè)計(jì)、服務(wù)器托管

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)