제목을 어떻게 지어야할 지 고민이었다.
물론 방법을 찾는 과정에서도 검색어를 뭐라고 해야할지도 고민이었다.
일단 하고싶은건, 로컬 변수를 쓰는 페이지나 컴포넌트 내부에 공통으로 자주 쓰이는 함수를 common 화 하는 것이었다.
이전에는 흔하게 functions/common.js 이런식으로 자주 사용되는 함수들을 죄다 모아놓던가 했었다.
함수 별로 각각 사용되는 매개변수들을 일일히 정의하고 넘겨주는 것은 덤이요,,,
최종적으로 선택해서 사용한 방법 Mixins)
redirect to 👉 https://tacit.tistory.com/166
⬇️ 아래는 삽질 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...(?)
'programming > Vue' 카테고리의 다른 글
[Vue] 하위 input 컴포넌트에 상위 data 연결 (emit & v-model) (0) | 2022.07.19 |
---|---|
[Vue] textarea 조건부 랜더링시 focus 이동 안되는 케이스 해결 -> $ref.focus() & nextTick() 메소드 (0) | 2022.07.19 |
[Vue.js] #11 네비게이션 바(NavBar) 만들기 (0) | 2022.03.04 |
[Vue.js] #10 vue-router 데이터 전달하기 (params, props) (0) | 2022.03.04 |
[Vue.js] #9 vue-router 사용하여 메뉴 navigation 링크만들기 (0) | 2022.03.04 |