AC 03/07 Vue.js

Bae Seong Jun·2024년 3월 7일

Acorn academy

목록 보기
49/70

데이터 바인딩이란?

https://tragramming.tistory.com/105
v-bind는 속성에 데이터를 바인딩하는 것으로 :속성명으로 사용할 수 있다.

v-if, v-model 활용

v-model과 v-if를 활용한 입력제한에 따른 텍스트 실시간 변경 기능

<template>
  <div>
    이름: <input type="text" v-model="name"> <span v-if="name.length>=4">4글자 이하여야합니다.</span><br>
    나이: <input type="text" v-model="age"> <span v-if="age<10 || age>120">10이상 120이하</span>
    <hr>
    이름길이:<span>{{ name.length }}</span>
    나이:<span>{{  age }}</span>
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      name:"",
      age:""
    };
  }
}
</script>

vi-if, else, else-if

v-for


키없으면 렌더링 안됨

순서 기억
배열: (내용, 인덱스)
객체: (내용, 키, 인덱스)

키값에 같은 이름의 변수 사용하면 안된다. 흠...
https://zzang9iu.tistory.com/101
https://mine-it-record.tistory.com/657

<template>
  <div>
    <!-- <v-for="contact in contacts" v-bind:key="유일값"> -->
    <h1>index없임</h1>
    <ul>
      <li v-for="name in names" v-bind:key="name">
        {{ name }}
      </li>
    </ul>
    {{ name }}

    <h1>index 지정</h1>
    <ul>
      <li v-for="(name, index) in names" v-bind:key="index">
        {{ index }} : {{ name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name:"HelloWorld",
  props:{

  }, data: function(){
    return {
      names: ["홍길동", "이순신", "유관순"]
    }
  }
}
</script>

v-for 활용 정적이미지 사용

require 역할 알아보기

이미지 경로가 src/assets일떄 vuejs에서는 @/assets로 사용할 수 있다.

@ 기능 알아보기
아마 ecma 쪽 문법 배운 것 중 하나일거임

<template>
  <div>
    <h1>도서목록 {{ bookList.length }}</h1>
    <ul>
      <li v-for=" book in bookList" v-bind:key="book.id">
        <img v-bind:src="require(`@/assets/image/${book.img}.jpg`)" width="100" height="100">
        <!-- 이미지 경로가 src/assets일떄 vuejs에서는 @/assets로 사용할 수 있다. -->
        {{ book.name }}
        {{ book.img }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props:{
    bookList : Array
  }, data: function(){
    return {
      
    };
  }
}
</script>

<style>

</style>

v-for json 객체 순회 예제

json 객체를 v-for디렉티브로 순회할 시에는 아래와 같다.
<태그명 v-for="(value, key, index) in 객체명" v-bind:key="key나 index 등">

<template>
  <div>
    <ul>
      <li v-for="(value, key, index) in person" :key="key">
        {{ index }} : {{  key }} / {{ value }}
      </li>
    </ul>

    <table border="1">
      <tr v-for="(value, key, index) in person" :key="key">
        <td>{{ index }}</td>
        <td>{{  key }}</td>
        <td>{{ value }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      person:{
        name:"홍길동",
        age:10,
        address:"서울"
      }
    };
  }
}
</script>

v-for <select>태그사용

<template>
  <div>
    <select v-model="result">
      <option disabled selected> 과일을 선택하세요.</option>
      <option v-for="(v, k ,i) in fruits" :key="i">
        {{ v }}
      </option>
    </select><br>
    선택한 과일은: {{ result }}
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      fruits:{
        apple:"사과",
        banana: "바나나",
        melon : "멜론"
      },
      result:""
    };
  }
}
</script>

template 태그

div 태그는 반복하면 div가 흔적이 남는다.
template 태그는 반면에 흔적을 아예 남기지 않는다.
그래서 여러 요소를 그룹핑하여 반복처리용 태그로 사용한다.

오류발생 고치기

<template>
  <div>
    <h1>1. 기본</h1>
    <div v-for="(name, idx) in names" :key="idx">
      {{ idx }} : {{ name }}님
    </div>
    <hr>
    <h1>2. div태그로 그룹핑: div 태그가 흔적으로 남음</h1>
    <div v-for="(name, idx) in names" :key="idx+10">
      <span>{{ idx }} : {{ name }}님</span>
    </div>
    <h1>3. template태그 그룹핑: template태그가 흔적으로 안남음</h1>
    <div class="hello">
      <template v-for="(v,i) in names">
        <span :key="i+100">{{ v }}님</span>
      </template>
    </div>
    <h1>4. </h1>
    </div>
      <span v-for="(v, i) in names" :key="i+1">{{ v }}</span>
    </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      names:["홍길동","이순신","유관순"]
    };
  }
}
</script>

v-on 이벤트처리 디렉티브

v-on:이벤트="실행할 함수" = @이벤트="실행할 함수"
함수는 methods에서 선언
이벤트 인자로 전달 가능

