vee-validate는 많이 알려진 input 유효성 검사 라이브러리이다.
vue2와 vue3에서 사용하는 차이점이 있는데
vue2
import Vue from 'vue' import { ValidationProvider, extend, ValidationObserver, localize } from 'vee-validate' import * as rules from 'vee-validate/dist/rules' import ko from 'vee-validate/dist/locale/ko.json' import en from 'vee-validate/dist/locale/en.json'
import {
i18n
} from '@/plugins/i18n'
const customValidate = require.context('@/assets/lang/veeValidate', true, /[A-Za-z0-9-_,\s]+.json$/i)
// loop over all rules
for (let rule in rules) {
extend(rule, rules[rule])
}
const customLocalize = {}
customValidate.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)./i)
if (matched && matched.length > 1) {
const locale = matched[1]
let tmpMessages = customLocalize[locale] || {}
customLocalize[locale] = Object.assign(tmpMessages, customValidate(key))
}
})
localize(i18n.locale)
localize({
ko: Object.assign(ko, customLocalize.ko),
en: Object.assign(en, customLocalize.en)
})
Vue.component('ValidationProvider', ValidationProvider)
Vue.component('ValidationObserver', ValidationObserver)
회사에서는 다국어 처리 프로세스가 있기 때문에 i18n 라이브러리를 사용해 validation 메세지를 커스텀 한 것으로 보인다. i18n에 대해서는 아직 아는게 많이 없기 때문에 더 공부하고 다음 포스팅에 작성 해 보도록 하겠다..
아무튼 vee-validation 라이브러리를 다운 받은 다음 아래 Vue.componet 구문에 각 Id를 할당해 컴포넌트에서 꺼내 사용하는 형식이다.
로그인 컴포넌트를 확인 해 보자
<ValidationObserver v-slot="{ passes }">
<form @submit.prevent="passes(_login)">
<div class="input-group without-label">
<input-text
v-model="userId"
name="userId"
:label="$t('attributes.userId')"
rules="required"
input-type="text"
error-msg-class="errors-msg"
:placeholder="$t('user.id_placeholder')"
></input-text>
</div>
<div class="input-group without-label">
<input-text
v-model="password"
name="password"
:label="$t('attributes.password')"
:rules="{ required: true, max: 16, regex: /(?=.*\d{1,})(?=.*[~`!@#$%\^&*()-+=]{1,})(?=.*[a-z]{1,})(?=.*[A-Z]{1,}).{8,16}$/ }"
input-type="password"
error-msg-class="errors-msg"
:placeholder="$t('user.pw_placeholder')"
></input-text>
</div>
<div>
<button data-cy="login" class="btn gradient-btn">{{ $t("user.login") }}</button>
</div>
<div>
<user-captcha
:user-id="captcha.userId"
:response.sync="captcha.response"
:is-show="captcha.isShow"
></user-captcha>
</div>
<div class="user-login-other-actions">
<div class="left">
<router-link :to="{ name: 'user-agree' }">{{ $t("user.sing_up") }}</router-link>
</div>
<div class="right" :class="{ kor : currentLocale == 'ko' }">
<!-- <router-link :to="{ name: 'user-find-id' }">{{ $t("user.find.id") }}</router-link> -->
<router-link :to="{ name: 'user-find-pwd' }">{{ $t("user.find.pw") }}</router-link>
</div>
</div>
</form>
</ValidationObserver>
위아래 잡다한 코드는 생략하고 ValidationObserver가 적용 되어 있는 부분만 발췌했다.
ValidationObserver태그로 감싸진 부분은 vee-validation이 적용되어 rules="required" 속성을 넣어주면 미리 정해놓은 rule에 따라 validation이 진행된다.
error-msg-class="errors-msg"는 validation에 걸렸을 때 에러 메세지를 나타내는 클래스를 넣어준다.
input-text도 커스텀 해서 사용했는데 속성의 인자로 넘겨준 rules부분에는
<ValidationProvider
:vid=id
:name="name"
:rules="rules"
v-slot="{ errors, invalid }">
<div v-if="label" :class="labelClass">{{ label }}<span v-if="required" class="required"></span>
</div>
<input />
<span :class="errorMsgClass" v-if="invalid" >{{ errors[0] }}</span>
</ValidationProvider>
아래처럼 ValidationProvider로 감싸져있다. 에러 메세지 클래스는 v-slot으로 바인드 되었기 때문에 에러가 발생 할 경우 나타난다.
> vue3
import { defineRule, configure } from 'vee-validate'
import { localize } from '@vee-validate/i18n'
import AllRules from '@vee-validate/rules'
import en from '@vee-validate/i18n/dist/locale/en.json'
import ko from '@vee-validate/i18n/dist/locale/ko.json'
import { i18n } from '@/plugins/i18n'
Object.keys(AllRules).forEach((rule) => {
defineRule(rule, AllRules[rule])
})
const customValidate = require.context(
'@/assets/lang/veeValidate',
true,
/[A-Za-z0-9-_,\s]+.json$/i
)
const customLocalize = {}
customValidate.keys().forEach((key) => {
const matched = key.match(/([A-Za-z0-9-_]+)./i)
if (matched && matched.length > 1) {
const locale = matched[1]
const tmpMessages = customLocalize[locale] || {}
customLocalize[locale] = Object.assign(tmpMessages, customValidate(key))
}
})
localize(i18n.global.locale.value)
configure({
validateOnInput: true,
generateMessage: localize({
ko: Object.assign(ko, customLocalize.ko),
en: Object.assign(en, customLocalize.en)
})
})
vue3는 vue2와 크게 달라진 점은 없지만 id를 할당하지 않고 configure구문에 작성한다.
똑같이 login컴포넌트와 input을 살펴보자
<Form @submit="_login">
<input-text
name="userId"
:rules="{ required: true }"
v-model="userId"
label="아이디"
type="textArea"
/>
<input-text
name="password"
type="password"
:rules="{
required: true,
max: 16,
regex:
/(?=.*\d{1,})(?=.*[~`!@#$%\^&*()-+=]{1,})(?=.*[a-z]{1,})(?=.*[A-Z]{1,}).{8,16}$/,
}"
v-model="password"
label="비밀번호"
/>
<button class="btn btn-primary">{{ t("login_label") }}</button>
</Form>
validationObserver 대신 Form태그로 감쌌고 provider 대신 Field 태그로 validation을 걸어준다. ErroMessageClass도 slot으로 구현하지 않고 직접 넣어준다.
두 버전 모두 validation에 걸리면 submit에 작성 한 메서드가 실행되지 않는다.