Vue Affix組件

在vue的項目中常常用到固釘,可是 element-ui 上並無提供這樣的組件可供使用,ant-design-vue 有提供,總不能爲了這一個組件再去引入一個組件庫吧vue

下面是一個封裝好的 affix 組件,能夠放到項目中直接使用git

Affix.vuegithub

<template>
    <div class="affix-placeholder" :style="wrapStyle">
        <div :class="{'affix': affixed}" :style="styles">
            <slot></slot>
        </div>
    </div>
</template>
<script>
/** * @file Affix.vue * @author v_shenjieping@baidu.com * @date 2018-12-11 10:09:50 */ export default { props: { offset: { type: Number, default: 0 }, onAffix: { type: Function, default() {} }, boundary: { type: String, default: '' } }, data() { return { affixed: false, styles: {}, affixedClientHeight: 0, wrapStyle: {} }; }, methods: { getScroll(w, top) { let ret = w[`page${(top ? 'Y' : 'X')}Offset`]; const method = `scroll${top ? 'Top' : 'Left'}`; if (typeof ret !== 'number') { const d = w.document; // ie6,7,8 standard mode
                ret = d.documentElement[method]; if (typeof ret !== 'number') { // quirks mode
                    ret = d.body[method]; } } return ret; }, getOffset(element) { const rect = element.getBoundingClientRect(); const body = document.body; const clientTop = element.clientTop || body.clientTop || 0; const clientLeft = element.clientLeft || body.clientLeft || 0; // const clientHeight = element.clientHeight || 0;
            const scrollTop = this.getScroll(window, true); const scrollLeft = this.getScroll(window); return { top: rect.bottom + scrollTop - clientTop - this.affixedClientHeight, left: rect.left + scrollLeft - clientLeft }; }, handleScroll() { const scrollTop = this.getScroll(window, true) + this.offsets; // handle setting offset
            const elementOffset = this.getOffset(this.$el); if (!this.affixed && scrollTop > elementOffset.top) { this.affixed = true; this.styles = { top: `${this.offsets}px`, left: `${elementOffset.left}px`, width: `${this.$el.offsetWidth}px` }; this.onAffix(this.affixed); } // if setting boundary
            if (this.boundary && scrollTop > elementOffset.top) { const el = document.getElementById(this.boundary.slice(1)); if (el) { const boundaryOffset = this.getOffset(el); if ((scrollTop + this.offsets) > boundaryOffset.top) { const top = scrollTop - boundaryOffset.top; this.styles.top = `-${top}px`; } } } if (this.affixed && scrollTop < elementOffset.top) { this.affixed = false; this.styles = {}; this.onAffix(this.affixed); } if (this.affixed && this.boundary) { const el = document.getElementById(this.boundary.slice(1)); if (el) { const boundaryOffset = this.getOffset(el); if ((scrollTop + this.offsets) <= boundaryOffset.top) { this.styles.top = 0; } } } } }, computed: { offsets() { if (this.boundary) { return 0; } return this.offset; } }, mounted() { this.affixedClientHeight = this.$el.children[0].clientHeight; this.wrapStyle = {height: `${this.affixedClientHeight}px`}; window.addEventListener('scroll', this.handleScroll); window.addEventListener('resize', this.handleScroll); }, beforeDestroy() { window.removeEventListener('scroll', this.handleScroll); window.removeEventListener('resize', this.handleScroll); } }; </script>
<style lang="sass"> .affix position: fixed </style>

使用方法也是很是簡單element-ui

test.vuesass

<template>
    <div class="test">
        <affix>
            <div>這是一個固釘組件</div>
        </affix>
        <affix :offset="40">
            <div>這是一個固釘組件</div>
        </affix>
    </div>
</template>

<script> import Affix from '@/components/Affix'; export default { name: 'test', components: { Affix } }; </script>

API函數

參數 說明 類型 默認值
offset 距離窗口頂部達到指定偏移量後觸發 Number 0
boundary 設置 Affix 的活動範圍,值爲affix上級元素的id(能夠是父元素,也能夠是父元素的父元素...) String(#parent)  
on-affix 固定狀態改變時觸發的回調函數 Function(affixed)
相關文章
相關標籤/搜索