<template>
  <div>
    <h1>v-on:이벤트명="처리함수" 또는 @이벤트명="처리함수"</h1>
    <button v-on:click="handleEvent"> v-on:click</button><br>
    <button @click="handleEvent"> @click</button><br>
      <button v-on:click="xxx('홍길동')"> v-on:click</button><br>
      <button @click="xxx('홍길동')"> @click</button><br>
      <button @click="xxx('홍길동', $event)"> @click('홍길동', $event)</button><br>
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      num:10
    };
  },
  methods:{
    handleEvent: function(e){
      console.log("handleEvent==========", e);
    }, 
    xxx: function(s, e){
      console.log(s, e);
    }
  }
}
</script>

태그에 속성을 통한 데이터 저장 (상당히 중요)

데이터 저장은 예전에 쓰던 방식 그대로 씀
data-xxx=""

하지만 사용하는 방식은 달라짐
이전에는 this를 통해 쉽게 접근이 가능했는데
여기서 this는 vuecomponent다.

따라서 이벤트 객체를 이용해서 접근을 한다
event.target => 이벤트가 발생한 태그를 가르킨다.
event.target.dataset => DOMStringMap {my: 'aaa', my2: '{"name":"홍길동", "age":"20"}'} 이런 형식의 데이터를 뽑아 쓸 수 있는 DOM객체가 반환된다.

여기서 my2는 json 객체를 문자열의 형식으로 태그에 저장했다.
관건은 작은 따옴표가 밖에 있어야 json형식을 위배하지 않기에 중요하다.
또한 사용하는 곳에서 값에 접근하려면 JSON.parse를 이용해야한다.

<template>
  <div>
    <h1>v-on:이벤트명="처리함수" 또는 @이벤트명="처리함수"</h1>
    <button v-on:click="handleEvent"> v-on:click</button><br>
    <button @click="handleEvent"> @click</button><br>
      <button v-on:click="xxx('홍길동')"> v-on:click</button><br>
      <button @click="xxx('홍길동')"> @click</button><br>
      <button @click="xxx2('홍길동', $event)"> @click('홍길동', $event)</button><br>
      <!-- $event 사용 주의
      속성을 이용한 데이터 전달시 속성이름에 data-을 사용
      함수에서는 data-를 제외한 부분을 사용하게 됨 이벤트.target.dataset으로 확인 -->
      <button v-on:click="handleEvent2"
      data-my="aaa"
      data-my2='{"name":"홍길동", "age":"20"}'>속성을 이용한 데이터 전송</button><br>
      <!-- 문자열로 만들기 위해 "{'name':'홍길동', 'age':'20'}" 주의 -->

      <!-- 연습용 버튼 -->
      <button v-on:click="handleEvent3"
      data-my="aaa"
      data-my2='{"name":"홍길동", "age":"20"}'>속성을 이용한 데이터 전송</button><br>
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      num:10
    };
  },
  methods:{
    handleEvent: function(e){
      console.log("handleEvent==========", e);
    }, 
    xxx: function(s,){
      console.log(s);
    }, 
    xxx2: function(s, e){
      console.log(s, e);
    },
    handleEvent2: function(e){
      console.log(this); //vuecomponent
      console.log("handleEvent2==== event", e);
      console.log(e.target);
      console.log(e.target.dataset);

      console.log("my: ", e.target.dataset.my);
      console.log("my2: ", e.target.dataset.my2);
      console.log("my2.name: ", e.target.dataset.my2.name); //문자열이라 당연히 접근이 안됨  
      console.log("my2.age: ", e.target.dataset.my2.age); //문자열이라 당연히 접근이 안됨  
      let data = JSON.parse(e.target.dataset.my2);
      console.log("my2.name: ", data.name);
      console.log("my2.age: ", data.age);
    },


    handleEvent3: function(e){
      let target = e.target; // 이벤트발생 태그
      let dataset = e.target.dataset; // 데이터가 들어있는 객체
      let jsonData = JSON.parse(e.target.dataset.my2); // 데이터
      console.log(jsonData.name); // 데이터 세부요소 접근
    }
  }
}
</script>

<style>

</style>

v-once

v-once가 설정된 태그는 단 한번만 렌더링 되게 만든다.
Data

<template>
  <div>
    {{ username }}
    <button v-on:click="changeName">changeName</button><br>
    기본:<span>{{ username }}</span><br>
    v-once1:<span>{{ username }}</span><br>
    v-once2:<span v-once>{{ username }}</span><br>

  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      username: "홍길동"
    };
  }, methods:{
    changeName: function(){
      this.username = "이순신";
    }
  }
}
</script>

배열.map 매서드 사용하기 (많이 사용)

간단 요약 : 배열 순회하고 새로운 배열을 리턴시킨다.

https://bigtop.tistory.com/57

배열메서드인 map은 콜백함수를 인자로 받는다.
콜백함수의 인자로는 element, index, array가 있으며, 일반적으로 element, index를 주로 사용한다.
array.map(callback(element, index, array));

여기까지만 보면 forEach와 다를 것이 없지만, 차이점은 마지막줄에서 확인한 것처럼 이 메서드가 실행된 자리에 리턴되는 배열이 있느냐이다.

