如何在 Vue 转换开始之前读取大小并移动隐藏元素?
How to read size and move hidden element before Vue transition starts on it?
如何读取维度并移动在 Vue 转换开始之前隐藏的 div?例如,用户单击一个按钮,我想移动一个隐藏的 div 以出现在带有淡入过渡的按钮下方。在转换开始之前,我需要能够读取尺寸并移动隐藏 div 的 top/left 位置。
假设我在 div 上使用 v-show="active"
,其中 active
是我的反应数据 属性 我想设置为 true 并能够移动过渡开始前的div。
这些我都试过了:
- 先移动 div,然后在 nextTick 上设置 active = true。
- 使用 javascript 钩子 beforeEnter 尝试在转换开始前移动 div。
- 使用 javascript 挂钩输入(和 'done' 回调)尝试在转换开始前移动 div。
- 在设置 active = true 之前立即用新位置更新 DOM 尝试了以上所有操作。 (换句话说,不是通过数据绑定,而是像
this.$refs.content.style.top = '500px'
那样直接设置元素样式属性,以避免在虚拟 DOM 上等待任何时间。)但是,理想情况下,我想在不直接接触DOM,但改用 nextTicks。两种方法都失败了。
- 尝试使用 hacky
transition: all .8ms ease-in, top 1ms, left 1ms
取得了一些成功。
- 首先尝试移动 div,然后在 setTimeout 中设置为活动状态,并已成功尝试。不过这不是正确的解决方案。
更新
感谢接受的答案,我能够看到我可以在 nextTick 上读取尺寸(此时 v-show 已打开显示)。然而,事实证明我需要将过渡全部设为 transition all .3s
,这会导致移动被包含在内。 DOM 将收集所有更改并将它们一起应用,这意味着它们会被集中到 Vue 稍后添加的转换中。最后的解决方案是我需要做动作,然后先触发 DOM 重绘,然后触发 v-show 打开。这是一个示例方法:
startTransition () {
this.$refs.content.offsetHeight // <-- Force DOM to repaint first.
this.isContentActive = true // <-- Turns on v-show.
},
使用 v-bind:style
移动您的 window 并且一切正常。
更新:要检查弹出窗口本身的大小,必须显示它,所以我使用 v-show
而不是 v-if
。我做的第一件事就是让它可见;在下一个刻度上,我可以测量它并放置它。
new Vue({
el: '.container',
data: {
top: 0,
left: 0,
width: 0,
show: false
},
methods: {
showFloater: function(evt) {
const t = evt.target;
this.show = true;
Vue.nextTick(() => {
const fEl = this.$el.querySelector('.floating');
this.top = t.offsetTop + 30;
this.left = t.offsetLeft;
this.width = fEl.offsetWidth;
setTimeout(() => this.show = false, 1000);
});
}
}
});
.container {
position: relative;
}
.floating {
border: thin solid black;
padding: 3em;
position: absolute;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div class="container">
<button @click="showFloater">Could go here</button>
<button @click="showFloater">Or here</button>
<transition name="fade">
<div v-show="show" class="floating" v-bind:style="{
top: top + 'px',
left: left + 'px'
}">
This window is {{width}}px wide.
</div>
</transition>
</div>
如何读取维度并移动在 Vue 转换开始之前隐藏的 div?例如,用户单击一个按钮,我想移动一个隐藏的 div 以出现在带有淡入过渡的按钮下方。在转换开始之前,我需要能够读取尺寸并移动隐藏 div 的 top/left 位置。
假设我在 div 上使用 v-show="active"
,其中 active
是我的反应数据 属性 我想设置为 true 并能够移动过渡开始前的div。
这些我都试过了:
- 先移动 div,然后在 nextTick 上设置 active = true。
- 使用 javascript 钩子 beforeEnter 尝试在转换开始前移动 div。
- 使用 javascript 挂钩输入(和 'done' 回调)尝试在转换开始前移动 div。
- 在设置 active = true 之前立即用新位置更新 DOM 尝试了以上所有操作。 (换句话说,不是通过数据绑定,而是像
this.$refs.content.style.top = '500px'
那样直接设置元素样式属性,以避免在虚拟 DOM 上等待任何时间。)但是,理想情况下,我想在不直接接触DOM,但改用 nextTicks。两种方法都失败了。 - 尝试使用 hacky
transition: all .8ms ease-in, top 1ms, left 1ms
取得了一些成功。 - 首先尝试移动 div,然后在 setTimeout 中设置为活动状态,并已成功尝试。不过这不是正确的解决方案。
更新
感谢接受的答案,我能够看到我可以在 nextTick 上读取尺寸(此时 v-show 已打开显示)。然而,事实证明我需要将过渡全部设为 transition all .3s
,这会导致移动被包含在内。 DOM 将收集所有更改并将它们一起应用,这意味着它们会被集中到 Vue 稍后添加的转换中。最后的解决方案是我需要做动作,然后先触发 DOM 重绘,然后触发 v-show 打开。这是一个示例方法:
startTransition () {
this.$refs.content.offsetHeight // <-- Force DOM to repaint first.
this.isContentActive = true // <-- Turns on v-show.
},
使用 v-bind:style
移动您的 window 并且一切正常。
更新:要检查弹出窗口本身的大小,必须显示它,所以我使用 v-show
而不是 v-if
。我做的第一件事就是让它可见;在下一个刻度上,我可以测量它并放置它。
new Vue({
el: '.container',
data: {
top: 0,
left: 0,
width: 0,
show: false
},
methods: {
showFloater: function(evt) {
const t = evt.target;
this.show = true;
Vue.nextTick(() => {
const fEl = this.$el.querySelector('.floating');
this.top = t.offsetTop + 30;
this.left = t.offsetLeft;
this.width = fEl.offsetWidth;
setTimeout(() => this.show = false, 1000);
});
}
}
});
.container {
position: relative;
}
.floating {
border: thin solid black;
padding: 3em;
position: absolute;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div class="container">
<button @click="showFloater">Could go here</button>
<button @click="showFloater">Or here</button>
<transition name="fade">
<div v-show="show" class="floating" v-bind:style="{
top: top + 'px',
left: left + 'px'
}">
This window is {{width}}px wide.
</div>
</transition>
</div>