Bleeding edge

Vue 정리 - 수정중... 본문

Javascript/Vue

Vue 정리 - 수정중...

codevil 2022. 6. 16. 18:06

Vue.js 맛보기


간단한 템플릿 구문을 사용하여 DOM에서 데이터를 선언적으로 렌더링 할 수 있다.

<template>
    <div v-if="show" id="app">
        {{message}} //message output
        <span v-bind:title='message'>
        이 위에 마우스를 올리면 동적으로 바인딩 된 title을 볼 수 있습니다
        </span>
        <div v-for="count in countdown">
        	{{count.text}}
        </div>
        <button v-on:click="reverseMessage">
        <!--<button @click="reverseMessage">-->
        	메시지 뒤집기
        </button>
    </div>
    <div v-else-if="showifelse">
    	Show 가 flase이고, showifelse가 ture인 경우
    </div>
    <div v-else>
    	show false, showifelse flase
    </div>
</template>
<script>
export default{
  name:'HelloWorld',
  data(){
    return {
        messgae: '메시지입니다',
        show:true,
        showifelse:true,
        countdown :[
            {text : 1},
            {text : 2},
            {text : 3}
            ]
        }
  },
  methods:{
    alertit : function(){
        this.message = this.message.split('').reverse().join('')
    }
  }
}
</script>
<template>
    <div>
        {{message}}
        <input type="text" v-model="message">
    </div>
</template>

<script>
export default {
    name:'HelloWorld',
    data(){
        return{
            messgae:'안녕하세요 Vue'
        }
    }
}
</script>

v-bind 속성은 디렉티브라고 입니다. v- 접두어가 붙은것은 DOM에 특수한 반응형 동작을 합니다.

v-if는 해당 selector가 표시 될 지 말지 여부를 정할 수 있습니다.(v-if-else, v-else와 같이 사용 가능하다)

v-for는 countdown에 있는 component만큼 반복합니다.

v-on 디렉티브를 이용하여 메서드를 호출하는 이벤트를 추가할 수 있습니다

v-model 디렉티브를 이용하여 양식에 대한 입력과 앱상태를 양방향으로 바인딩 할 수 있습니다

v-once 디렉티브는 업데이트 되어도 수정하지 않습니다


1. v-bind:title 같은경우, title="message"의 message가 변하거나

2. if의 조건인 show가 바뀌거나.

3. countdown에 push가 되서 값이 추가되면 

동적으로 값들이 변한다.


이때 주의해야할 것은  인스턴스가 생성될 때 존재한 것들만 반응형이다.

Vue의 디자인?


Vue는 model, view modelview 즉 MVVM패턴의 디자인으로부터 영감을 받고 만들어 졌습니다.

Component를 이용한 작성법


컴포넌트는 미리 정의된 옵션을 가진 Vue 인스턴스입니다. 

예문)

//app.vue
<template>
    <div id="app">
        <HelloWorld
            v-for="todoItem in todos"
            v-bind:todo="todoItem"
            v-bind:key="todoItem.id"
        />
    </div>
</template>
<script>
    import HelloWorld from "./components/HelloWorld"
    export default{
        name:'App',
        components:{
            HelloWorld,
        },
        data(){
            return{
                todos:[
                    {id:0, name:'사과'}.
                    {id:1, name:'망고'}
                ]
            }
        }
    }    

</script>
//HelloWorld.vue
<template>
  <div class="hello">
    <h4>{{todo.name}}</h4>
  </div>
</template>

<script>
export default{
    name:'HelloWorld',
    props:['todo'],
    // components:{
    //     HelloWorld,
    // },
    data(){
        return{
            message:'Hello'
        }
    }
}
</script>

app.vue에서 todos에 있는 값 1개를 todoItem이라하고 이를 v-bind:todo="todoItem" todo라는 변수로 HelloWorld에 대입을한다.

HelloWorld.vue에서는, {{todo.name}}으로 호출한다.

여기서 <HelloWorld/>가 컴포넌트이다!

이때, Object.freeze(messge)와 같은 기능을 사용하면, message는 수정할 수 없게 바뀐다

 

Vue.js 인스턴스 만들기

//관례적으로 Vue 인스턴스를 참조하기 위해 종종 vm을 사용합니다.
//Vue인스턴스를 생성할 때는 options객체를 전달해야 합니다
var vm = new vue{{
	//option list
    //data
    //props
    //computed
    //methods
    //watch:
}}

 

