gpt4 book ai didi

javascript - Vue 过渡的动态样式

转载 作者:行者123 更新时间:2023-11-28 14:19:16 25 4
gpt4 key购买 nike

我正在开发一个 VueJS 侧边栏组件。它应该允许父级指定一个宽度并呈现一个将侧边栏滑入和滑出的切换。像这样:

<template>
<div class="sidebarContainer">
<transition
name="slide"
>
<div v-if="isOpen" class="sidebar" :style="{ width }">
<slot/>
</div>
</transition>
<div class="toggle" @click="isOpen = !isOpen">&lt;&gt;</div>
</div>
</template>
export default {
props: {
'width': {
default: '20em',
}
},
data() {
return {
isOpen: true,
};
},
};
<style scoped>
.slide-enter-active, .slide-leave-active {
transition: all 0.6s;
}
.slide-enter, .slide-leave-to {
margin-left: -20em;
}
</style>

工作 codepen .它完全按照我想要的方式工作,除了过渡的宽度(如 .slide-enter, .slide-leave-to 样式中指定的那样)是硬编码的,而不是响应组件的 width 属性。如果您设置 width=30em,那么过渡会很不稳定。

我怀疑我可能需要使用 transition hooks ,但我似乎无法让它发挥作用。我试过这个:

beforeEnter(el) {
el.style = {
transition: 'all 0.6s',
marginLeft: '-20em',
};
},
enter(el, done) {
el.style.marginLeft = '0';
done();
},
beforeLeave(el) {
el.style = {
transition: 'all 0.6s',
marginLeft: '0',
};
},
leave(el, done) {
el.style.marginLeft = '-20em';
done();
},

参见 modified codepen .您可以看到侧边栏仍在移动,但没有动画。我认为也许将 done 回调包装在 setTimeout 中以允许完成转换会有所帮助,但事实并非如此。

我知道我可以使用像 Velocity 这样的库,或者我可以手动编写动画代码,但似乎应该有一种方法让 CSS 来处理它。我错过了什么?

最佳答案

首先,您设置样式的方式行不通

el.style = {
transition: 'all 0.6s',
marginLeft: '-20em',
};

我只是将 transition: 'all 0.6s' 移动到 css 并像这样设置样式

el.style.marginLeft = '-20em';

其次, enter 事件在 beforeEnter 事件之后很快被调用,因此浏览器无法检测到两种状态之间的变化。所以我将 enter 事件包装到 setTimeout 中以制作触发转换的技巧。

第三, done 回调在这种情况下不是必需的。它仅在纯 js 转换中需要。我们正在使用混合的 CSS 和 JS

Vue.component('app', {
template: `<div class="app">
<sidebar>sidebar content</sidebar>
<div class="main">Hello, VueJS!</div>
</div>`
});

Vue.component('sidebar', {
template: ` <div class="sidebarContainer">
<transition
name="slide"
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
>
<div v-if="isOpen" class="sidebar" :style="{ width }">
<slot/>
</div>
</transition>
<div class="toggle" @click="isOpen = !isOpen">&lt;&gt;</div>
</div>`,
props: {
'width': {
default: '20em',
}
},
data() {
return {
isOpen: true,
};
},
methods: {
beforeEnter(el) {
el.style.marginLeft = '-20em';
},
enter(el, done) {
// Wait a tick here, so browser can detect style change and tigger transition
setTimeout(() => {
el.style.marginLeft = '0';
}, 0)
},
leave(el, done) {
el.style.marginLeft = '-20em';
},
},
});

new Vue({
el: '#app',
template: '<app/>'
});
html,
body,
.app {
height: 100%;
}

.app {
display: flex;
}

.main {
flex-grow: 1;
background: red;
}

.sidebarContainer {
display: flex;
}

.sidebar {
flex-grow: 1;
padding: 0.5em;
background: blue;
transition: all 0.6s;
}

.toggle {
margin: 0.5em;
}
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>

关于javascript - Vue 过渡的动态样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55409337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com