vue-element-resize-event

Version Downloads License

AndroidFirefoxChromeIEiPhoneEdgeSafari
>=4.4>=9

vue-element-resize-event,简称elresize,是一个扩展vue事件的插件,使vue可以监听普通元素的resize事件。HTML中如果在页面或框架被调整大小时会触发resize事件,但是普通元素尺寸变化的时候却没有对应的事件。vue-element-resize-event基于js的奇巧淫技可以模拟出这个事件。

源码

安装

npm install vue-element-resize-event

可以采用插件形式的全局安装:

import Vue from 'vue'
import * as ElResize from 'vue-element-resize-event'
Vue.use(ElResize)

也可以采用局部安装:

import {
    elresizeDirective,
    elresize,
} from 'vue-element-resize-event'

export default {
    ...
    directive: {
        elresizeDirective,
    }
    component: {
        elresize,
    },
}

使用

vue-element-resize-event提供了两种使用方式——directive和component。

指令

使用v-elresize指令监听elresize事件。要求v-elresize所在的元素的position值不能为static:

<div style="position: relative;" v-elresize @elresize="test"></div>
</doc>
Your browser does not support the srcdoc attribute in the iframe. Or CSP prohibits the use of iframes.
view code

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="./vue-element-resize-event.js"></script>
    <style>
        body, html{
            padding: 0;
            margin: 0;
        }
        .test{
            margin: 0;
            background: #e6e6e6;
            height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 10px;
            box-sizing: border-box;
        }
        .elresize{
            background: red;
            width: 100px;
            height: 100px;
            resize: both;
        }
        .box {
            position: relative;
            background: #2ecc71;
        }
        .label{
            width: 220px;
            height: 40px;
            line-height: 40px;
            text-align: left;
        }
        .title{
            width: 50px;
            display: inline-block;
        }
        .range{
            width: 140px;
            -webkit-appearance: none;
            background: #059CFA;
            height: 3px;
            outline: none;
            vertical-align: middle;
        }
        .range::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 26px;
            width: 26px;
            background: #fff;
            border-radius: 50%;
            border: solid 1px #ddd;
        }
    </style>

</head>
<body>

    <div id="app">
        <div class="test">
            <label class="label">
                <span class="title">width:</span>
                <input id="widthInput" type="range" class="range" max="200" min="100" v-model="width">px
            </label>

            <Elresize class="box" :style="{width: width + 'px', height: '100px'}" @elresize="test">
                resize count : {{resizeCount}}
            </Elresize>
        </div>
    </div>
    <script>
        Vue.use(vueElementResizeEvent)
        var app = new Vue({
            el: '#app',
            data: {
                width: '200',
                resizeCount: 0
            },
            methods: {
                test(e){
                    this.resizeCount++
                },
            }
        })
    </script>
</body>
</html>

控件

使用Elresize控件监听elresize事件:

<Elresize @elresize="test"></Elresize>
Your browser does not support the srcdoc attribute in the iframe. Or CSP prohibits the use of iframes.
view code

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="./vue-element-resize-event.js"></script>
    <style>
        body, html{
            padding: 0;
            margin: 0;
        }
        .test{
            margin: 0;
            background: #e6e6e6;
            height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 10px;
            box-sizing: border-box;
        }
        .elresize{
            background: red;
            width: 100px;
            height: 100px;
            resize: both;
        }
        .box {
            position: relative;
            background: #2ecc71;
        }
        .label{
            width: 220px;
            height: 40px;
            line-height: 40px;
            text-align: left;
        }
        .title{
            width: 50px;
            display: inline-block;
        }
        .range{
            width: 140px;
            -webkit-appearance: none;
            background: #059CFA;
            height: 3px;
            outline: none;
            vertical-align: middle;
        }
        .range::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 26px;
            width: 26px;
            background: #fff;
            border-radius: 50%;
            border: solid 1px #ddd;
        }
    </style>

</head>
<body>

    <div id="app">
        <div class="test">
            <label class="label">
                <span class="title">width:</span>
                <input id="widthInput" type="range" class="range" max="200" min="100" v-model="width">px
            </label>

            <Elresize class="box" :style="{width: width + 'px', height: '100px'}" @elresize="test">
                resize count : {{resizeCount}}
            </Elresize>
        </div>
    </div>
    <script>
        Vue.use(vueElementResizeEvent)
        var app = new Vue({
            el: '#app',
            data: {
                width: '200',
                resizeCount: 0
            },
            methods: {
                test(e){
                    this.resizeCount++
                },
            }
        })
    </script>
</body>
</html>

原理

模拟resize事件目前主要有两种:

  • 方法一,监听scroll事件:

要求可以监听resize事件的元素的css的position属性不可以是static,然后创建两个和该元素等大的div,一个监听元素放大事件,一个监听元素缩小事件。两个div都是绝对定位,并且css的visibility属性是hidden,同时使用js将水平和垂直滚动条的值都设置大最大。实现的例子有:KyleAMathews/element-resize-event

  • 方法二,监听object(iframe)的resize事件:

同样要求可以监听resize事件的元素的css的position属性不可以是static,然后创建一个iframe或者object。因为frame和object可以监听resize事件,所以只要要求frame或object和被监听元素等大,就可以让frame或object的resize事件实现该元素的resize事件了。实现的例子有:developit/simple-element-resize-detector

因为object(iframe)更耗费资源,而且会被CSP策略限制,所以vue-element-resize-event选用了第一种方法。