簡體   English   中英

(Vue3) 使用 v-model 和 v-on 同步 DOM 元素高度變化的問題

[英](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的實現都無濟於事。

簡而言之,我需要:

  1. 更新范圍 slider
  2. 調整firstDiv的大小,獲取它在 DOM 中的高度,調整otherDiv的大小
  3. 重新繪制 DOM(因此兩者同時調整大小)。

我希望這是有道理的。 歡迎任何指點,謝謝!

這是你想要達到的目標嗎?

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM