2.7. 트랜지션
- CSS 속성값이 서서히 변경되는것. (마치 면접의 신 fade 효과처럼)
- <transition> 태그를 이용하여 효과 적용
- v-if, v-show, 동적 컴포넌트, 컴포넌트 루트 노트 상황에서 모든 태그 및 컴포넌트 트랜지션 추가 가능
- 참조 : https://kr.vuejs.org/v2/guide/transitions.html
2.7.1. 트랜지션 클래스
- CSS 에서 사용되는 트랜지션 클래스
- 해당 클래스별로 CSS를 각각 적용할 수 있음.
- <transition> 태그의 name 속성값-클래스명 조합으로 css 파일에 정의 해야 함
- 예 : 이름이 test인 경우, CSS 적용을 위해서는, .test-enter { 효과 }
- v 는 Transition 태그의 name 속성값으로 치환됨. 만일, name 속성값 없이 <transition> 태그만 사용한다면, v 로 작성해야함
2.7.1.1. v-enter
- enter의 시작 상태
- <transition> 태그가 삽입되기 전에 적용되며, 한 프레임 후 제거됨
2.7.1.2. v-enter-active
- enter의 활성 및 종료상태
- 삽입되기 전에 적용
- 트랜지션 / 애니메이션이 완료되면 제거됨
2.7.1.3. v-enter-to
- 진입상태의 끝에서 실행됨
- 삽입된 후, 트랜지션/애니메이션이 끝나면 제거됨
2.7.1.4. v-leave
- leave를 위한 시작상태
- leave가 트리거 될때 적용되고 한 프레임 후 제거됨
2.7.1.5. v-leave-active
- leave 활성 및 종료 상태
- leave가 트리거 될때 적용되고, 트랜지션/애니메이션 완료시 제거됨
2.7.1.6. v-leave-to
- leave 끝에서 실행
- leave가 트리거 되고 트랜지션/애니메이션 완료시 동작하며 한 프레임 후 제거됨
2.7.1.7. v-move
- 배열의 아이템들이 위치변경 할때 사용하는 클래스
- 주로 v-for과 함께 쓴다. 2.7.9. 참조
- 예
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="flip-list-demo" class="demo">
<button v-on:click="shuffle">Shuffle</button>
<transition-group name="flip-list" tag="ul">
<li v-for="item in items" v-bind:key="item">
{{ item }}
</li>
</transition-group>
</div>
new Vue({
el: '#flip-list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9]
},
methods: {
shuffle: function () {
this.items = _.shuffle(this.items)
}
}
})
//css의 v-move 클래스
.flip-list-move {
transition: transform 1s;
}
- 전체 예
//css 파일내용
//fade 는 하단부 transition 태그의 name에 설정한 이름
// transition 태그로 싸여진 항목이 사라지거나 보여질때 적용
// transition: opacity.. 에서 transition은 fade를 의미함
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
===================
<html>
....
<header>
<link href="css 파일위치" rel="stylesheet" type="text/css">
</header>
...
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#demo',
data: {
show: true
}
})
2.7.1. 트랜지션 효과
- css 의 각 트랜지션 클래스에서 transition: 설정값 으로 사용함
- fade 효과를 트랜지션 효과라고 함
2.7.2. 애니메이션 효과
- css 의 각 트랜지션 클래스에서 animation: 설정값 으로 사용함
css 파일 구성
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
2.7.3. 사용자 지정 트랜지션 클래스
- 원본 클래스를 오버라이드
- css 에서 하지 않고 html 의 transition 태그의 속성으로 설정함
- 클래스명="css 에 정의된 동작 방식" 으로 사용
- 기존 css 라이브러리와 결합하기 위해 사용
- enter-class
- enter-active-class
- enter-to-class
- leave-class
- leave-active-class
- leave-to-class
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="example-3">
<button @click="show = !show">
Toggle render
</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada" //animated tada 는 위의 link에 적용된 css 파일에서 효과를 사용하는 방식임. tada 효과를 사용하려면 class값에 animated 효과명
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hello</p>
</transition>
</div>
2.7.4. 트랜지션 지속시간 지정
- transition 태그의 속성으로 :duration="시간(mil)" 지정
- enter, leave 별로 지속시간 지정 가능
- :duration ="{enter:500, leave : 800}"
2.7.5. 트랜지션 발생시, JavaScript 함수 호출
- transition 태그의 속성에서 설정 가능
- v-on:트랜지션클래스명(예 : enter)="javascript 함수명"
- 호출된 javascript 함수 내부에 작업 완료후 함수 리턴을 대신해 done() 코드 작성 필요.
- CSS 에서 효과를 적용할 수도 있으므로, CSS skip 속성값을 설정해야 함
- v-bind:css="false"
- 예
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
<button @click="show = !show">
Toggle
</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-if="show">
Demo
</p>
</transition>
</div>
new Vue({
el: '#example-4',
data: {
show: false
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
},
enter: function (el, done) {
Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
Velocity(el, { fontSize: '1em' }, { complete: done })
},
leave: function (el, done) {
Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
Velocity(el, {
rotateZ: '45deg',
translateY: '30px',
translateX: '30px',
opacity: 0
}, { complete: done })
}
}
})
2.7.6. appear 속성
- 최초 렌더링 시 트랜지션을 적용할 때 사용
- transition 태그에 appear 속성을 사용
2.7.6.1. CSS 연동
<transition
appear
appear-class="custom-appear-class"
appear-to-class="custom-appear-to-class" (2.1.8+)
appear-active-class="custom-appear-active-class"
>
<!-- ... -->
</transition>
// css 에서는
.custom-appear-class {
...
} 이런식으로 작성? 예제에 css는 안나와 있음
2.7.6.2. javascript 연동
<div id="test"
<transition
appear
v-on:before-appear="customBeforeAppearHook"
v-on:appear="customAppearHook"
v-on:after-appear="customAfterAppearHook"
v-on:appear-cancelled="customAppearCancelledHook"
>
<!-- ... -->
</transition>
=== javascript에서
new Vue({
el:'#test',
....
methods:
{
customBeforeAppearHook : function(el,done)
{ ... }
}
})
2.7.7. 트랜지션 태그 안에 동일한 태그가 2개 이상 있을경우
- 예 : <transition> <button...> <button...> </transition> 일 경우.
- 각 중복되는 이름의 태그에 고유한 key 값을 배정해줘야 함.
<transition>
<button v-if="isEditing" key="save">
Save
</button>
<button v-else key="edit">
Edit
</button>
</transition>
이는 아래로 대체 가능함
<transition>
<button v-bind:key="isEditing">
{{ isEditing ? 'Save' : 'Edit' }}
</button>
</transition>
2.7.7.1. 동일 태그 3개 이상시
<transition>
<button v-if="docState === 'saved'" key="saved">
Edit
</button>
<button v-if="docState === 'edited'" key="edited">
Save
</button>
<button v-if="docState === 'editing'" key="editing">
Cancel
</button>
</transition>
또는
<transition>
<button v-bind:key="docState">
{{ buttonMessage }}
</button>
</transition>
new Vue({
...
computed: {
buttonMessage: function () {
switch (this.docState) {
case 'saved': return 'Edit'
case 'edited': return 'Save'
case 'editing': return 'Cancel'
}
}
}
})
2.7.7.2. mode 속성
- enter, leave가 동시에 트랜지션이 됨
- 따라서, 같은 위치의 ui가 겹쳐 보일 수 있음
- 한 ui는 사라지고, 다른 ui는 보여질 경우, 잠깐동안 2개가 모두 렌더링 됨
2.7.7.2.1. in-out
- 처음에는 enter가 트랜지션 되고, 완료 후 leave가 트랜지션
2.7.7.2.2. out-in
- 처음에는 leave가 드랜지션 되고, 완료 후 enter가 트랜지션
<transition name="fade" mode="out-in">
<!-- ... the buttons ... -->
</transition>
2.7.8. 컴포넌트 간 트랜지션
- 동적 컴포넌트 전환시 트랜지션
- key 속성을 설정할 필요 없음
- transition 태그 안에 component 태그에서, is를 사용한 동적 컴포넌트 할당을 이용
- 동적 컴포넌트는 2.3.10. 동적 컴포넌트 (내부 컴포넌트) 참조
- 예
//css
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
//html
<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
//javascript
new Vue({
el: '#transition-components-demo',
data: {
view: 'v-a'
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
})
2.7.9. v-for 를 이용한 transition
- <transition-group> 태그를 사용
- 실제 렌더링 될 태그는 <transition-group> 태그 안에 구현해야 함. (v-for 이용)
- <transition-group> 의 tag 속성으로, 렌더링될 자식 태그들의 부모태그를 지정할 수 있음
- 자식 태그에는 v-bind:key 속성을 반드시 사용해야함
- 예
<div id="list-demo">
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group name="list" tag="p"> // 자식 태그인 span의 부모 태그로 p를 지정
<span v-for="item in items" v-bind:key="item" class="list-item"> //v-bind:key 지정 필요. span이 실제 렌더링 되는 자식임
{{ item }}
</span>
</transition-group>
</div>
new Vue({
el: '#list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
})
//css
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
2.7.9.1. CSS 대신 Javascript 연동
- v-on:클래스명="javascript 함수명"
- 2.7.5. 참조
- 예 : 필터 효과 예제
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="staggered-list-demo">
<input v-model="query">
<transition-group
name="staggered-fade"
tag="ul"
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<li
v-for="(item, index) in computedList"
v-bind:key="item.msg"
v-bind:data-index="index"
>{{ item.msg }}</li>
</transition-group>
</div>
new Vue({
el: '#staggered-list-demo',
data: {
query: '',
list: [
{ msg: 'Bruce Lee' },
{ msg: 'Jackie Chan' },
{ msg: 'Chuck Norris' },
{ msg: 'Jet Li' },
{ msg: 'Kung Fury' }
]
},
computed: {
computedList: function () {
var vm = this
return this.list.filter(function (item) {
return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
})
}
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
el.style.height = 0
},
enter: function (el, done) {
var delay = el.dataset.index * 150
setTimeout(function () {
Velocity(
el,
{ opacity: 1, height: '1.6em' },
{ complete: done }
)
}, delay)
},
leave: function (el, done) {
var delay = el.dataset.index * 150
setTimeout(function () {
Velocity(
el,
{ opacity: 0, height: 0 },
{ complete: done }
)
}, delay)
}
}
})
2.7.10. 트랜지션 재사용
- <transition> 태그 또는 <transition-group> 태그를 html에 작성하지 않고, 컴포넌트의 template에 정의
- 예
Vue.component('my-special-transition', {
template: '
<transition
name="very-special-transition"
mode="out-in"
v-on:before-enter="beforeEnter"
v-on:after-enter="afterEnter"
>
<slot></slot> // slot은 2.3.9. 참조. html에서 작성한 태그 내용을 이곳에 보여줌 (동일레벨)
</transition>',
methods: {
beforeEnter: function (el) {
// ...
},
afterEnter: function (el) {
// ...
}
}
})
2.7.11. 동적 트랜지션
- <transition> 태그 또는 <transition-group> 태그의 name 속성에 v-bind를 이용
- 뷰 인스턴스의 맴버변수를 바인딩 함 (v-bind:name="vue인스턴스 변수명")
- css 에 각 변수이름-트랜지션 클래스 별 동작할 코드를 추가
- 상황에 맞게 맴버변수 이름을 변경하면, 동작하는 css 함수가 달라지므로, 효과가 동적으로 변경된다.
- 예 (css 파일 사용치 않고 javascript에서 처리하는 방식
<div id="test">
<transition
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:name="transtion-name"
>
.....
</div>
new Vue({
el:'#test'
data : {
transtionName:''
}
methods :
{
beforeEnter: function(el) {
if(transtionName == 'a')
...
else
...
}
...
}
})
2.8. Mixin
- 컴포넌트 및 뷰 인스턴스의 공통 기능 및 옵션 객체 구현, 각 컴포넌트에서 이를 상속받아 공통으로 사용하기 위한 것
- 예
// 공통기능으로 사용할 객체 구현
var myMixin = {
created: function () { //생성자
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// mixin을 사용할 컴포넌트 정의
// Vue.extend : 위의 공통 기능으로 사용할 객체 구현과 비슷한 개념
// new Component를 통해 미리 정의된 옵션등이 있는 객체를 생성한다.
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"
또는,
new Vue({
mixins: [mixin],
created: function () {
console.log('component hook called')
}
})
// mixins 옵션을 통해 직접 배정 할 수도 있음.
2.8.1. 옵션 병합 또는 대체
- 옵션 이름이 동일할 경우 발생
- hook 의 경우, 병합이 되어, 동일한 옵션이 다 호출됨.
- 순서는 mixin 으로 사용하는 객체 -> mixin객체를 mixins 옵션을 통해 설정한 객체
var mixin = {
created: function () {
console.log('mixin hook called')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('component hook called')
}
})
// => "mixin hook called"
// => "component hook called"
- 그외 옵션은 mixin 객체를 사용하는 (mixins 옵션을 통해) 옵션으로 대체됨.
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
2.8.2. 전역 mixin
- 이후에 생성하는 모든 vue 인스턴스에 적용되므로 권장하지 않음
- Vue.mixin({ }) 을 통해 설정
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
myOption: 'hello!'
})
// => "hello!"
2.9. 사용자 지정 디렉티브
- Vue.directive('명칭', { }) 혹은 directives: 를 통해 정의 가능
- 사용시, 기존 다른 디렉티브 (예 : v-on) 처럼 사용가능
- <태그명 v-사용자지정명>
- 예
// 전역 사용자 정의 디렉티브 v-focus 등록
Vue.directive('focus', {
// 바인딩 된 엘리먼트가 DOM에 삽입되었을 때...
inserted: function (el) {
// 엘리먼트에 포커스를 줍니다
el.focus()
}
})
// 지역 사용자 정의
new Vue({ 혹은 Vue.compoment('명칭'{
....
directives: {
focus: {
// 디렉티브 정의
inserted: function (el) {
el.focus()
}
}
}
})
<태그명 v-focus> 으로 사용
2.9.1. 훅 함수
- 사용자 정의 디렉티브에서 특정 상태일때 동작하기 위함
2.9.1.1. bind
- 속성에 처음 바인딩 될때 한번만 호출됨. 일회성
2.9.1.2. inserted
- 바인딩된 html태그가 삽입되었을때
2.9.1.3. update
- 포함하는 컴포넌트가 업데이트 된 후 호출됨. 불필요한 업데이트가 있을 수 있음
2.9.1.4. componentUpdated
- 컴포넌트 및 그 자식들이 업데이트 된 후 호출
2.9.1.5. unbind
- 언바인딩된 경우 한번 호출
2.9.2. 훅 함수 매개변수
- 오브젝트 맴버변수
2.9.2.1. el
- html 태그 오브젝트
- 이를 통해 html태그 접근, 사용 가능
2.9.2.2. binding
- binding.변수명 으로 접근하여 사용
2.9.2.2.1. name
- 디렉티브 이름으로 v- 프리픽스 없음
2.9.2.2.2. value
- 디렉티브에서 전달받은 값
- 예 : v-value:변수명="1+1" 이면 2를 전달받음
2.9.2.2.3. oldvalue
- update, componentUpdate에서만 사용가능. 변경전 값
2.9.2.2.4. expression
- 표현식 문자열
- 예 : v-value:변수명="1+1" 이면, "1+1"을 전달받음
2.9.2.2.5. arg
- 디렉티브 전달인자. 있는경우에만 존재함
- 예 : v-value:변수명="1+1" 이면, "변수명" 을 전달받음
2.9.2.2.6. modifiers
- 디렉티브 수식어 객체, 있는 경우에만 존재
- 예 : v-value:변수명.A.B 이면, {A:true,b:true} 를 전달받음
2.9.2.3. vnode
- Vue 컴파일러가 만든 가상노드
2.9.2.4. oldVnode
- 이전 가상노드. update, componentUpdate 에서만 사용 가능
- 예
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
//
name : "demo"
value : "hello!"
expression : "message"
arguemnt: "foo"
modifiers : {"a":true,"b":true}
2.9.3. 객체 리터럴
- 디렉티브에 여러값이 필요할경우 javascript 양식을 활용할 수 있음.
- 예
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
'FrontEnd' 카테고리의 다른 글
HTML5 상에서 비디오, 오디오, 음성녹음 테스트 (0) | 2022.03.25 |
---|---|
부트스트랩 (0) | 2022.03.25 |
vue js 내용정리 (2.3.9 컴포넌트-slot태그 ~ 2.6. 사용자 정의 이벤트) (0) | 2022.03.25 |
vue js 내용정리 (1. 설치 ~ 2.3.8. 컴포넌트 - 이벤트 발생시 사용자 정의함수 호출) (0) | 2022.03.25 |
FrontEnd 개발 관련 내용정리 (0) | 2022.03.25 |