minbaowang / SSeffects

some small effects in my code's history
1 stars 0 forks source link

页面底部滚动条,替代element的table滚动条(外部组件) #10

Open minbaowang opened 5 years ago

minbaowang commented 5 years ago

页面底部滚动条,替代element的table滚动条

1、html部分

<div id="footer-scroll-bar" class="footer-scroll-bar" v-if="show">
<div class="footer-scroll-bar-content" :style="{width: width}" @scroll="scroll" ref="scrollBar">
<div class="footer-scroll-bar_bar" :style="{width: scrollWidth}"></div>
</div>
</div>

2、js部分


/*
* @Author   JL_Guan && wangfumin
* 页面底部滚动条,替代element的table滚动条
* 先在入口使用Vue.use注册
* 在页面上使用: const bar = this.initScrollBar(className | Element, className | Element)
* 在watch里面使用,tableData数据变化时重新调用this.initScrollBar(className | Element, className | Element)
* 考虑到性能问题, 有必要时可以在页面上的beforeDestroy钩子调用 bar.removeListener()
*/

define([ 'itFooterScrollBar.html',//引进html文件和css文件,具体文件夹路径视自己的构造 'itFooterScrollBar.css', ], function (template, css) { "use strict"

    return function (Vue) {
        const vm = new (Vue.extend({
            name: 'itFooterScrollBar',
            template,
            data: () => ({
                body: '',
                container: '',
                scrollWidth: 0,
                width: 0,
                // 滚动节点
                scrollNode: '',
                // 是否需要显示滚动条
                show: true,
            }),
            methods: {
                /**
                 * 初始化函数
                 * @Author   JL_Guan && wangfumin
                 * @param    {[String | Element]}                 body [滚动条容器]
                 * @param    {[String | Element]}                 container [设置了overflow:auto的容器]
                 * @return   {[type]}                             this [返回当前实例]
                 */
                init(body, container) {
                    if (!body) {
                        return new Error('Please enter a node or string!');
                    }
                    this.$nextTick(() => {
                        // 若在created调用, 此时dom还没加载,更新后再获取
                        this.body = typeof body === 'string' ? document.querySelector(body) : body;
                        this.container = typeof container === 'string' ? document.querySelector(container) : container;
                        if (!this.body) return;
                        this.scrollNode = this.body.querySelector('.el-table__body-wrapper');
                        if (this.container.scrollHeight - this.container.clientHeight > 50) {
                            this.show = true;
                            this.scrollNode.style.overflow = 'hidden';
                        } else {
                            this.scrollNode.style.overflow = 'auto';
                            this.show = false;
                        }
                        this.width = this.body.clientWidth + 'px';
                        this.addListener(body, container);
                        if (!this.body.querySelector('#footer-scroll-bar')) {
                            this.appendChild();
                        }
                        this.setStyle();
                    })
                    return this;
                },
                setStyle() {
                    // 异步获取table表格
                    const fn = () => {
                        if (!this.body) return;
                        const tableNode = this.body.querySelector('.el-table');
                        const el_table_body = tableNode.querySelector('.el-table__body');
                        this.scrollWidth = el_table_body.clientWidth / tableNode.clientWidth * this.body.clientWidth + 'px';
                        // 去除el-table的滚动条
                        const fixed = tableNode.querySelector('.el-table__fixed');
                        const fixed_right = tableNode.querySelector('.el-table__fixed-right');
                        // 把滚动条的高度补回去
                        if (fixed) {
                            fixed.style.height = parseInt(fixed.style.height) + (this.show ? 8 : -1) + 'px';
                        }
                        if (fixed_right) {
                            fixed_right.style.height = parseInt(fixed_right.style.height) + (this.show ? 8 : -1) + 'px';
                        }
                    }
                    // 当在created的时候调用,未加载dom
                    setTimeout(() => {
                        fn();
                    }, 500)
                },
                appendChild() {
                    this.body.appendChild(this.$el);
                },
                // 滚动事件
                scroll(e) {
                    if (!this.show) return;
                    if (this.scrollNode) this.scrollNode.scrollLeft = e.target.scrollLeft;
                },
                addListener(body, container) {
                    const fn = this.throttle(this.init, 200);
                    // 监听页面宽度变化
                    if (!window.onresize) window.onresize = (e) => {
                        fn(body, container);
                    }
                    if (!this.container) return;
                    const tableNode = this.body.querySelector('.el-table');
                    this.container.onscroll = this.throttle((e) => {
                        if (e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop < 50) {
                            this.scrollNode.style.overflow = 'auto';
                            this.show = false;
                        } else {
                            this.scrollNode.style.overflow = 'hidden';
                            this.show = true;
                        }
                    }, 200)
                },
                // 移除所有监听
                removeListener() {
                    if (window.onresize) {
                        window.onresize = null;
                    }
                    if (this.container) this.container.onscroll = null;
                },
                // 简单节流
                throttle(fn, delay) {
                    let time;
                    return (body, container) => {
                        if (time) {return;}
                        time = setTimeout(() => {
                            time = null;
                            fn(body, container);
                        }, delay)
                    }
                },
            },
        }))

        Vue.prototype.initScrollBar = vm.$mount().init;
    }
}

)

>3、scss部分
```js
.footer-scroll-bar-content {
    width: 500px;
    overflow-x: auto;
    position: fixed;
    bottom: 0;
    z-index: 1000;
    &::-webkit-scrollbar-thumb:hover {
        background: #909090;
    }
}
.footer-scroll-bar_bar {
    height: 10px;
    width: 1250px;
}
Damao2250 commented 5 years ago

niubility Wang

minbaowang commented 4 years ago

niubility Wang

no