我正在研究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"><></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来处理它。我想念什么?
答案 0 :(得分:1)
首先,您设置样式的方法不起作用
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"><></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>