결과적으로 map은 메서드를 호출한 배열의 길이 만큼의 새로운 배열을 만들어내는 게 핵심인데, 콜백 함수의 return 값을 통해 새로운 배열들의 각 요소를 변형할 수 있다는 특징이 있는 것이다.

간혹 forEach의 기능을 포괄한다고 생각해서, 이런 류의 작업을 모두 map으로만 사용하는 경우도 있는데, 개인적으로는 가급적 목적에 맞는 최적화된 문법을 사용하는 것이 좋다고 생각한다.

<template>
  <div>
    <h1>{{ mesg }}</h1>
    <div v-for="(v,i) in bookList" :key="i">
      <input type="checkbox" v-model="books" v-bind:value="v">
      {{ v.name }}의 정석
      <span>{{ v.price }}</span>
    </div>
    <hr>
    선택교재: <br>
    <div v-for="(v, i) in books" :key="i+10">
      {{v.name}} 정석
    </div>
    
    전체가격 : {{ [getTotal(), total] }}
  </div>
</template>

<script>
export default {
  props:{
    mesg: String
  }, data: function(){
    return {
      bookList:[
        {name:"자바", price:"2000"},
        {name:"jsp", price:"4000"},
        {name:"spring", price:"5000"},
        {name:"jquery", price:"6000"},
        {name:"angular", price:"7000"},
      ],
      books:[], //선택된 책목록 저장
      total:0 //총액
    };
  },
  methods:{
    getTotal: function(){
      // var sum=0;
      // for(var i =0;i<this.books.length;i++){
      //   sum+=parseInt(this.books[i].price);
      // }
      // this.total = sum;
      // console.log(this.total);

      var sum=0;
      var totalbook= this.books;
      totalbook.map(
        function(ele, idx){
          console.log(idx, ele.name, ele.price);
          sum=sum+parseInt(ele.price)
        }
      );
      this.total = sum;
      console.log(this.total);
      return this.total;
    }
  }
}
</script>

<style>

</style>

computed

한번만 호출되는 녀석. 거의 쓰지 않아서 스킵.

watch 속성 (관찰 속성)


1. 주로 긴 시간을 필요로 하는 비동기처리에 사용
2. 데이터가 변경되었을 때 함수가 자동 호출된다.
3. 반드시 함수명과 data 속성명이 일치해야한다.

<template>
  <div>
    <h1>watch 속성</h1>
    값: <input type="text" v-model.number="num"><br>
    변경된 값 : {{ num }}
  </div>
</template>

<script>
export default {
  props:{

  }, data: function(){
    return {
      num:10
    };
  },

  // 1. watch함수명과 속성변수명이 동일해야함
  // 2. mdethod와 computed는 명시적으로 호출해야하지만
  // 3. watch는 자동으로 호출됨
  watch:{
    num:function(changeValue){
      console.log("watch함수 실행======", this.num, "\t", changeValue);
    }
  }
}
</script>
<template>
  <div>
    <h1>{{ mesg }}</h1>
    <div v-for="(v,i) in bookList" :key="i">
      <input type="checkbox" v-model="books" v-bind:value="v">
      {{ v.name }}의 정석
      <span>{{ v.price }}</span>
    </div>
    <hr>
    선택교재: <br>
    <div v-for="(v, i) in books" :key="i+10">
      {{v.name}} 정석
    </div>
    
    전체가격 : {{ total }}
  </div>
</template>

<script>
export default {
  props:{
    mesg: String
  }, data: function(){
    return {
      bookList:[
        {name:"자바", price:"2000"},
        {name:"jsp", price:"4000"},
        {name:"spring", price:"5000"},
        {name:"jquery", price:"6000"},
        {name:"angular", price:"7000"},
      ],
      books:[], //선택된 책목록 저장
      total:0 //총액
    };
  },
  methods:{
  },
  watch:{
    books:function(cv){
      var sum = 0;
      this.books.map(
        (ele, index)=>{sum+=parseInt(ele.price);}
      )
      this.total=sum;

    }
  }
}
</script>

v-on 속성명 동적 바인딩하기

v-on:[변수], @[변수]

<template>
  <div>
      <h1>{{ msg }}</h1>
      <!-- <button @click="처리함수", button v-on=:[속성이름]="처리함수",
      @[속성이름]="처리함수" -->
      <button v-on:[aaa]="handleEvent">v-on:[aaa]</button> <br>
      <button @[bbb]="handleEvent">@[bbb]</button> <br>

      <button @[ccc]="handleEvent">@[ccc]</button> <br>
      <button @[aaa]="handleEvent2" data-my="홍길동"
      data-my2='{"name":"이순신","age":20}'
      >@[aaa] handleEvent2</button> <br>

  </div>
</template>

<script>
export default {
  props:{
    msg:String
  }, data: function(){
    return {
      aaa: "click",
      bbb: "mouseover",
      ccc: "mouseleave"
    };
  },
  methods:{
    handleEvent:function(e){
      console.log("handleEvent====", e)
    },
    handleEvent2:function(e){
      console.log("handleEvent2====", e);
      console.log(e.target.dataset.my);
      console.log(JSON.parse(e.target.dataset.my2).name);
    }
  }
}
</script>
profile
코딩 프로?

0개의 댓글