인스턴스 라이프사이클 훅


Vue 인스턴스는 생성될 때 일련의 초기화 단계를 거치며, 이 단계에 따라 호출될 다른 훅이 있습니다.

mounted, updated, destroyed

<script>
    export default{
        name:'HelloWorld',
        data(){
            return{
                messgae:'안녕하세요'
            }
        },
        created(){
            console.log('created')
        },
        mounted(){
            console.log('mounted')
        },
        destroyed(){
            console.log('destroyed')
        }
    }
</script>

인스턴스 라이프사이클 훅에서의 주의 사항, options 속성이나 콜백에서 화살표함수는 this를 가지기 않기 때문에 화살표함수 사용을 지양해야 합니다.

 

템플릿 문법


1. HTML 속성 사용하기

Mustaches는 HTML 속성을 사용할 수 없기 때문에 v-bind 디렉티브를 사용해야합니다.

<div v-bind:id="dynaicId">

</div>
<a v-bind:href="url"> {{url}} </a>

단, 속성에 들어가는 값이 true, false, null, undefined와 같이 boolean속성을 가진경우, falsy한 값을 넣었을 때는 빈칸이들어갑니다.

//input
<button v-bind:disabled="falsy">Button</button>
//output
<button                       >Button</button>

2. Javascript 문법사용하기

{{ok ? 'yes':'no'}} //삼항 연산자만 허용된다

 

3. 동적 argument

<a v-bind:[attributeName] ="url"> ...</a>
<a v-on:[eventName] ="url"> ...</a>

//argument의 제한사항
//<a v-bind:['foo'+bar] ="url"> ...</a>
//스페이스와 따음표와 같은 HTML 속성명으로 적합하지 않은 문자는 불가능하다

4. 수식어

<form v-on:submit.prevent="onSubmit"> ...</form>

.prevent는 event.preventDefault()와 같다

5. 약어

<a v-bind:href="url">...</a>
<a :href="url">...</a>
//v-bind shorthands

<a v-on:click="clickevent">...</a>
<a @click="clickevent">...</a>
//v-on shorthands

//v-model ->#

 

Vue property


1. Computed

{{로직이 많이 계산이 필요한가 ? Method : Computed}}

Computed는 (렌더링을 할때) 특정 값을 계산하여 안에 들어간 변수가 바뀌기 전까지 불러들이는 형태.

Method는 (렌더링을 할때)매번 계산을 하는 형태

//computed general shape

computed:{
    reversedMessage:function(){
        return this.message.split('').reverse().join('')
    }
}
//computed getter setter shape
computed:{
    fullName:{
        get: function(){
            return this.firstName + ' ' + this.lastName
        },
        set: function(newValue){
            var names = newValue.split('')
            this.firstName = names[0]
            this.lastName = names[names.length-1]
        }
    }
}
//getter
//vm.fullName
//setter
//vm.fullName ="John Don"

주의 : Date.now처럼 아무 곳에도 의존하지 않는 computed속성의 경우 절대 업데이트 되지 않는다.

computed:{
	now:function(){
    	return Date.now()
    }
}

 

2. Watch

대부분의 경우 computed가 적합하지만, 비동기식 또는 시간이 많이 소요되는 조작과 같은 경우엔 watch가 적합하다.

{{다루는 데이터 기반으로 변경할 필요가 있다 ? computed : watch}}

watch는 감시할 데이터를 지정하고 데이터가 바뀌면 이런 함수를 실행하는 망식으로 사용하는 명령형 프로그래밍 방식

computed는 계산해야하는 목표를 정의하는 방식으로 선언형 프로그램방식이다.

 

Style and Class


Class

1. 객체

<template>
	<div v-bind:class="{active:isActive, static}">

	</div>
</template>
export default{
	name:app,
    data(){
    	return {
            static:{
      	      condition0: true,
          	  condition1: false,
            },
            active : true,
            error : true
        }
    },
    computed(){
    	return{
        	static:function(){
            	return{
                    active:this.isActive && this.error,
                    'text-danger': this.error&&this.error.type=='fatal'
                }
            }
        }
    }
}

2. 배열

