본문 바로가기

programming/Vue

[Nuxt] Vue 페이지나 컴포넌트에서 분리된 공통 함수 사용하기

제목을 어떻게 지어야할 지 고민이었다.

 

물론 방법을 찾는 과정에서도 검색어를 뭐라고 해야할지도 고민이었다.

 

일단 하고싶은건, 로컬 변수를 쓰는 페이지나 컴포넌트 내부에 공통으로 자주 쓰이는 함수를 common 화 하는 것이었다.

 

이전에는 흔하게 functions/common.js 이런식으로 자주 사용되는 함수들을 죄다 모아놓던가 했었다.

 

함수 별로 각각 사용되는 매개변수들을 일일히 정의하고 넘겨주는 것은 덤이요,,,

 

 


최종적으로 선택해서 사용한 방법 Mixins)

redirect to 👉 https://tacit.tistory.com/166

 

 

[Nuxt] (mixins 사용법) vue 페이지나 컴포넌트에서 분리된 공통 함수에서 this 사용하기

[Nuxt] Vue 페이지나 컴포넌트에서 분리된 공통 함수 사용하기 [Nuxt] Vue 페이지나 컴포넌트에서 분리된 공통 함수 사용하기 제목을 어떻게 지어야할 지 고민이었다. 물론 방법을 찾는 과정에서도

tacit.tistory.com

 


 

⬇️ 아래는 삽질 history ⬇️

 

예시)

/pages/start.vue : 시작 폼 페이지

<template>
    <form @submit.prevent="submitForm">
        <div class="email-wrapper">
          <label for="email" class="font-15b form-label">이메일</label>
          <input
            v-model="email"
            type="text"
            class="form-input"
            :class="{'input-error': !emailValidation}"
            placeholder="example@domain.com"
            maxlength="100"
            required
            @input="onInputEmail"
          />
          <p v-if="!emailValidation" class="font-15r warning">올바르지 않은 이메일 형식입니다</p>
        </div>

        <div class="phone-wrapper">
          <label for="phone" class="font-15b form-label">연락처</label>
          <input
            v-model="phone"
            class="form-input"
            :class="{'input-error': !phoneValidation}"
            type="text"
            placeholder="010-1234-5678"
            maxlength="20"
            required
            @input="onInputPhone"
          />
          <p v-if="!phoneValidation" class="font-15r warning">올바르지 않은 전화번호 형식입니다</p>
        </div>
        <div class="button-wrapper">
          <button class="font-20b submit-button" type="submit">컨설팅 신청하기</button>
        </div>
    </form>
</template>

 

 

동일한 파일(/pages/start.vue) 함수 부분

<script>
export default {
  name: 'Start',
  data() {
    return {
      email: '',
      phone: '',
      emailValidation: true,
      phoneValidation: true,
      phoneFormat
    }
  },
  methods: {
    onInputEmail() {
      this.email = this.email.replace(/[^a-zA-Z0-9@._]*$/gi, '')
      // 이메일 정규식
      const emailRegex = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/
      // 이메일 정규식 부적합
      if (!emailRegex.test(this.email)) {
        this.emailValidation = false
      } else {
        this.emailValidation = true
      }
    },
    onInputPhone() {
      this.phone = this.phoneFormat(this.phone)
      // 휴대폰 정규식
      const phoneRegex = /^\d{2,3}-\d{3,4}-\d{4}$/
      // 휴대폰 정규식 부적합
      if (!phoneRegex.test(this.phone)) {
        this.phoneValidation = false
      } else {
        this.phoneValidation = true
      }
    }
  }
}
</script>

 

 

phone / email 정규식 체크하고, 포멧 맞춰주는 일을 하는 함수를 공용화 하고 싶었다.

 

방법1) 그냥 평소 쓰던 것 처럼 functions/common.js 에 함수들 정의하고 필요한 인자들을 넘겨줘서 값을 리턴 받기

방법2) functions/common.js 안에 함수를 정의 하지만, 인자를 정의하지 않고, vue 스코프 내부의 this를 전체 전달하기

방법3) plugins/common.js 플러그인으로 빼서 전역함수로 inject 하여 this.$phoneCheck() 로 사용하기

 

 

 

방법1) 예시

 // functions/common.js
 
 export const onInputEmail= (email, emailValidation) => {
  email = email.replace(/[^a-zA-Z0-9@._]*$/gi, '')
  // 이메일 정규식
  const emailRegex = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/
  // 이메일 정규식 부적합
  if (!emailRegex.test(this.email)) {
    emailValidation = false
  } else {
    emailValidation = true
  }
  return email, emailValidation
},

// pages/start.vue

import { onInputEmail } from "~/functions/common.js"

this.phone, this.emailValidation = this.onInputEmail(this.phone, this.emailValidation)

 

- 페이지별로 공통적인 역할을 하는 함수이긴 하지만, 약간씩 달라지는 조건이 있어서, 넘겨줘야할 인자들이 점점 많아지고, 함수 내부에서 분기를 쳐야하는 경우가 생기기도 한다.

- 리턴 받는 값으로 페이지 내부 로컬 변수들에 할당해 주어야한다.

- 참고로 위의 코드가 동작하는지는 모름 ㅋ

 

 

방법2) 지역 this 넘겨주기

// functions/common.js


