ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Vue.js] v-model, watcher, Transition
    Front-End/Vue.js 2022. 11. 24. 16:17

     

    📑 v-model 값 이용하기

     

    사용자의 입력값 받으려면 v-model을 사용한다. 예를들어 원룸을 판매하는 어플이 있을 때 몇 개월을 살지 입력하면 그에 맞는 가격이 출력되도록! 

     

    <!--input은 숫자로 입력해도 자료형은 문자열로 나올 것이다.
        html요소.addEventListener('click',function(e){})
        여기서 e가 $event와 같은 것 .
        @input은 사용자가 입력할 때마다 month라는 곳에 값을 입력해줘라.-->
    <!-- <input @input="month= $event.target.value"> -->
    <!--v-model은 input, select, textarea 등등 다 가능-->
    <input v-model.number="month">
    <p> {{month}} 개월 선택함 : {{외부데이터[사용자클릭].price * month}}</p>

     

    v-model을 안 쓴다면, @input 이벤트를 통해 사용자가 값을 입력하면 month라는 변수에 $event.target.value 사용자가 입력한 값을 받아오게 만들었다. 그 후 {{ }} 데이터 바인딩을 통해 {{month}}의 값을 출력한다.

     

    만약 데이터 바인딩을 하려면 data()에 month라는 데이터를 선언해줘야한다. 초기값을 1로 출력한다. input 태그에 값이 들어오면 string 형태로 저장되는데 이를 숫자로 변환하기 위해 v-model.number를 해준다. number를 붙여주면 숫자 뒤에 붙는 문자는 무시하게 된다 '1ㅇㄹㅈㄷ' 이러면 '1'만 인식하게 된다. 

     

    export default {
    
        name : 'Modal',
        data(){
            return{
                month :1,
            }
        },
    
        //data(){}로 만들면 되지 않음? 
        //되긴 되는데 부모도 쓰는 데이터라면 부모컴포넌트에 만들어두자.
        props : {
            외부데이터 : Array,
            모달창보이나 : Boolean,
            사용자클릭 : Number,
    
        }
    }

     

     

     

     

     

    📑 watcher : 데이터 감시자

     

    만약 숫자를 입력해야되는 input 태그 값에 문자가 들어온다면? 그때 사용하는게 watcher이다. 함수 명을 감시하는 데이터 이름과 같게하면 된다. 위에서 month는 사용자의 입력을 받아오는 input 태그에 model 값으로 받아뒀다. 

     

    <input v-model="month"> 
    <p> {{month}} 개월 선택함 : {{외부데이터[사용자클릭].price * month}}</p>

     

     

    model이라는 데이터가 변할 때 watch는 아래 정해둔 조건값에 해당한다면 alert를 실행한다. 

    watch :{
        //month를 감시하는 함수인 것. 이름은 데이터 이름과 같게 하면 된다.
        month(a){
            //사용자가 month를 글자로 입력하면 경고문 띄워주셈 
            if(a>=13) {
                alert(' 13보다 작아야 됩니다 경고경고!');
                this.month=1;
            }else if(isNaN(a)==true ){ //숫자가 아니라면
                alert('숫자만 입력하세요');
                this.month=1;
            }
        }
    },

     

     

     

     

     

     

    📑 애니메이션 주기 Transition

     

    UI가 등장하고 퇴장할 때 애니메이션을 주는 방법은 2가지가 있다. 하나는 CSS 애니메이션을 주는 방법이고 다른 하나는 Vue가 제공하는 <Transition> 태그를 이용해서 줄 수도 있다. 

     

    일단 css로 애니메이션을 주려면 1. 시작전 class 디자인 2. 끝난 후 class 디자인 3. 원할 때 2번 클래스를 부착 

     

     

    📌 1. css 애니메이션 주기

     

    <div class="start" :class="{ end : 모달창보이나}">

     

    위와 같이 class명에 start라는 이름을 주고 end는 만약 "모달창보이나"라는 데이터가 true가 된다면 부착되게 만들었다. css 스타일은 아래와같이 주면 된다. 그럼 모달창이 떴을 때 희미하게 보였다가 서서히 선명해지는 걸 확인할 수 있다. 

     

    .start{
      opacity: 0;
      /*이 클래스에 있는 애니메이션 변할 때 1초에 걸려 스무스하게 변한다.*/
      transition : all 1s;
    }
    
    .end{
      opacity: 1;
    }

     

     

     

    📌 2. Vue에서 제공하는 <Transition> 태그 이용

     

    트랜지션을 적용하고 싶은 문장을 <Transition> 태그로 감싼다. 그후 name 값으로 명칭을 지정해주면 된다. 

    <Transition name="fade">
    <!-- <div class="start" :class="{ end : 모달창보이나}"> -->
    <Modal @closeButton ="모달창보이나=false;" 
    :외부데이터="외부데이터" :사용자클릭="사용자클릭" :모달창보이나="모달창보이나"/>
    </Transition>

     

    명칭을 fade로 준 뒤 from, active, to에 주고 싶은 속성을 주면 된다. 

     

    /*시작스타일*/
    .fade-enter-from{
      transform:  translateY(-1000px);
      opacity :0;
    }
    .fade-enter-active{
      transition: all 1s;
    }
    /*끝 스타일*/
    .fade-enter-to{
      transform:  translateY(0px);
      opacity :1;
    }

     

     

     

     

    📑 정렬 sort()

     

    array.sort()는 문자정렬이다. 배열안의 문자들은 문자순으로 정렬해주는 것. 만약 숫자순으로 정렬하고 싶다면 아래와 같이 사용한다. 

     

    var array = [3,5,2];     
    array.sort(function(a,b){         
    return a-b; //a-b가 만약 양수면 숫자를 오른쪽으로 보낸다.     
    });

     

    sort는 근데 원본을 영구적으로 변경한다. 그렇기에 다시 정렬했던 걸 되돌리려면 어떻게 할까?? 원본 데이터를 보존해두는 방법이 있다. 

     

    array와 object는 a=b와 같은 등호를 사용하면 갑을 집어넣으라는 의미가 아닌 a와 b의 값을 공유해줘. 라는 의미이다. 따라서 되돌리기를 하려고 this.원룸들 = this.원룸원본데이터 이런식으로 등호를 사용하면 문제가 생긴다. 

     

    여기서 값 공유가 일어나지 않게 독립적인 array 복사본을 만들고 싶다면 ... 이 기호를 사용하자. 이 기호는 spread operator라는 기호로 array, object의 괄호를 없애주는 문법이다. 만약 ...[1,2,3]을 쓴다면 1,2,3 이렇게 쓰인다는 소리이다. 

     

    <!--vue의 html과 같은 뼈대, App.vue에다가 작성한다. -->
    <template>
    
    <!-- 
      동적인 UI 만드는 법
      1. UI의 현재 상태를 데이터로 저장해둔다.
      2. 데이터에 따라 UI가 어떻게보일지 작성한다.
      3. 
    
     -->
    
     <!--props로 자식에게 데이터 보내는 법
      1. 데이터 보내고
      2. 등록하고
      3. 쓰면 된다. -->
    
     <Modal  
     :원룸들="원룸들" :모달창열렸니="모달창열렸니" :사용자가누른상품번호="사용자가누른상품번호"
     @closeModal="모달창열렸니=false"></Modal>
    
      <div class="menu">
     <!--    <a>Home</a>
        <a>Products</a>
        <a>Sale</a> -->
       <!--  <a v-for="작명 in 반복횟수">Home</a> -->
        <a v-for="a in 메뉴들" :key="a">{{a}}</a>
    
      </div>
    
      <Discount></Discount>
    
    
      <button @click="priceSort()">가격순정렬</button>
      <button @click="sortBack()">되돌리기</button>
    
    
    
      <Card @openModal="모달창열렸니=true; 사용자가누른상품번호=$event"
      :원룸들 = "원룸들[i]"  v-for="(a,i) in 원룸들" :key="a"></Card>
    
    
    
    </template>
    
    <script>
    
    //document.getElementById().innerHTML = ?? ; 기존 JS에서는 이렇게 해야 값을 집어넣을 수 있엇다. 하지만 뷰에서는 이렇게 길게 코드를 짜지 않는다. 
    
    /* 데이터 바인딩 하는 이유는 ?
    1. HTML에 하드코딩해놓으면 나중에 변경이 어렵다.
    2. VUE의 실시간 자동 렌더링을 하려고
    실시간으로 바뀔 데이터가 아니라면 그냥 하드코딩 해도 된다. 
    3. HTML 속성도 데이터 바인딩이 가능한데 그건 v-on을 사용해서 바인딩 한다. 
     */
    
    
    import data from './assets/data.js';
    import Discount from './Discount.vue';
    import Modal from './Modal.vue';
    import Card from './Card.vue';
    
    
    
    
    
    
    export default {
      name: 'App',
      data(){
        return{
          price1 : 60,
          price2 : 70,
          스타일 : 'color : red' ,
          products : ['역삼동원룸', '천호동원룸','용현동원룸'],
          메뉴들 : ['HOME', 'SHOP','ABOUT'],
          num :[0,0,0],
          모달창열렸니 : false, //UI가 어떻게 보일지 현재 상태를 기록
          원룸들 : data,
          원룸들오리지널 :[...data],
          사용자가누른상품번호 : 0
        }
      },
      methods: {
        increase(){
          this.신고수+=1;
        },
        priceSort(){
          //아래와 같음 문자 정렬이다. 정확한 숫자는 function을 넣어야된다.
          /* this.원룸들.sort() */
          this.원룸들.sort(function(a,b){
            return a.price-b.price
          })
        },
        sortBack(){
          //sort는 원본을 아예 변형시켜버린다. 따라서 원본을 보존하려면 map, filter 이용해야한다.
          this.원룸들 = [...this.원룸들오리지널];
    
        }
      },
      components: {
        Discount : Discount,
        Modal,
        Card
      }
    }
    </script>
    
    <style>
    
    
    body{
      margin:0
    }
    div{
      box-sizing:border-box;
    }
    .black-bg{
      width:100%; height:100%;
      background:rgba(0,0,0,0.5);
      position :fixed; padding: 20px;
    }
    .white-bg{
      width:100%; 
      background:white;
      border-radius :8px; padding: 20px;
    }
    
    
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
    }
    
    .menu {
      background: darkslateblue;
      padding : 15px;
      border-radius:  5px;
    }
    
    .menu a{
      color:white;
      padding: 10px;
    }
    .room-image{
      width:100%;
    }
    
    </style>
    반응형

    댓글

Designed by Tistory.