<template>
<div :class="[activeClass, errorClass]"></div>
<!--activeClass, errorClass 항상 -->
<div :class="[isActive?activeClass:'', errorClass]"></div>
<!--isActive조건부, errorClass 항상 -->
<div :class="[{active:isActive}, errorClass]"></div>
<!--isActive조건부, errorClass 항상 -->
</template>

export default{
    data(){
        return{
            isActive:true,
            activeClass:'active',
            errorClass:'text-danger'
        }
    }
}

3. HTML 클래스와 함께 바인딩

Vue.component('my-component',{template:'<p class="foo bar">hi</p>'})
<my-component class="bar boo"> </my-component>
<my-component class={active:isActive}> </my-component>
//my-component의 class는 foo bar baz boo, foo bar active이다.

 


Style

1. 객체 구문

<template>
<div :style="{color:activeColor, fontSize:fontSize+'px'}"> {{msg}}</div>
<div :style="StyleObject">{{msg}}</div>
</template>

export default{
	data(){
    	return {
        	msg:'hi',
        	activeColor:'red',
            fontSize:30
            styleObject:{
            	color:'red',
                fontSize:'13px'
            }
        }
    }
}

2. 배열 구문

<template>
<div :style="[baseStyles, overridingStyles]"> {{msg}}</div>
<div :style="{display:['-webkint-box', '-ms-flexbox', 'flex']}"
<!--display에 webkit이 없으면 ms-flex, 그게없으면ms-flex 또 그게 없으면 flex
</template>

 

조건부 렌더링


사용가능한 디렉티브 : v-if, v-else-if, v-else, v-show

v-if, v-else-if, v-else

Key를 이용한 재사용 가능한 엘리먼트 제어

<!--sample 1-->
<template>
<div v-if="type === "A">A </div>
<div v-else-if="type === "B">B </div>
<div v-else="type === "C">C</div>
</template>
<!--sample 2-->
<template v-if"loginType===username">
	<label>사용자 이름 </label>
    <input placeholder="사용자 이름을 입력하세요" key="usename-input"/>
</template>
<template v-else>
	<label>이메일 </label>
    <input placeholder="이메일 주소를 입력하세요" key="email-input"/>
</template>

sample 2와 같은 경우에는, template에 label과, input속성 두가지가 있습니다. label과 같은경우는 값을 전달하지 않기 때문에 재사용을 하는게 효율적이고, input 같은 경우 값을 전달하기 때문에 입력된 값을 바꿔야 합니다. 따라서 key를 사용하는 것이 좋습니다.

v-show

v-show가 있는 엘리먼트는 항상 렌더링 되고 DOM에 나타나 있습니다. v-show안에 있는 속성은 display css입니다.

<h1 v-show="ok">안녕하세요</h1>

 

리스트 렌더링


사용가능한 디렉티브 : v-for

v-for= "item in x" , x로 가능한 것 : object, array, number

<template>
	<div v-for="item in object">
    	{{item}}
        <!--t, a, p가 나온다-->
    </div>
	<div v-for="{item, index} in object">
    	{{item}} : {{index}}
        <!--t:0, a:1, p:2가 나온다-->
    </div>    
	<div v-for="item in object" v-bind:key="item.id">
    	{{item}}
    </div>
    <div v-for"n in 10">
    	{{n}}
    </div
</template>

export default{
	data (){
    	return{
        	object:{
            	title:'t',
                author:'a',
                publish:'p'
            }
        }
    }
}

맨 마지막에 v-bind;key를 사용하는 이유는 DOM 노드를 추적하여 재사용 재정렬하기 위해 고유한 key값을 제공하는 것입니다. 

배열 변경 감지 변이 메소드

push, pop, shift, unshift, splice, sort, reverse

배열 변경 감지 배열 대체

filter, concat, slice

 

주의 사항 

렌더링을 Vue에서 감지 못할때

vm.iitems[indexOfItem] = new Value//배열 값 직접 입력

vm.items.length = new Length //배열 길이를 직접 수정하는경우

vm.postCreate =2 //인스턴스를 처음 생성할 때 없던 postCreate의 값을 할당하는 경우

세 경우에는, Vue는 속성 추가 및 삭제를 감지하지 못합니다.

해결책

배열 값 직접 입력 해결책 3개

Vue.set(vm.items, indexOfItem, newValue)

vm.items.splice(indexOfItem, 1, newValue)

vm.$set(vm.items, indexOfItem, newValue)

배열 길이 직접 수정 해결책 1개