export const phoneValidate = localThis => {
  localThis.phone = localThis.phoneFormat(localThis.phone)
  // 휴대폰 정규식
  const phoneRegex = /^\d{2,3}-\d{3,4}-\d{4}$/
  // 휴대폰 정규식 부적합
  if (!phoneRegex.test(localThis.phone)) {
    localThis.phoneValidation = false
  } else {
    localThis.phoneValidation = true
  }
}

export const emailValidate = localThis => {
  localThis.email = localThis.email.replace(/[^a-zA-Z0-9@._]*$/gi, '')
  // 이메일 정규식
  const emailRegex = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/
  // 이메일 정규식 부적합
  if (!emailRegex.test(localThis.email)) {
    localThis.emailValidation = false
  } else {
    localThis.emailValidation = true
  }
}

페이지, 컴포넌트 에서 사용하기

// pages/start.vue

<template>
    <form>
        <div class="email-wrapper">
          <label for="email" class="font-15b form-label">담당자 이메일</label>
          <input
            v-model="email"
            type="text"
            class="form-input"
            :class="{'input-error': !emailValidation}"
            placeholder="example@domain.com"
            maxlength="100"
            required
            @input="onInputEmail"
          />
          <p v-if="!emailValidation" class="font-15r warning">올바르지 않은 이메일 형식입니다</p>
        </div>

        <div class="phone-wrapper">
          <label for="phone" class="font-15b form-label">담당자 연락처</label>
          <input
            v-model="phone"
            class="form-input"
            :class="{'input-error': !phoneValidation}"
            type="text"
            placeholder="010-1234-5678"
            maxlength="20"
            required
            @input="onInputPhone"
          />
          <p v-if="!phoneValidation" class="font-15r warning">올바르지 않은 전화번호 형식입니다</p>
        </div>
    </form>
</template>

<script>
import {phoneValidate,emailValidate} from '~/functions/common.js'

export default {
  name: 'Start',
  data() {
    return {
      phoneValidate,
      emailValidate,
      email: '',
      phone: '',
      emailValidation: true,
      phoneValidation: true,
      phoneFormat
    }
  },
  methods: {
    onInputEmail() {
      this.emailValicate(this)
    },

    onInputPhone() {
      this.phoneValidate(this)
    },
  }
}
</script>

 

 

- 냅다 로컬 this를 넘겨버림

- 리턴 할 필요 없이 분리된 함수에서 바로 this.phone = '1231313' 이런식으로 바로 값을 할당 가능

- 분리된 함수 페이지 (functions/common.js) 내부 함수를 화살표함수로 정의하면 함수가 호출된 부모의 this를 참조하므로 지역 this를 인자로 안넘겨줘도 작동할 것이라고 예상했으나, 그렇지 않았다.

- 넘겨주는 인자 없이 functions/common.js 내부의 phoneValidate() 함수 안에서 console.log(this) 를 하면 undefined 가 떴다.

 

 

 

방법3) plugins

전체적으로 2번과 동일하지만 구현 방법의 약간의 차이가 있을 뿐

플러그인을 사용할 뿐,,

 

플러그인 파일 생성 (그냥 functions/common.js 같은 역할)

 

// plugins/common.js

export default (context, inject) => {
  const phoneValidate = localThis => {
    localThis.phone = localThis.phoneFormat(localThis.phone)
    // 휴대폰 정규식
    const phoneRegex = /^\d{2,3}-\d{3,4}-\d{4}$/
    // 휴대폰 정규식 부적합
    if (!phoneRegex.test(localThis.phone)) {
      localThis.phoneValidation = false
    } else {
      localThis.phoneValidation = true
    }
  }
  inject('phoneValidate', phoneValidate)
}

 

 

nuxt.config.js에 plugins 등록

기존에 등록되어있는것 그대로 두고, 리스트 형태로 추가 추가 추가

 

// nuxt.config.js


  // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
    '~/plugins/axios/interceptors.js',
    '~/plugins/vuex-persistedstate',
    '~/plugins/common.js'
  ],

 

페이지나 컴포넌트에서 사용하기

 

// pages/start.vue

<template>
    <form>
        <div class="phone-wrapper">
          <label for="phone" class="font-15b form-label">담당자 연락처</label>
          <input
            v-model="phone"
            class="form-input"
            :class="{'input-error': !phoneValidation}"
            type="text"
            placeholder="010-1234-5678"
            maxlength="20"
            required
            @input="onInputPhone"
          />
          <p v-if="!phoneValidation" class="font-15r warning">올바르지 않은 전화번호 형식입니다</p>
        </div>
    </form>
</template>

<script>
export default {
  name: 'Start',
  data() {
    return {
      phoneValidate,
      phone: '',
      phoneValidation: true,
      phoneFormat
    }
  },
  methods: {
    onInputPhone() {
      this.$phoneValidate(this)
    },
  }
}
</script>

 

- 별도의 import 없이 this.$함수명으로 접근하여 사용할 수 있다.

- input 태그에서 @input=$phoneValidate(this) 로 바로 사용은 불가능 했다.

 

 

 

결론적으로 localThis를 통째로 넘겨주는 방법으로 구현을 할 수 있다는걸 알게 되었으나,,

왜 화살표 함수를 썼는데 호출부의 this 를 읽지 못하는지,

왜 @input 함수에서 바로 사용하지 못하는지, 

 

해결해야할 의문이 남아있다

 

to be...continue...(?)