컴포넌트 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>


+ Recent posts