컴포넌트 LifeCycle
created 훅은 인스턴스가 생성된 후에 호출이 단계는 컴포넌트가 돔에 추가되기 전 단계아직 컴포넌트가 돔에 추가되기 전이기 때문에
돔에 접근하거나 this.$el를 사용할 수 없다created 훅에서는 이제 data와 events가 활성화되어 접근할 수 있다. 여전히 템플릿과 가상돔은 마운트 및 렌더링되지 않은 상태
mounted: 컴포넌트, 템플릿, 렌더링된 돔에 접근할 수 있는 단계mounted 훅에서 유의할 점은, 부모와 자식 관계의 컴포넌트에서 우리가 생각한 순서로 mounted가 발생하지 않는다는 점.즉 부모의 mounted훅이 자식의 mounted훅보다 먼저 실행되지 않는다. 오히려 그 반대이다 created훅은 부모->자식의 순서로 실행되지만 mounted는 그렇지 않다.부모는 mounted훅을 실행하기 전에 자식의 mounted훅이 끝나기를 기다린다
updated: 이 훅은 컴포넌트의 데이터가 변하여 재 렌더링이 일어난 후에 실행된다. 돔이 업데이트 완료된 상태이므로돔 종속적인 연산을 할 수 있다. 그러나 여기서 상태를 변경하면 무한루프에 빠질 수 있다. 모든 자식 컴포넌트의 재 렌더링 상태를 보장하지는 않는다
destroyed: 이 훅은 해체(뷰 인스턴스 제거)된 후에 호출된다. Vue 인스턴스의 모든 디렉티브가 바인딩 해제 되고 모든 이벤트 리스너가 제거되며 모든 하위 Vue 인스턴스도 삭제된다. 서버 렌더링시 호출되지 않는다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="http://unpkg.com/vue"></script>
<style>
div{
padding:10px;
border: 1px solid silver;
}
</style>
</head>
<body>
<div id="app">
{{msg}}
<my-comp v-if="visible"></my-comp>
</div>
<script>
//컴포넌트
var myComp={
template:'<div>MyComponent {{str}}</div>',
data(){
return {
str:'MyComp data'
}
},
created(){
console.log('myComp created')
},
mounted(){
console.log('myComp mounted')
},
updated(){
console.log('myComp updated')
},
destroyed(){
console.log('destroyed')
}
}
new Vue({
el:'#app',
data:{
msg:'Hello Vue JS',
visible:true
},
components:{
//컴포넌트 이름: 컴포넌트객체
'my-comp':myComp
}
})
</script>
</body>
</html>
vue-ajax
this접근 문제 해결
1) 밖에서 선언하고 접근
2) bind를 통해 해결
3) 화살표함수를 사용하면 this는 vue 인스턴스이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="http://www.unpkg.com/vue"></script>
<style>
div#app{
width: 90%;
margin: 30px auto;
}
</style>
</head>
<body>
<div id="app">
<button @click="getData">Movie Data가져오기</button>
<div v-for="movie in movies" :key="movie.id">
<img :src="movie.medium_cover_image">
<h3>영화제목:{{movie.title}}</h3>
<h4>rating:{{movie.rating}}</h4>
</div>
</div>
</body>
<script>
new Vue({
el:'#app',
data(){
return {
movies:[]
}
},
methods:{
getData(){
var req = new XMLHttpRequest();
//open('요청방식',url)
//onreadystatechange=콜백함수
//send('')
//console.log("1."+this); vue instance
var vm = this;
req.open('GET','list_movies.json');
req.onreadystatechange=function(){
if(req.readyState==4&&req.status==200){//성공적 응답
var res= JSON.parse(req.responseText);
//JSON형태로 된 문자열을 JSON객채로 만들어주는 함수
//JSON.parse()
//alert(res.data.movies);
//console.log("2."+this); XMLHttpRequest
//vm.movies=res.data.movies;
this.movies=res.data.movies;
console.log(this.movies);
}
}.bind(this);
req.send(null); //post일때는 요청값
}
}
})
</script>
</html>
axios를 이용해서 ajax통신
axios.get(url).then(콜백함수) => 응답이 성공적으로 왔을 때
.catch(콜백함수) => 에러발생시
axios.post(url,요청파라미터데이터)
.then(함수)
.catch(함수)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="http://www.unpkg.com/vue"></script>
<script src="http://www.unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<button @click="getData">Movie Data가져오기 - Axios이용</button>
<div v-for="movie in movies" :key="movie.id">
<img :src="movie.medium_cover_image">
<h3>영화제목:{{movie.title}}</h3>
<h4>rating:{{movie.rating}}</h4>
</div>
</div>
</body>
<script>
new Vue({
el:'#app',
data(){
return{
movies:[]
}
},
methods:{
getData(){
axios.get('list_movies.json')
.then((res)=>{
console.log(res.data);
this.movies=res.data.data.movies;
})
.catch(function(err){
alert('error'+err.message);
})
}
}
})
</script>
</html>
VueCli생성
Windows의 경우
콘솔에서
npm i -g @vue/cli
친 뒤 아래를 작성하자 (현재의 최신 버전 설치됨)
vue create myvue-app
cd myvue-app
npm run serve 로 실행함
[2] Vue-router 설치
참고: https://router.vuejs.org/installation.html
Myvue-app 디렉토리에서
npm i --s vue-router
[3] jquery, bootstrap등도 설치하여 사용해보자.
npm i --s jquery bootstrap popper.js
HeaderComp.vue
<template>
<div class="jumbotron text-center">
<h1>My Frist Vue App</h1>
</div>
</template>
<script>
export default{}
</script>
NavComp.vue
<template>
<nav class="navbar navbar-expand-sm bg-warning navbar-dark">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li class="nav-item">
<router-link to="/" class="nav-link">HOME</router-link>
<!-- <a class="nav-link" href="#">HOME</a> -->
</li>
<li class="nav-item">
<router-link to="#" class="nav-link text-success">a님 로그인중...</router-link>
</li>
<li class="nav-item">
<router-link to="/login" class="nav-link">Login</router-link>
<router-link to="/logout" class="nav-link">Logout </router-link>
</li>
<li class="nav-item">
<router-link to="/signup" class="nav-link">SignUp</router-link>
</li>
<li class="nav-item">
<router-link to="/memo" class="nav-link">Memo</router-link>
</li>
</ul>
</div>
</nav>
</template>
<script>
export default {
}
</script>
App.vue
<template>
<div id="app" class="container">
<header-comp></header-comp>
<nav-comp></nav-comp>
<div class="row p-4">
<div class="col-md-12">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import HeaderComp from './components/HeaderComp.vue'
import NavComp from './components/NavComp.vue'
export default {
name: 'App',
components: {
'header-comp' : HeaderComp,
NavComp
}
}
</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;
}
</style>
Home.vue
<template>
<div>
<h1>Home Page</h1>
</div>
</template>
<script>
export default {
}
</script>
NotFound.vue
<template>
<div class="text-center">
<h1>Not Found</h1>
</div>
</template>
<script>
export default {
}
</script>
route하는법
router 폴더 생성 후
index.js
import VueRouter from 'vue-router';
import Vue from 'vue';
import Home from '../components/Home.vue'
import NotFound from '../components/NotFound.vue'
import SignUp from '../components/user/SignUp.vue'
Vue.use(VueRouter) //VueRouter를 미들웨어로 사용하겠다고 명시
export default new VueRouter({
mode:'history', //hash 가 default
base:'/',
routes:[
{
path:'/',
name:'Home',
component: Home
},{
path:'/signup',
name:'SignUp',
component: SignUp
}
,{
path:'*',
component: NotFound
}
]
})
SignUp.vue
@submit.prevent="send()"를 한다면 submit을 막을 수 있다.
parameter을 넘길때
new URLSearchParams를 이용하면 쉽다.
<template>
<div>
<!-- <div><h1>처리 중...</h1></div> -->
<div id="join" class="container p-3">
<h1>SingUp</h1>
<form name="frm" action="join.json" method="POST" @submit.prevent="send()">
<div class="row">
<div class="col-md-6 offset-md-3">
Name: <input type="text" name="userName" v-model="user.name"
placeholder="Nick Name" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
Nick Name: <input type="text" name="userNick" v-model="user.nick"
@input="checkNick"
placeholder="User ID" class="form-control" >
<div class="text-danger" v-if="nickErr">아이디는 4자이상 8자 이하 입니다.</div>
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
PASSWORD: <input type="text" name="userPwd" v-model="user.pwd"
@input="checkPwd"
placeholder="Password" class="form-control">
<div class="text-danger" v-if="pwdErr">비밀번호는 4자 이상 8자 이내입니다.</div>
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
PASSWORD Confirm :
<input type="text" name="userPwd" placeholder="Password Confirm" class="form-control" @input="checkRePwd">
<div class="text-danger" v-if="pwdErr2">비밀번호가 일치하지 않아요</div>
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
Tel :
<input type="text" name="userTel" placeholder="Phone" class="form-control" v-model="user.tel">
</div>
</div>
<div class="row">
<div class="col-md-6 offset-md-3">
Address :
<input type="text" name="userAddr" placeholder="Address" class="form-control">
</div>
</div>
<div class="row m-2">
<div class="col-md-6 offset-md-3 p-1">
<button class="btn btn-block btn-outline-success">Signup</buttoN>
</div>
</div>
<div class="row m-5">
<div class="col-md-6 offset-md-3">
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return {
user:{
name:'',
nick:'',
pwd:'',
tel:''
},
nickErr:false,
pwdErr:false,
pwdErr2:false
}
},
methods:{
checkNick(evt){
//console.log(evt.target.value);
let nick =evt.target.value;
let len = nick.length;
if(len<4||len>8){
this.nickErr=true;
}else{
this.nickErr=false;
}
},
checkPwd(evt){
let len = evt.target.value.length;
this.pwdErr = (len<4||len>8)? true:false;
},
checkRePwd(evt){
let pwd2 = evt.target.value;
if(this.user.pwd!=pwd2){
this.pwdErr2=true;
}else{
this.pwdErr2=false;
}
},
send(){
//ajax 요청
if(!this.nickErr&&!this.pwdErr&&!this.pwdErr2){
let params=new URLSearchParams();//파라미터명1=값&파라미터명2=값
params.append('name',this.user.name);
params.append('nick',this.user.nick);
params.append('pwd',this.user.pwd);
params.append('tel',this.user.tel);
axios.get('/join.json?'+params)
.then(function(res){
alert(res.data);
})
.catch(function(err){
alert("error: "+err.message)
})
}
}//send() end----
}
}
</script>
'개발자 > 국비지원 SW' 카테고리의 다른 글
국비지원 108일차 - VueJS db연동 (0) | 2020.09.28 |
---|---|
국비지원 107일차 - Spring 계층형게시판(페이징,블록,답글) (0) | 2020.09.24 |
국비지원 105일차 - Spring 결제 확인까지 구현 (0) | 2020.09.23 |
국비지원 104일차 - Vue 인스턴스, 컴포넌트(전역, 지역, 통신), 이벤트 버스, To Do App (0) | 2020.09.21 |
국비지원 103일차 - Spring 주문처리2, MyBatis foreach (0) | 2020.09.18 |