Reputation: 1180
How to get the element width and height immediately when it resizing in Vue.js? Here is my code pen illustration please help me to change it till work,thanks!
let app = new Vue({
el: '#app',
data: {
boxs: [{
width: 100,
height: 100
},
{
width: 100,
height: 100
}
]
}
});
#app {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.resize {
display: flex;
justify-content: center;
align-items: center;
margin: 5px;
width: 100px;
height: 100px;
overflow: hidden;
resize: both;
background-color: #C3E2CE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id="app">
<div v-for="box,key in boxs" class="resize">
{{ box.width }} x {{ box.height }}
</div>
</div>
Upvotes: 3
Views: 19663
Reputation: 1787
Easy way would be plain JS eventListener
to change a local variable
window.addEventListener('resize', this.getWindowWidth);
data() {
return {
windowWidth:0
}
},
mounted () {
this.$nextTick(function() {
window.addEventListener('resize', this.getWindowWidth);
this.getWindowWidth()
})
},
methods: {
getWindowWidth() {
this.windowWidth = document.documentElement.clientWidth
}
}
and don't forget to remove the eventListener
on component destroy
beforeDestroy() {
window.removeEventListener('resize', this.getWindowWidth);
}
Upvotes: 4
Reputation: 26877
To get immediate feedback that responds to the actual resize action, you might want to try using a MutationObserver
. You can attach it to a ref
point of your component and listen for mutations there.
You can attach the MutationObserver
in the mounted
function. Be sure to also do any cleanup that you need in the destroyed
function.
const Resizable = {
template: "<div ref='main' @resize='onResize' class='resize'>{{dims.width}} | {{dims.height}}</div>",
data() {
return {
dims: {
width: null,
height: null
}
};
},
mounted() {
const {
width,
height
} = this.$refs.main.getBoundingClientRect();
this.dims.width = width;
this.dims.height = height;
const mutationHandler = mutationList => {
for (let mutation of mutationList) {
if (mutation.type === "attributes") {
const {
width,
height
} = mutation.target.getBoundingClientRect();
this.dims.width = width;
this.dims.height = height;
}
}
};
const mo = new MutationObserver(mutationHandler);
mo.observe(this.$refs.main, {
attributes: true,
childList: true,
subtree: true
});
},
methods: {
onResize() {
console.log("Resized");
}
}
};
const app = new Vue({
el: "#app",
components: {
"resizable": Resizable
},
data() {
return {
items: [
"foo",
"bar",
"fizz"
]
}
}
});
body {
background-color: #414141;
}
.container {
display: flex;
align-items: center;
justify-content: center;
}
.resize {
resize: both;
margin: 5px;
width: 100px;
height: 100px;
color: black;
overflow: scroll;
background-color: white;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id="app">
<div class="container">
<resizable v-for="item in items" :key="item" class="resize"></resizable>
</div>
</div>
Upvotes: 8
Reputation: 3065
Forgive me, but I'm still learning Vue as well. I'd suggest you do more modular approach and extract the boxes, then just loop how many you want. Please note that this is not best-practice, as the box w/h should probably be coming from props and data being loaded from the root element.
const box = Vue.component("box", {
template: '<div class="resize">{{ boxWidth }} x {{ boxHeight}}</div>',
data() {
return {
boxWidth: 100,
boxHeight: 100,
};
},
mounted: function() {
this.$el.addEventListener("mouseup", this.move);
},
methods: {
move(e) {
if (e.target == this.$el) {
this.boxWidth = parseInt(this.$el.style.width);
this.boxHeight = parseInt(this.$el.style.height);
}
}
}
});
let app = new Vue({
el: "#app",
components: { box: box },
});
#app {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.resize {
display: flex;
justify-content: center;
align-items: center;
margin: 5px;
width: 100px;
height: 100px;
overflow: hidden;
resize: both;
background-color: #C3E2CE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.js"></script>
<div id="app">
<div v-for="b in [0,1]">
<box></box>
</div>
</div>
Upvotes: 0