I am creating a website in which the value of a range slider is bound using v-model
, to a property called rangeValue
. The code looks similar to the following:
<template>
...
<input
type="range"
min="10"
max="50"
v-model="rangeValue"
@change="updateHeight()"
/>
<div :style="{ height: `${wrapperHeight}px`></>
<div
ref="first"
:style="{ width: `${rangeValue}rem` }">
<!-- There are elements inside whose height is also bound by rangeValue, and some that are toggled on/off via other checkbox inputs, thereby changing the height of firstDiv -->
</div>
</template>
<script>
export default {
data() {
return {
wrapperHeight: 0,
rangeValue: "10",
},
mounted(){
this.wrapperHeight = this.$refs.first.offsetHeight;
},
methods: {
updateHeight() {
this.wrapperHeight = this.$refs.first.offsetHeight;
}
}
}
</script>
<style>
...
</style>
I would like to make the height of otherDiv
match the height of firstDiv
, whose height changes based on range slider changes. My problem is that the height of firstDiv
updates concurrently with the range slider changes, while the height of otherDiv
always lags one "tick" behind, updating to the value of the firstDiv
before it's been changed by the range slider, rather than after. I have tried all sorts of implementations using nextTick
to no avail.
In short, I would need to:
- Update range slider
- Resize
firstDiv
, get its height in the DOM, resizeotherDiv
- Repaint DOM (so both are resized at the same time).
I hope this makes sense. Any pointers are more than welcome, thank you!
CodePudding user response:
Is this what you want to achieve?
const { createApp, toRefs, reactive, computed } = Vue
createApp({
setup: () =>
toRefs(
reactive({
h8: 135
})
)
}).mount("#app")
#app .grid {
display: grid;
grid-gap: 0.75rem;
grid-template-columns: repeat(2, 1fr);
padding: 0.5rem;
}
#app .grid > * {
overflow-y: auto;
padding: 0.5rem;
border-radius: 5px;
box-shadow:
inset 0 1px 8px 0 rgb(0 0 0/10%),
inset 0 3px 4px 0 rgb(0 0 0 / 7%),
inset 0 3px 3px -2px rgb(0 0 0 / 6%);
background-color: #f8f8f8;
}
#app [type="range"] {
max-width: 400px;
width: 100%;
margin: 0 auto;
display: block;
}
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<div id="app">
<input type="range" min="60" max="400" v-model="h8" />
<div :style="{ height: `${h8}px` }">
<div >first div</div>
<div >
second div
<p v-for="n in 10" :key="n">Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
CodePudding user response:
I don't really get your goal and height/width relation.
But here is a working playground with something alike.
const { createApp, ref, onMounted } = Vue;
const App = {
setup() {
const mydiv = ref(null);
const wrapperHeight = ref(0);
const rangeValue = ref(50);
onMounted(() => {
console.log(`onMounted(): ${mydiv.value.offsetHeight}`);
wrapperHeight.value = mydiv.value.offsetHeight;
});
const updateHeight = (event) => {
console.log(`updateHeight(): ${event.target.value}`);
wrapperHeight.value = event.target.value;
}
return {mydiv, wrapperHeight, rangeValue, updateHeight }
}
}
const app = createApp(App)
app.mount('#app')
<div id="app">
<input
type="range"
min="10"
max="100"
v-model="rangeValue"
@change="updateHeight"
/><br/>
rangeValue: {{rangeValue}} <br/>
wrapperHeight: {{wrapperHeight}} <br/><br/>
<div :style="{ 'background-color': 'yellow', 'min-height': `${wrapperHeight}px` }">
<div ref="mydiv" style="{ 'float': 'bottom' }">My Div</div>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>