vm.items.splice(newLength)

인스턴스 생성시 없던 값을 할당하는 경우

vm.userProfile = Object.assign({}. vm.userProfile, {
	age:27, //기존에 있던 값
	favoriteColor: 'Green' //기존에 없던 값
})

 

필터정렬을 사용할 때

1. for안에 for을 사용할 때는 method

2. 단일 for 문 같은 경우에는 computed를 사용해야 한다(method도 가능하다)

<template>
	<li v-for"n in computedEven" :key="n"> {{n}}</li>
   	<li v-for"n in methodEven" :key="n"> {{n}}</li>
</template>

export default{
	data(){
    	return{
        	numbers : [1,2,3,4,5]
        }
    }
    computed(){
    	computedEven : function(){
        	return this.numbers.filter(function(number) {
            	return number %2 ===0
            })
        }
    }
    method(){
    	methodEven : function(){
        	return numbers.filter(function (number){
            	return number %2 ===0
            })
        }
    }
}

 

v-if가 v-for보다 우선순위를 가지고 있기 때문에, 둘이 동시에 사용하는 것은 추천하지 않습니다.

<li v-for="todo in todos" v-if="!todo.isComplete"> 
{{todo}}
</li>

 

 

이벤트 핸들링


사용가능한 디렉티브 : v-on

<template>
	<button @click="counter+=1"> {{counter}} +1  </button>
    <button @click="say('hi')" say hi </button>
    <!--method -->
	<button @click='warn('Form cannot be submitted yet', $event> Submit </button>
    <!--$event를 사용하여 원본 DOM이벤트에 엑세스-->
</template>

export default {
	data(){
    	return {
        	counter :0
        }
    },
	method:{
    	say : function(msg){
        	alert(msg)
        },
        warn:function(msg, event){
        	if(event) event.preventDefault()
            alert(msg)
        }
    }
	
}

 

이벤트 수식어 : stop, prevent, capture, self, once, passive

이를 사용해 부모나 자식에게서 불필요하게 발생하는 이벤트를 다룰 수 있다.

<a @click.stop="doTHis">A </a>
<!--stopPropagation-->
<a @click.prevent="doTHis"> A</a>
<!--preventDefault-->
<a @click.capture="doTHis">A </a>
<!--이벤트 캡쳐링-->
<a @click.self="doTHis">A </a>
<!--자식 엘리먼트에서는 불가!-->
<a @click.once="doTHis">A </a>
<!--클릭 이벤트는 한번만 가능합니다-->
<a @click.passive="doTHis">A </a>
<!-- 스크롤 이벤트를 취소할 수 없습니다-->

event.preventDeafult(), event.stopPropagation()와 같은 친구들이다.

키 수식어 : enter, tab, delete, esc, space, up, down, left, right, [alt, ctrl, shift, meta]

키보드 이벤트를 청취할 때 사용합니다.

<input @keyup.enter="submit">

alt, ctrl, shift, meta와 같은 경우 키가 눌러진 경우에만 마우스 또는 키보드 이벤트 리스너를 트리거할 수 있습니다.

<input @keyup.alt.67="clear">
<!-- ALT + C -->
<div @click.ctrl='doit'> DO it </div>
<!-- Ctrl + click-->

 

뷰 핸들러 함수를 사용하면 좋은장점

1. HTML 템플릿을 간단히 하여 Javascript코드 내에서 핸들러 함수 구현하는 것이 더 쉽다.

2. Javascript와 이벤트 리스너를 수동연결 할 필요가 없기에 ViewModel 코드는 순수 로직과 DOM이 필요하지 않다

3. ViewModel이 파기되면 모든 이벤트 리스너가 자동으로 제거됩니다.

 

폼입력 바인딩


사용가능한 디렉티브 : v-model

사용하는 selector : input, textarea

v-model과 input, textarea를 이용하여 양방향 데이터 바인딩을 생성합니다.

이때, input checkbox 같은 경우 1개면 true, false, 여러개인 경우에는, 배열을 바인딩할 수 있습니다.

<input v-model='msg1' placeholder='여기를 수정하세요'>
<p>메시지 : {{msg1}}</p>

<textarea v-mode='msg2' placeholder='여러줄을 입력하세요'> </textarea>
<p style='white-space:pre-line>{{msg2}}</p>

<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{checked}}</label>

