[英](Vue3) Problems syncing DOM element heights change using v-model and v-on
我正在创建一个网站,其中使用v-model
将范围 slider 的值绑定到名为rangeValue
的属性。 该代码类似于以下内容:
<template>
...
<input
type="range"
min="10"
max="50"
class="slider"
v-model="rangeValue"
@change="updateHeight()"
/>
<div class="otherDiv" :style="{ height: `${wrapperHeight}px`></>
<div
class="firstDiv"
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>
我想让 otherDiv 的高度与otherDiv
的高度相匹配,其高度根据范围firstDiv
的变化而变化。 我的问题是firstDiv
的高度与范围 slider 的变化同时更新,而otherDiv
的高度总是滞后一个“滴答”,更新到firstDiv
的值在它被范围 slider 改变之前,而不是之后。 我尝试了各种使用nextTick
的实现都无济于事。
简而言之,我需要:
firstDiv
的大小,获取它在 DOM 中的高度,调整otherDiv
的大小我希望这是有道理的。 欢迎任何指点,谢谢!
这是你想要达到的目标吗?
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/vue@3.2.45/dist/vue.global.prod.js"></script> <div id="app"> <input type="range" min="60" max="400" v-model="h8" /> <div class="grid":style="{ height: `${h8}px` }"> <div class="firstDiv">first div</div> <div class="secondDiv"> second div <p v-for="n in 10":key="n">Lorem ipsum dolor sit amet.</p> </div> </div> </div>
您不仅限于拥有共同的父母(这似乎更适合您的情况)。
您可以同步完全不相关的组件,即使在单独的应用程序中也是如此(参见下面的示例)。 您所需要的只是一个单一的事实来源。 我使用了反应式 object 但更常见和有用的实现是使用实际商店(pinia,vuex):
const { createApp, toRefs, reactive, computed } = Vue const store = reactive({ h8: 85 }); ['input-app', 'app-1', 'app-2'].forEach(app => createApp({ setup: () => toRefs(store) }).mount(`#${app}`))
#app-1, #app-2 { padding: 0.5rem; }.grid { display: grid; grid-template-areas: "input input" "app-1 app-2"; grid-template-rows: auto 1fr; grid-template-columns: 1fr 1fr; min-height: 100vh; } body { margin: 0 } #input-app { grid-area: input; } #app-1 { grid-area: app-1; } #app-2 { grid-area: app-2; align-self: end; }.firstDiv, .secondDiv { 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; } [type="range"] { max-width: 400px; width: 100%; margin: 0 auto 1rem; display: block; }
<script src="https://unpkg.com/vue@3.2.45/dist/vue.global.prod.js"></script> <div class="grid"> <div id="input-app"> <input type="range" min="60" max="500" v-model="h8" /> </div> <div id="app-1"> <div class="firstDiv":style="{ height: `${h8}px` }"> first div </div> </div> <div id="app-2"> <div class="secondDiv":style="{ height: `${h8}px` }"> second div <p v-for="n in 10":key="n">Lorem ipsum dolor sit amet.</p> </div> </div> </div>
我真的不明白你的目标和高度/宽度关系。
但这里有一个类似的工作操场。
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" class="slider" 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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.