Vue - 动画与使用 Click 的普通 javascript 实现的区别
Vue - animation difference with the plain javascript implementation using Click
我正在关注this tutorial制作动画。
它仅使用 html、css 和普通的 javascript.
这就是我所期待的,展开和折叠都很流畅。
html
HTML CSS JSResult Skip Results Iframe
EDIT ON
<div class="box">
<div class="top">
<h1>Lorem Ipsum</h1>
</div>
<p class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida.
</p>
<button><i class="arrow"></i></button>
</div>
css
@import url("https://fonts.googleapis.com/css?family=Dosis:200,400&display=swap");
body {
color: #000;
background: #e2e2e2;
font-family: "Dosis", sans-serif;
}
/* Box */
.box {
margin: 22px auto;
width: 320px;
padding: 12px 32px 64px;
max-height: 162px;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}
.box.open {
max-height: 100rem;
transition: max-height 0.3s cubic-bezier(0.9, 0, 0.8, 0.2);
}
/* Text */
@keyframes open {
from {
line-clamp: 3;
-webkit-line-clamp: 3;
}
to {
line-clamp: initial;
-webkit-line-clamp: initial;
}
}
@keyframes close {
from {
line-clamp: initial;
-webkit-line-clamp: initial;
}
to {
line-clamp: 3;
-webkit-line-clamp: 3;
}
}
.text {
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
margin: 12px 0;
animation: close 0.1s linear 0.1s forwards;
}
.open .text {
animation: open 0.1s linear 0s forwards;
}
/* Irrelavant css... */
.arrow {
border: solid #000;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 4px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.open .arrow {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
margin-top: 5px;
}
button {
background: transparent;
border: 2px solid #000;
height: 32px;
width: 32px;
border-radius: 50%;
outline: none;
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}
javascript
const box = document.querySelector('.box');
let isOpen = false;
document.querySelector('button').addEventListener('click', () => {
isOpen = !isOpen;
isOpen ? box.classList.add('open') : box.classList.remove('open')
});
然而,当我尝试使用 VueJs
和完全相同的 css
应用它时,动画与我的预期不同,如下所示:
App.vue
<template>
<div id="app">
<div :class="{ box, open: showMore }">
<div class="top">
<h1>Show More</h1>
</div>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum. Curabitur pretium tincidunt lacus. Nulla
gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros
bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in
mauris eu nibh euismod gravida.
</p>
<button @click="handleShowMore()"><i class="arrow"></i></button>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
showMore: false,
};
},
methods: {
handleShowMore() {
this.showMore = !this.showMore;
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
/* Box */
.box {
margin: 22px auto;
width: 320px;
padding: 12px 32px 64px;
max-height: 162px;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}
.box.open {
max-height: 100rem;
transition: max-height 0.3s cubic-bezier(0.9, 0, 0.8, 0.2);
}
/* Text */
@keyframes open {
from {
line-clamp: 3;
-webkit-line-clamp: 3;
}
to {
line-clamp: initial;
-webkit-line-clamp: initial;
}
}
@keyframes close {
from {
line-clamp: initial;
-webkit-line-clamp: initial;
}
to {
line-clamp: 3;
-webkit-line-clamp: 3;
}
}
.text {
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
margin: 12px 0;
animation: close 0.1s linear 0.1s forwards;
}
.open .text {
animation: open 0.1s linear 0s forwards;
}
/* Irrelavant css... */
.arrow {
border: solid #000;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 4px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.open .arrow {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
margin-top: 5px;
}
button {
background: transparent;
border: 2px solid #000;
height: 32px;
width: 32px;
border-radius: 50%;
outline: none;
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}
</style>
这两个实现有什么区别?如何解决?
Codesandbox
https://codesandbox.io/s/serverless-surf-0t0nb?file=/src/App.vue:0-2814
您的 vue 组件存在语法错误。它混淆了你的 class 名称和应用程序 属性
[Vue warn]: Property or method "box" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
从 :class
绑定中删除 box
class。
<div class="box" :class="{open: showMore }">
这将修复您的流畅动画
我正在关注this tutorial制作动画。
它仅使用 html、css 和普通的 javascript.
这就是我所期待的,展开和折叠都很流畅。
html
HTML CSS JSResult Skip Results Iframe
EDIT ON
<div class="box">
<div class="top">
<h1>Lorem Ipsum</h1>
</div>
<p class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida.
</p>
<button><i class="arrow"></i></button>
</div>
css
@import url("https://fonts.googleapis.com/css?family=Dosis:200,400&display=swap");
body {
color: #000;
background: #e2e2e2;
font-family: "Dosis", sans-serif;
}
/* Box */
.box {
margin: 22px auto;
width: 320px;
padding: 12px 32px 64px;
max-height: 162px;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}
.box.open {
max-height: 100rem;
transition: max-height 0.3s cubic-bezier(0.9, 0, 0.8, 0.2);
}
/* Text */
@keyframes open {
from {
line-clamp: 3;
-webkit-line-clamp: 3;
}
to {
line-clamp: initial;
-webkit-line-clamp: initial;
}
}
@keyframes close {
from {
line-clamp: initial;
-webkit-line-clamp: initial;
}
to {
line-clamp: 3;
-webkit-line-clamp: 3;
}
}
.text {
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
margin: 12px 0;
animation: close 0.1s linear 0.1s forwards;
}
.open .text {
animation: open 0.1s linear 0s forwards;
}
/* Irrelavant css... */
.arrow {
border: solid #000;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 4px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.open .arrow {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
margin-top: 5px;
}
button {
background: transparent;
border: 2px solid #000;
height: 32px;
width: 32px;
border-radius: 50%;
outline: none;
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}
javascript
const box = document.querySelector('.box');
let isOpen = false;
document.querySelector('button').addEventListener('click', () => {
isOpen = !isOpen;
isOpen ? box.classList.add('open') : box.classList.remove('open')
});
然而,当我尝试使用 VueJs
和完全相同的 css
应用它时,动画与我的预期不同,如下所示:
App.vue
<template>
<div id="app">
<div :class="{ box, open: showMore }">
<div class="top">
<h1>Show More</h1>
</div>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum. Curabitur pretium tincidunt lacus. Nulla
gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros
bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in
mauris eu nibh euismod gravida.
</p>
<button @click="handleShowMore()"><i class="arrow"></i></button>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
showMore: false,
};
},
methods: {
handleShowMore() {
this.showMore = !this.showMore;
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
/* Box */
.box {
margin: 22px auto;
width: 320px;
padding: 12px 32px 64px;
max-height: 162px;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}
.box.open {
max-height: 100rem;
transition: max-height 0.3s cubic-bezier(0.9, 0, 0.8, 0.2);
}
/* Text */
@keyframes open {
from {
line-clamp: 3;
-webkit-line-clamp: 3;
}
to {
line-clamp: initial;
-webkit-line-clamp: initial;
}
}
@keyframes close {
from {
line-clamp: initial;
-webkit-line-clamp: initial;
}
to {
line-clamp: 3;
-webkit-line-clamp: 3;
}
}
.text {
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
margin: 12px 0;
animation: close 0.1s linear 0.1s forwards;
}
.open .text {
animation: open 0.1s linear 0s forwards;
}
/* Irrelavant css... */
.arrow {
border: solid #000;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 4px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.open .arrow {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
margin-top: 5px;
}
button {
background: transparent;
border: 2px solid #000;
height: 32px;
width: 32px;
border-radius: 50%;
outline: none;
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}
</style>
这两个实现有什么区别?如何解决?
Codesandbox
https://codesandbox.io/s/serverless-surf-0t0nb?file=/src/App.vue:0-2814
您的 vue 组件存在语法错误。它混淆了你的 class 名称和应用程序 属性
[Vue warn]: Property or method "box" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
从 :class
绑定中删除 box
class。
<div class="box" :class="{open: showMore }">
这将修复您的流畅动画