ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Vue.js] 계산된 속성 computed vs methods
    Front-End/Vue.js 2022. 11. 13. 12:51

     

    vue를 사용하면서 el, data, method 값을 정의할 수 있었다. 만약 버튼 클릭 시 1씩 증가하는 로직이 있다고 했을 때 보통 method에 이러한 로직을 처리한다. 그러나 html 에서 {{ }} 내에서 js 로직을 처리할 수도 있고 <button v-on:click="count++">와 같이 html 태그안에 직접 js 코드를 넣어줘도 가능하다. 하지만 이런 템플릿 내의 표현식은 단순한 연산에서만 사용이 가능하기 때무에 복잡한 계산식을 계산해서 값을 return 해주는 "계산된 속성"이라는 computed가 필요하다. 

     

     

    📑 computed 

     

    만약 count의 값이 1씩 증가할 때 값이 10보다 커지면 10보다 큽니다 라는 문구를 출력하도록 작성해보자. 

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Computed</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    </head>
    <body>
    
        <div id="app">
            {{ isLargerThanTen }} 
            <button v-on:click="count++">클릭</button>
        </div>
    
        <script>
    
            new Vue({
                el : '#app',
                data : { 
                    count : 0
                },
                computed : {
    
                    isLargerThanTen : function(){
                        return this.count * 3 >10 ? "10보다 큽니다." : "10보다 작거나 같습니다."
                    }
    
                }
    
    
            })
    
        </script>
        
    </body>
    </html>

     

     

    클릭 버튼을 4번째 누름과 동시에 10보다 큽니다라는 문구가 뜨게 된다.

     

     

    이 형태는 methods를 호출하여 같은 결과를 얻을 수 있다는 사실을 알고있다. 위에서 작성한 코드에서 computed를 methods로 바꾸고 {{ isLargerThanTen }} 을 {{ isLargerThanTen() }} 함수 선언으로 바꾸면 같은 결과를 나타낼 수 있다. 그렇다면 methods와 computed의 차이는 무엇일까??

     

     

     

    📑 computed vs methods

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Computed</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    </head>
    <body>
    
        <div id="app">
            <div id="app">
                <p>count: {{ count }}</p>
                <p>computed: {{ double }}</p>
                <p>methods: {{ triple() }}</p>
                <button v-on:click="count ++">클릭</button>
              </div>
        </div>
    
        <script>
    
            new Vue({
                el : '#app',
                data : { 
                    count : 0
                },
                computed: {
                    double: function () {
                    return this.count * 2
                    }
                },
                methods :{
                    triple : function(){
                        return this.count *3
                    }
                }
    
    
            })
    
        </script>
        
    </body>
    </html>

     

     

    data 객체 내에 count라는 변수를 만들고 count의 값을 1씩 증가시켜 주는 버튼을 만든다. computed 내에는 double, methods 내에는 triple로 숫자를 증가시키는 함수 로직을 생성했다.

     

     

     

     

    결과만을 봤을 땐 methods와 computed의 큰 차이가 없어 보인다. 그럼 몇가지 코드를 더 추가해보자.  

    아래 scondCount라는 vue 변수를 하나 생성했다. 이 변수는 mtehods, computed에서는 전혀 사용되지 않고 있는 그냥 무관한 변수이다.  버튼을 통해 각 함수에 맞춰 값이 올라가는 걸 확인해 보자.

     

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Computed</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    </head>
    <body>
    
        <div id="app">
            <div id="app">
                <p>count: {{ count }}</p>
                <p>secondCount: {{ secondCount }}</p>
                <p>computed: {{ double }}</p>
                <p>methods: {{ triple() }}</p>
                <button v-on:click="count ++">클릭</button>
                <button v-on:click="secondCount ++">클릭</button>
    
              </div>
        </div>
    
        <script>
    
            new Vue({
                el : '#app',
                data : { 
                    count : 0,
                    secondCount : 0
                },
                computed: {
                    double: function () {
                        console.log('Computed double')
                    return this.count * 2
                    }
                },
                methods :{
                    triple : function(){
                        console.log('Methods triple')
                        return this.count *3
                    }
                }
    
    
            })
    
        </script>
        
    </body>
    </html>

     

     

    1번 버튼을 총 4번 클릭한 다음, 2번 버튼을 3번 클릭했을 때 결과 값이다. 즉) computed 내의 double()은 자신이 참고하고 있는 count 값이 변경될 때만 재실행 되었고, methods내 triple()은 자신이 참고하고 있는 count가 변경될 때는 물론이고, 자신의 계산식과는 상관 없는 secondsCount가 변경될 때도 실행 되었다. 

     

     

     

     

    우리는 application을 만들 때 지금 예제처럼 단순한 작업뿐만이 아닌 복잡한 계산도 하게 된다. methods와 computed 내에는 수많은 함수들이 서로의 값을 참고하고 계산하는 복잡한 application을 만들게 되는 것이다. 이때 값이 변경될 때마다 새로 재실행 된다면 어떻게 될까 매우 비효율적으로 동작하게 된다. 이를 피하기 위해 VueJs에서는 모든상황에 재실행 되는 methods와 달리 참고하고 있는 값의 변경만 재실행 하는 computed를 제공하는 것이다. 

     

     

     

    또한 computed는 get/set을 제공한다. 만약 아래와 같이 vue를 정의해 뒀을 때 vuecompute.a를 호출하면 1의 값을 출력한다. 만약 vuecompute.aPlus라는 computed 내의 함수를 호출했을 때 값 저장 없이 그냥 함수만 호출한 것이면 get function()이, fn_compute2 함수처럼 값을 vuecompute.aPlus에 저장하면 set function이 실행된다. ! 따라서 fn_compute2 는 2가 출력된다. 

     

    vuecompute = new Vue({
                  data: { a: 1 },
                  computed: {
                                // get only, just need a function
                                aDouble: function () {
                                  return this.a * 2
                                },
                                // both get and set
                                aPlus: {
                                              get: function () {
                                                return this.a + 1
                                              },
                                              set: function (v) {
                                                this.a = v - 1
                                              }
                                      }
                             }
                });
                
     function fn_compute1() {
    		 alert("vuecompute.a : " + vuecompute.a + " vuecompute.aPlus : " + vuecompute.aPlus);
    	 }
    	 
    	 function fn_compute2() {
    		 vuecompute.aPlus = 3
    		 alert("vuecompute.a : " + vuecompute.a);
    	 }
    	 
    	 function fn_compute3() {
    		 alert("vuecompute.a : " + vuecompute.a);
    	 }
    	 
    	 function fn_compute4() {
    		 alert("vuecompute.a" + vuecompute.a + " vuecompute.aDouble : " + vuecompute.aDouble);
    	 }

     

    반응형

    댓글

Designed by Tistory.