Vue реализует простой эффект потолка, якоря и кнопки выделения прокрутки.

Vue.js

предисловие

Поскольку многие функции и технологии внутренней системы управления компании устарели, Vue в последнее время используется для реконструкции внутренней системы управления компании. необходимо реализовать простой потолок и опорную точку, а также прокрутку эффектов кнопки подсветки.

нужно

  1. Прокрутите страницу вверх, чтобы добиться эффекта закрепления элемента наверху
  2. Нажмите кнопку, страница прокрутится до соответствующей позиции
  3. Прокрутите страницу, когда вы достигнете определенной позиции, выделите соответствующую соответствующую кнопку

Реализация потолочного элемента

Что касается эффекта потолка элемента, есть три способа, которые можно получить, ознакомившись с соответствующими материалами и соответствующими тестами (есть также метод jquery, который здесь не будет представлен).

1. Используйте положение: липкое

1. Что такое position:sticky?

Элемент липкого позиционирования эквивалентен комбинации position:relative и position:sticky, он ограничен родительским элементом и представляет разные эффекты страницы в разных условиях.

2. Как использовать липкий?

Эффект липкого элемента полностью ограничен родительским элементом с использованием условий:
1. Переполнение родительского элемента липкого элемента можно сделать только видимым, иначе эффекта липкости не будет
2. Родительский элемент липкого элемента не может устанавливать фиксированную высоту, иначе не будет эффекта липкости
3. Когда липкий элемент соответствует условиям и становится фиксированным, он отличается от стандартного фиксированного элемента и не будет отклоняться от потока документов.
4. Элемент, позиционированный как sticky, не может добавить родительский элемент, который содержит только себя, что не приведет к эффекту прилипания.
5. Липкие элементы в одном и том же родительском элементе будут перекрываться, если значения позиционирования равны.Если они принадлежат разным родительским элементам, предыдущие элементы будут выдавлены, чтобы сформировать эффект заполнения места. Конкретный эффект реализации заключается в следующем:

.sticky-box{  
 position: sticky;  
 position: -webkit-sticky;
 top: 60px; //可通过js动态设置
}

3. Совместимость

Соответствующую совместимость можно увидеть, посмотрев, могу ли я использовать:

Видно, что совместимость этого атрибута не очень хорошая, если проекту нужна совместимость с ie11 и т.п., то он не так применим.

2. Используйте смещение сверху

HTMLElement.offsetTop — это свойство только для чтения, которое возвращает расстояние текущего элемента относительно верхнего заполнения его элемента offsetParent. Следовательно, на что нам нужно обратить внимание, так это на то, что в процессе мониторинга прокрутки страницы необходимо вычислить смещение позиционирования родительского элемента, которое можно записать следующим образом:

    //获取当前元素的offsetTop
    getOffsetTop(obj) {
      let offsetTop = 0;
      while (obj != window.document.body && obj != null) {
        offsetTop += obj.offsetTop;
        obj = obj.offsetParent;
      }
      return offsetTop;
    }

Добавив событие, которое отслеживает прокрутку события, в смонтированную функцию жизненного цикла Vue:

 mounted() {
    /**通过给变成固定定位的元素添加一个同等高度的父元素,防止该元素变成固定定位时,脱离文档流导致的页面抖动 */
    this.tabsHeight = this.$refs.elTabs.offsetHeight;
    window.addEventListener("scroll", this.handleScroll);
  },
  destroyed() {
    //离开该页面需要移除这个监听的事件
    window.removeEventListener("scroll", this.handleScroll);
  },
   methods: {
    /**滚动事件 */
    handleScroll() {
        //获取页面滚动条的高度
        let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
        let offsetTop = this.getOffsetTop(this.$refs.elTabs);
        this.isFixed = scrollTop > offsetTop;
    }
  }

В то же время, если этот способ потолка будет многократно использоваться в проекте, его можно инкапсулировать в виде компонентов

3. Используйте getBoundingClientRect().top

Существует также более прямой способ достижения эффекта потолка, который заключается в использовании getBoundingClientRect().top для получения положения элемента относительно окна просмотра (окна браузера).По сравнению с offsetTop, этот метод не требует учета потолок элемента потолка. Высота родительского элемента и полоса прокрутки страницы могут обрабатываться непосредственно на элементе. Реализация следующая: /*событие прокрутки/ handleScroll() { /* getBoundingClientRect().top 获取某元素距离浏览器顶部的高度,不包含滚动的距离 */ let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top; this.isFixed = tabOffsetTop

     /**滚动事件 */
    handleScroll() {
      /**
       * getBoundingClientRect().top 获取某元素距离浏览器顶部的高度,不包含滚动的距离
       this.offsetTop 表示的是吸顶元素距离顶部的条件值(一般项目需求是0)
       */
      let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top;
      this.isFixed = tabOffsetTop < this.offsetTop
    }

Положение якоря

Нажмите соответствующую кнопку, и страница прокрутится до соответствующей позиции. В настоящее время я знаю, что есть два способа выполнить эту функцию:
1. Используйте тег, чтобы найти
2. Используйте js для имитации позиционирования якоря