<div>
<input type="checkbox" id="jack" value="jack" v-model="checkList">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="john" v-model="checkList">
<label for="john">John</label>
<input type="checkbox" id="mike" value="mike" v-model="checkList">
<label for="jack">Mike</label>
    
<span>{{checkList}}</span>
</div>

<input type="radio" id="one" value="One" v-model="radiopick">
<label for="one">One </label>
<input type="radio" id="two" value="Two" v-model="radiopick">
<label for="two">Two </label>
<span> 선택 : {{picked}}</span>

<select v-model="selected">
    <option disabled value=""> Please select one </option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
</select>
<span> 선택 : {{seleted}}
export default{
	data (){
    	return {
        	checkList : [],
            selected:''
        }
    }
}

보통 라디오, 체크박스 및 셀렉트 옵션의 경우 v-model 바인딩 값은 보통 정적인 문자열(또는 체크 박스의 boolean)입니다.

구체적인 이용방법

<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">

vm.toggle ==='yes' //체크된 경우
vm.toggle ==='no' //체크 안된 경우

<input type="radio" v-model="pick" v-bind:value="a">
vm.pick ===vm.a //체크하면

<select v-model="seleted">
	<option v-bind:value="{number:123}">123</option>
</select>

typeof vm.selected//'object'
vm.seleted.number//123

true-value와 false-value는 폼 전송시 체크되지 않은 박스를 포함하지 않기 때문에 입력의 value속성에 영향을 미치지 않기 때문에, 폼을 통해 전송되려면 라디오를 대신 사용해야 합니다

폼 입력 바인딩 수식어 : lazy, number, trim

<input v-model.lazy="msg">
//input 대신 change 이후에 동기화 됩니다
<input v-model.trim='msg1'>
//자동으로 trim을 해줍니다
<input v-model.number='msg2'>
//자동으로 입력이 숫자로 형변환됩니다.

 

 

Vue component에 관하여


간단한 컴포넌트 사용법

1. DOM 템플릿 구문 분석 경고

Vue에서 ul, ol, table, select와 같은 일부 엘립먼트는 어떤 엘리먼트가 나타날 수 있는지 제한을 가지고 있습니다

//이슈 발생
<table>
	<my-row> </my-row>
</table>

//이슈 탈출
<table>
	<tr is="my-row"> </tr>
</table>

2. Vue생성자 안에서 data 함수

