bdfgdfg

[Vue.js] $refs, 믹스인, Vuex, slot 본문

웹프로그래밍/vuejs

[Vue.js] $refs, 믹스인, Vuex, slot

marmelo12 2023. 12. 5. 23:59
반응형

$refs

refs문법을 이용해 Dom에 직접 접근할 수 있다. 

사실상 document.querySelector로 해당 Dom 요소를 가져와 접근하는것과 동일하다.

 -> 또한 HTML 태그뿐만 아닌, 템플릿에 컴포넌트 태그에도 ref 속성을 정의해서 해당 컴포넌트에 접근할 수 있다(내부 data등 접근가능)

 -> 사실 vue를 쓴다면 태그에 binding된 데이터에 접근하면 되기에 그럴일은 거의 없겠지만은

 

<template>
  <div class="home">
    <HelloWorld ref="child" />
    <button @click="refHandler">ref버튼</button>
  </div>
</template>

<script>
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'HomeView',
  components : {
    HelloWorld
  },
  data() {
    return {
      textMsg : 'idValue',
    }
  },
  methods : {
    refHandler() {
      // refs는 컴포넌트별로 들고있음.
      this.$refs.child.myData = "ref를 통해 데이터를 바꾸었습니다."
      // 자식 컴포넌트의 버튼 요소에 접근하여 클릭이벤트 발생시키기
      this.$refs.child.$refs.childBtn.click();
    }
  }
}
</script>

상위 컴포넌트의 코드.

하위 컴포넌트인 HelloWorld를 자식으로 두고있고, HelloWorld컴포넌트(자식)의 내부 요소에 접근하기 위해 ref버튼을 만들었음.

 

<template>
  <div class="hello">
    <p>{{myData}}</p>
    <button ref="childBtn" @click="testFunc" >버튼</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      myData : '안녕하세요?'
    }
  },
  methods : {
    testFunc() {
      alert('자식 ref를 통해 button접근하여 click발생');
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

하위 컴포넌트의 코드

button의 ref는 상위 컴포넌트에서 ref의 이름을 통해 접근하기 위해서 정의함. 

 

ref버튼 클릭시

정상 동작.

 

요약 : ref키워드는 결국 dom요소에 접근하기 위한 문법.

 

믹스인(mixin)

믹스인은 컴포넌트들이 공통으로 사용중인 로직 과 기능들을 재사용하기 위한 방법.

 -> data,methods,created등..

 

단순 함수나 데이터만을 가져다가 쓸 수 있는게 아닌, 전역적으로 모든 컴포넌트가 created등에서 어떠한 로직이 수행되어야한다면 전역 mixin을 사용하여 모든 컴포넌트에 영향을 줄 수 있다.

 -> 주로 쓰는 방법은 아니라고함.

import { createApp } from 'vue';
import App from './App.vue';
import mixin from './mixin.js';

createApp(App)
	.mixin(mixin)
	.mount('#app');

 

간단하게 mixin js파일을 만들고 자주 사용되는 format기능을 만들어서 써보면

export default {
    data() {
        return {
            mixinItem : '믹스인 데이터'
        }
    },
    methods : {
        yyyyMMddFormat(stringValue) {
            if(
                stringValue == null ||
                typeof stringValue == "undefined" ||
                typeof stringValue != "string"
            ) {
                return null;
            }
            let date = new Date(stringValue);
            let returnValue = 'yyyy-MM-dd';
            return returnValue.replace('yyyy',date.getFullYear())
                              .replace('MM', (('0' + (date.getMonth() + 1)).slice(-2)))
                              .replace('dd', (('0' + date.getDate()).slice(-2)));
        }
    }
}

 

그리고 중요한점. 해당 믹스인을 컴포넌트에서 사용할려면 밑과같이 쓴다.

<template>
  <div class="home">
    <p>{{mixinItem}}</p> <!-- mixin의 data -->
    <hr>
    <input type="text" ref="data">
    <button @click="useMixinFunc">클릭</button>
    <p>{{textMsg}}</p>
  </div>
</template>

<script>
import mixin from '../mixin' // 해당 파일의 객체를 가져와서

export default {
  name: 'HomeView',
  mixins: [mixin], // 추가
  data() {
    return {
      textMsg : '',
    }
  },
  methods : {
    useMixinFunc() {
      // mixin의 함수
      console.log(this.$refs.data.value);
      this.textMsg = this.yyyyMMddFormat(this.$refs.data.value);
    }
  }
}
</script>

 

Vuex

Vuex는 상태를 관리하는 저장소이며, 어느 컴포넌트에서든 접근 가능한(공유하는) 데이터 저장소.

 -> vue에서 공통으로 접근하는 데이터를 관리하기 위해 부모자식간에 데이터를 넘나들면서 작업하기엔 어려운 부분이 있음.

 

그전에 npm i vuex --save 를 통해 vuex npm을 설치하고

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store.js';

createApp(App).use(router).use(store).mount('#app')

main.js에 위의 store를 추가해준다.

 

이후 store.js파일을 만들고 밑의 코드 작성

import { createStore } from 'vuex';

const store = createStore({
    state() {
        return {
            isLogin : false
        }
    },
    //computed처럼 특정 데이터를 가공(로직)하여 반환받을 때.
    //여러 컴포넌트에선 state의 isLogin을 가져다 가공할 필요없이
    // getter에서 정의.
    getters : {
        getAnythingValue() {
            // 암튼 복잡한 로직이 들어가있음
            return 1;
        }
    },  
    mutations : { //동기식, 직접 수정은 못하고 commit을 통해 밑의 함수명을 전달해야함
        reverseLogin(state){
            state.isLogin = !state.isLogin
        }
    },
    // actions : { // 비동기
    //     
    //     
    //     
    // }
});

export default store;

 

그리고 해당 store에 있는 state값을 가져다 써보면

<template>
  <div class="home">
    <p v-if="login">로그인 되었음</p>
    <p v-else>로그인 하세요</p>

    <button @click="clickLogin">로그인하기</button>
  </div>
</template>

<script>
export default {
  name: 'HomeView',
  computed : {
    login() {
      return this.$store.state.isLogin
    }
  },
  methods : {
    clickLogin() {
      this.$store.commit("reverseLogin",null); // 매개변수를 쓰지않으므로 null을넘김
    }
  }
}
</script>

보면 store에 있는 commit이라는 함수를 통해서 호출할 함수명과 인자를 넘겨주면 끝.

 

 

여기서 알아낸점이 하나 더 있는데, data함수는 인스턴스가 생성될 때 호출되는 함수이므로 data함수안에 정의되는 데이터에 초기값들은 그 시점에 값들이 확정되어 있어야한다. 그렇지않으면 오류가 발생.

반응형
Comments