Используйте тег, чтобы найти

Это распространенный метод позиционирования, и его можно реализовать двумя способами:
1. Ссылка на id указанного элемента через атрибут href
2. Другой способ — добавить тег a и связать атрибут href с атрибутом name тега a.

  <a href="#view1">按钮1</a>  
  <a href="#view2">按钮1</a>  
  <div id="view1">视图1</div>  
  <div><a name="view2">视图2</a></div>  

Этот метод позиционирования очень прост и поддерживает позиционирование любой метки, но позиционирование метки меняет хэш маршрута.Если есть связанный маршрут, маршрут будет пропущен.

Используйте js для имитации позиционирования привязки

Получите значение scrollTop элемента через js и прокрутите его до указанной позиции, чтобы добиться эффекта позиционирования точки привязки. Параметр переключения вкладок здесь использует компонент el-tabs элемента-ui. Конкретная реализация выглядит следующим образом:

<!-- html -->
 <el-tabs v-model="activeName" type="card" @tab-click="tabClick">
    <el-tab-pane :label="item.name" :name="item.key" v-for="item in tabList" :key="item.key"></el-tab-pane>
</el-tabs>
<!-- js -->
methods:{
  //获取当前元素的offsetTop
  getOffsetTop(obj) {
    let offsetTop = 0;
    while (obj != window.document.body && obj != null) {
    offsetTop += obj.offsetTop;
    obj = obj.offsetParent;
  }
    return offsetTop;
 },
 <!--锚点点击事件-->
 <!--fixedHeight 滚动的位置上方固定的高度-->
 tabClick(e) {
    let _this = this;
    //获取当前选中的index以便后面滚动高亮
    this.index = parseInt(e.index);
    //给定一个标识,锚点事件不触发滚动
    this.isScroll = false;
    this.isChange = false;
    //获取当前选中元素的top值(给元素绑定对应的ref值)
    let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
    let scrollTop = offsetTop - this.fixedHeight;
    window.scrollTo({
        top: scrollTop
   });
}

Один метод, который я должен упомянуть, это scrollIntoView, Метод Element.scrollIntoView() позволяет прокручивать текущий элемент в видимую область окна браузера, а также поддерживает динамические эффекты, но не поддерживает настройку расстояния от верха прокрутки, и будут окклюзии Феномен капюшона, но он очень подходит для функции, которая достигнет вершины

Выделенная кнопка прокрутки

Когда пользователь прокручивает область содержимого, кнопка, соответствующая элементу, ближайшему к компоненту кнопки, выделяется. Прослушивая событие прокрутки, получите значение offsetTop текущей выбранной вкладки и значение scrollTop текущей страницы, определите, следует ли прокручивать вверх или вниз, и выполните различную обработку следующим образом:

//页面滚动要做的事情
handleScroll() {
    let scrollTop =
        window.pageYOffset ||
        document.documentElement.scrollTop ||
        document.body.scrollTop;
      this.scrollTop = scrollTop;
      <!--isScroll 用于避免锚点事件触发页面滚动-->
      if (!this.isScroll) return;
      /**
       * scrollTop 页面的滚动条的高度
       * offsetTop 当前选中的tab元素的offsetTop
       * offsetHeight 当前选中元素的高度
       */
      let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
      let offsetHeight = this.$refs[this.activeName].offsetHeight;
      let actuaTop = scrollTop + this.fixedHeight;
      let length = this.tabList.length;
      /**
       * 页面滚动中根据相应位置变换选中tab
       */
      if (actuaTop < offsetTop && this.index > 0) {
        this.index = this.index - 1;
        this.activeName = this.tabList[this.index].key;
      } else if (this.index < length && actuaTop > offsetTop + offsetHeight) {
        this.index = this.index + 1;
        this.activeName = this.tabList[this.index].key;
  }
}

оптимизация производительности

Чтение атрибутов на странице приведет к перекомпоновке страницы (в следующий раз сделаем сводку операций, приводящих к перекомпоновке и перерисовке страницы), чрезмерное перекомпоновывание приведет к падению производительности страницы, поэтому надо постараться уменьшить количество перекомпоновок, чтобы чтобы дать пользователям лучший опыт. Если продукт может принять эффект задержки, вы можете использовать функцию регулирования для управления функцией, которая будет выполняться только один раз в течение определенного периода времени (функция регулирования может использовать метод дросселирования, инкапсулированный lodash.js).

Суммировать

На данный момент три функции в требованиях реализованы, и могут быть лучшие решения, но на этот раз за счет реализации этих трех требований, если у вас есть другие лучшие методы, оставьте сообщение для добавления, но я также узнал из него получилось что-то
1.позиция: использование и условия использования липкой
2. Связанные свойства элементов scrollTop, offsetTop и других, использование getBoundingClientRect() и использование scrollTo, scrollIntoView
3. Обработка конфликтов, вызванных временем привязки, событиями прокрутки и т. д.