//이슈 발생
Vue.component('my-component',{
	template:`<span>{{msg}}</span>`
    data:{
    	msg:'this is msg'
    }
}
//이슈 해결 - data를 {} to function form
Vue.component('my-component,{
	template:`<span>{{msg}}</span>`
    data(){
    	return{
    	msg:'this is msg'
    	}
    }
}

 

3. Vue생성자 안에서 data함수 공유 안하는 방법

수정전. simple-counter 끼리 모두 counter의 값을 공유한다

<<template>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</template>

export default { Vue.comonent('simple-counter',{
var data = {counter:0}
template:'<button @click="counter +=1'>{{counter}}</button>
    data:function(){
        return data
    }
}) }

수정후 simple-counter component 각각 data를 가지고 계산한다

<<template>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</template>

export default { Vue.comonent('simple-counter',{
template:'<button @click="counter +=1'>{{counter}}</button>
    data:function(){
        return {
 			counter:0       
        }
    }
}) }

 


부모 - 자식 컴포넌트 관계

부모는 자식에게 props를, 자식은 부모에게 events를 보낸다.

props는 하위 컴포넌트의 템플릿에서 상위 데이터를 직접 참조하는 것이 아닌, 상위 컴포넌트가 하위 컴포넌트로 전달하는 것이다.


여기서 잠깐! 정적 props랑 동적 props 구분방법! 

1. 동적 prop는 v-bind:title과 props.title과 같이 변하는 변수를 전달한다

2. 정적 props는 title="string"같이 v-bind 없이 전달하거나, v-bind:title="false" v-bind:title="42"와 같이 숫자 혹은 논리형 자료를 전달하는 방식이 있다.


ParentComponent.vue

<template>
    <ChildComponent v-bind="ParentToChild"></ChildComponent>
    <!-- v-bind로 props를 child로 보낸다 -->
</template>
<script>
    import ChildComponent from './ChildComponent.vue'
    export default{
        compoents:{
            ChildComponent,
        },
        name:'ParentComponent',
        data(){
            return{
                ParentToChild:{
                    text : 'this is props',
                    isComplete : true,
                }
            }
        }

    }
</script>

v-bind로 props를 ChildComponent로 내린다

ChildComponent

<template>
  {{ text }}
  {{ isComplete }}
</template>
<script>
export default {
  name: "ChildComponent",
  props: ["text", "isComplete"],
  data() {
    return {};
  },
};
</script>

여기서 볼 것은 name으로 본인의 Component Name을 정하고, 부모는 components로 자식을 선언하고, 자식은 props로 무엇을 받았는지 표시한다.

이때 Props는 단방향 데이터의 흐름이다.


Props - 검증, 컴포넌트가 받는 동안 prop에 대한 요구사항을 지정하는 것을 유효성 검사 요구사항이 있는 객체로 할 수 있습니다. ChildComponent.vue를 보면 props : {}에 맞지 않으면, 콘솔로 알림이 나옵니다

//ParentComponent.vue
<template>
    <input type="text" v-model="uerInput">
    <ChildComponent v-bind:text="userInput" :PropC="10", :PropE="10"></ChildComponent>
</template>
<<script>
export default {
    component:{
        ChildComponent,
    },
    name:ParentComponent,
    data(){
        return {
            userInput :''
        }
    }
}
</script>


// ChildComponent.vue
Vue.component('ChildComponent',{
    props:{
        propA:Number,
        PropB:[String, Number],
        PropC:{
            type:String,
            required:true
        },
        PropD:{
            type:Number,
            default:100
        },
        PropE:{
            type:Object,
            default:function(){
                return {msg:'hello'}
            }
        },
        propF:{
            validator:function(value){
                return value>10
            }
        }
    }
})

 

Props가 아닌 속성 중 type 같은 경우 원래 있던 성격을 대입하면서 바꿔버린다.  하지만, class와 style같은 경우에는 두 값이 합쳐져서 추가로 더한다.


Props가 아닌 속성 v-on을 이용한 사용자 지정 이벤트 $on을 사용하여 이벤트를 이벤트를 감지하고, $emit으로 이벤트를 트리거하여 발동할 수 있다. 

<template>
<h1>{{total}}</h1>
    <ChildComponent @increment="incrementTotal"></ChildComponent>
</template>
<script>
    import ChildComponent from './ChildComponent.vue'
    export default{
        component:{
            ChildComponent,
        },
        name:'ParentComponent',
        data(){
            return{
                total:0,
            }
        },
        methods(){
            incrementTotal(){
                this.total+=1
            }
        }
    }
</script>

//ChildComponent.vue
<template>
    <button @click="incrementCounter">{{counter}}</button>
</template>
<script>
export default {
    name :'ChildComponent',
    data(){
        return {
            counter : 0,
        }
    },
    methods:{
        incrementCounter(){
            this.counter +=1
            this.$emit("increment")
        }
    }
}
</script>

1 ChildComponent의 @click을 누르면 incrementCounter methods가 실행된다

2. method내의 this.$emit("incremnt")가 발생한다. {{counter+1}}

3. ParentComponent의 @increment가 실행된다

4. @increment에 있는 incrementTotal이 실행된다. {{total +1}}

 


Props가 아닌 속성 .sync

일부의 경우에 속성에 "양방향 바인딩"이 필요할 때, 자식 컴포넌트가 sync를 가지는 속성을 변경하면 값을 변경이 부모에게 반영됩니다. 편리하지만 단방향 데이터 흐름이 아니기 떄문에 장기적으로 유지보수에 문제가 생깁니다.


Props가 아닌 속성 사용자 정의 이벤트를 사용하여 폼 입력 컴포넌트 만들기

<input v-model ="something">
<input :value="something" @input="something = $event.target.value">
<!-- 위와 아래는 결과가 같다-->

따라서 v-model을 사용하는 컴포넌트는 value prop를 가집니다. 새로운 값으로 input 이벤트를 내보냅니다.

Vue.component('my-checkbox', {
	model:{
    	prop:'check',
        event:'change'
    }
})
<my-checkbox v-model="foo" value="some value"> </my-checkbox>

v-model은 value를 보조 변수로 사용하고 input 이벤트로 사용하지만, 체크 박스와 라디오버튼과 같이 value속성으로 사용할 수있습니다. model옵션을 사용하면 다음 경우에 충돌을 피할 수 있습니다


Props가 아닌 속성 비부모 자식간 통신

var bus = new Vue()

bus.$emit('id-seleted', 1)

bus.$on('id-seleted', function(id){}

 

 


슬롯을 사용한 컨텐츠 배포

//ParentComponent.vue
<template>
  <h2>저는 부모 컴포넌트입니다</h2>
  <ChildComponent>
    <p>slot에 들어갈 내용입니다</p>
  </ChildComponent>
</template>
//ChildComponent.vue
<template>
  <h2>저는 자식 컴포넌트입니다</h2>
  <slot> 제공된 컨텐츠가 없는 경우에만 볼 수 있스빈다 </slot>
</template>

자식 컨텐츠에 <slot> 이라는 공간을 마련해두면, 부모안에 들어간 자식 셀렉터 사이에 넣은 문자가 slot에 배치됩니다.

만일 슬롯이 여러게 필요한경우

//ParentComponent.vue
<template>
<ChildComponent>
    <h1 slot="header">여기에 페이지 제목이 위치합니다</h1>
    <!-- default slot -->
    <p>메인 컨텐츠</p>
    <p>입니다</p>
    <!-- default slot -->
    <p slot="footer">푸터 위치입니다</p>
</ChildComponent>
</template>
//ChildComponent.vue
<template>
<header>
    <slot name="header"></slot>
</header>
<main>
    <slot>

    </slot>
</main>
<footer>
    <slot name="footer"></slot>
</footer>
</template>

slot 속성에 있는 값이(header) slot name에 맞춰 값이 들어간다. 만일 slot속성이 없는 값이 있고, slot에 name이 없는 것이 있다면 그 값을 default로 보고 대입한다.

범위를 가지는 슬롯

//ParentComponent.vue
<template>
    <ChildComponent>
        <template slot-scope="props">
            <span>hello from parent</span>
            <span>{{props.text}}</span>
        </template>
        <template slot-scope="{text}">
            <span>{text}</span>
        </template>
    </ChildComponent>
</template>
//ChildComponent.vue
<template>
    <slot text="hello from child"></slot>
</template>

slot-scope에 있는 span개가 child의 slot으로 들어간다. 이때 scope에 있는 prop가 props.text의 값을 전달한다

 


동적 컴포넌트

1. is 속성

여러 컴포넌트 간에 동적으로 트랜지션하고 is 속성에 동적으로 바인드 할 수 있습니다

<template>
	<button @click="toggle"> change view </button>
    <component v-bind:is='currentView'></component>
</template>

<script>
export default {
    name:'body',
    components :{
    	'child-component' : ChildComponent,
        'next-component' : NextComponent
    },
    data(){
        return{
            currentView: 'child-component'
        }
    }
    method:{
    	toggle(){
        	this.currentView = (this.currentView === 'child-component )? 'next-component':'child-component'
        }
    }
}
</script>

 

2. keep-alive 속성

메모리에 유지하여 상태를 보존하거나 다시 렌더링하지 않도록 하려면 동적 컴포넌트를 keep-alive에 래핑해야한다

<keep-alive>
	<component :is = "currentView>
    </component>
</keep-alive>

keep-alive vs v-once : 둘다 한번 실행을 한다는 접에서 비슷하지만 다른점은

keep-alive는 동적, v-once는 정적에서 사용한다.


비동기 컴포넌트

//example1
Vue.component('async-example', function(resolve, reject){
    setTimeout(function(){
        resolve({template:<div>I am async!</div>})
    }, 1000)
})
//example2
Vue.component('async-webpack-example', ()=>import(".my-/async-component"))

//example3
const AsyncComp = ()=>{
    component:import('./Mycomp.vue'),
    loading:LoadingComp,
    error:ErrorComp,
    delay:200,
    timeout:3000
}

example 1, 2를 이용하여, 실제로 필요할 때만 컴포넌트를 로드 하는 방식을 사용할 수 있고, example3는 이 비동기 컴포넌트 팩토리를 자세히 설정하는 방법입니다.

 

프로그래밍적 이벤트 리스너


$on을 이용한 이벤트 청취

$once를 이용한 단발성 이벤트 청취

$off를 이용한 이벤트 청취 중단이 가능합니다.

 

'Javascript > Vue' 카테고리의 다른 글

Pinia with Vue 사용법!  (0) 2022.07.11