zoukankan      html  css  js  c++  java
  • Vue Affix组件

    在vue的项目中经常用到固钉,但是 element-ui 上并没有提供这样的组件可供使用,ant-design-vue 有提供,总不能为了这一个组件再去引入一个组件库吧

    下面是一个封装好的 affix 组件,可以放到项目中直接使用

    Affix.vue

    <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`,
                         `${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>

    使用方法也是非常简单

    test.vue

    <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)
  • 相关阅读:
    家居有线网络布线方案(转)
    ARP、Tracert、Route 与 NBTStat 命令详解(转)
    集线器、路由器、交换机、第三层交换技术(转)
    C#版nbtstat
    交换机常见故障的一般分类和排障步骤(转)
    Women guojia keneng zai 2015 nian qianhou wancheng di yi ci xiandaihua(拼音化汉字)
    IPv6协议在各操作系统下的安装与配置(转)
    具有字典验证的记事本
    子网掩码计算方法(转)
    最后推荐一篇关于PreEcho的总结论文
  • 原文地址:https://www.cnblogs.com/shenjp/p/10100837.html
Copyright © 2011-2022 走看看