javascript - 如何使用 Vue.js 进行表单向导进行验证
问题描述
我正在使用 Vue.Js 做一个小项目,我按照视频教程创建向导,但现在我尝试使用我已经创建的两个 css 类来验证表单'is-valid'和'is-invalid ' 但我的验证不起作用,这是我的代码
<div class="modal-content tx-14">
<div class="p-0 bg-ui-01">
<ul class="nav nav-tabs nav-justified" id="myTab3" role="tablist">
<li class="nav-item m-0">
<a class="nav-link border-0 rounded-0" id="home-tab3" data-toggle="tab" href="#home3" role="tab" aria-controls="home" aria-selected="true" :class="{'active':current_step == 1}" @click.prevent="goToStep(1)">Website</a>
</li>
<li class="nav-item m-0">
<a class="nav-link border-0 rounded-0" id="profile-tab3" data-toggle="tab" href="#profile3" role="tab" aria-controls="profile" aria-selected="false" :class="{'disabled':max_step < 2, 'active': current_step == 2}" @click.prevent="goToStep(2)">Location</a>
</li>
<li class="nav-item m-0">
<a class="nav-link border-0 rounded-0" id="contact-tab3" data-toggle="tab" href="#contact3" role="tab" aria-controls="contact" aria-selected="false" :class="{'disabled':max_step < 3, 'active': current_step == 3}" @click.prevent="goToStep(3)">Keywords</a>
</li>
<li class="nav-item m-0">
<a class="nav-link border-0 rounded-0" id="contact-tab3" data-toggle="tab" href="#contact4" role="tab" aria-controls="contact" aria-selected="false" :class="{'disabled':max_step < 4, 'active': current_step == 4}" @click.prevent="goToStep(4)">Crawler</a>
</li>
<li class="nav-item m-0">
<a class="nav-link border-0 rounded-0" id="contact-tab3" data-toggle="tab" href="#contact4" role="tab" aria-controls="contact" aria-selected="false" :class="{'disabled':max_step < 5, 'active': current_step == 5}" @click.prevent="goToStep(5)">Competition</a>
</li>
</ul>
</div>
<div class="modal-body">
<div class="tab-content" id="myTabContent">
<div class="fade show active" id="home" role="tabpanel" aria-labelledby="home-tab" v-show="current_step == 1">
<h4 class="text-center">Create Your Project</h4>
<p class="text-center">Enter your website informations, so you can track and improve your SEO traffic and keep an eye on the competition.</p>
<div class="row row-sm">
<div class="col-sm-12">
<div class="form-group">
<input type="url" id="project_url" v-model="rules.project_url.string" class="form-control" placeholder="Project URL">
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" id="project_name" v-model="rules.project_name.string" placeholder="Project name">
</div>
</div>
</div>
</div>
<div id="location" role="tabpanel" aria-labelledby="profile-tab" v-show="current_step == 2">
<h4 class="text-center">Choose Your Location</h4>
<p class="text-center">
Enter all of the countries or cities you do business in or want traffic from. We recommend that you add at least 3 locations.
</p>
<div class="row row-sm">
<div class="col-sm-4">
<div class="form-group">
<select class="custom-select">
<option selected>Select Engine</option>
<option value="1">Google</option>
<option value="2">Google Mobile</option>
</select>
</div>
</div>
<div class="col-sm-8">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
</div>
<div class="row row-sm">
<div class="col-sm-4">
<div class="form-group">
<select class="custom-select">
<option selected>Select Engine</option>
<option value="1">Google</option>
<option value="2">Google Mobile</option>
</select>
</div>
</div>
<div class="col-sm-8">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
</div>
</div>
<div id="keywords" role="tabpanel" aria-labelledby="contact-tab" v-show="current_step == 3">
<h4 class="text-center">Add Keywords</h4>
<p class="text-center">
Choose the keywords you would like to track across the selected search engines. Track on the national level, or add locations to track on the local level. Add labels to group keywords by topic.
</p>
<textarea class="form-control" cols="30" rows="10" placeholder="Add separated keywords by comma ex: pasta,fish"></textarea>
</div>
<div id="crawling" role="tabpanel" aria-labelledby="contact-tab" v-show="current_step == 4">
<h4 class="text-center">Set Crawl Limit</h4>
<p class="text-center">
We crawl your site weekly to surface technical site issues that may be impacting your SEO performance. Select the number of pages you’d like to have crawled on this site.
</p>
<div class="row row-sm">
<div class="col-sm-4">
<div class="form-group">
<select class="custom-select">
<option value="5000">5,000</option>
<option value="10000">10,000</option>
<option value="20000">20,000</option>
<option value="30000">30,000</option>
<option value="40000">40,000</option>
<option value="50000">50,000</option>
<option value="75000">75,000</option>
<option value="100000">100,000</option>
<option value="250000">250,000</option>
<option value="450000">450,000</option>
</select>
</div>
</div>
<div class="col-sm-8">
<div class="form-group">
<select class="custom-select">
<option selected>Whole Website</option>
<option value="1">Exclude sub-domains</option>
<option value="2">Follow sitemap</option>
</select>
</div>
</div>
</div>
</div>
<div id="crawling" role="tabpanel" aria-labelledby="contact-tab" v-show="current_step == 5">
<h4 class="text-center">Benchmark vs Competitors</h4>
<p class="text-center">
We will track competitive link and keyword metrics for these sites.
</p>
<div class="row row-sm">
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<input type="text" class="form-control" placeholder="Target Location">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary tx-13" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary tx-13" @click="advanceStep">
<span v-if="max_step === 5">Submit</span>
<span v-else>Next</span>
</button>
</div>
</div>
Javascript
<script>
new Vue({
el: "#page",
delimiters: ['[[', ']]'],
data (){
return {
rules: {
project_url: {
pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,
string: ''
},
project_name: {
pattern: /^(?!\s*$).+/,
string: ''
}
},
current_step: 1,
max_step: 1
}
},
methods:{
is_valid(rules){
$.each(rules, function(index, value){
if (value.string.match(value.pattern)) {
$('#' + index).removeClass('is-invalid')
$('#' + index).addClass('is-valid')
nextStep = true
} else {
$('#' + index).removeClass('is-valid')
$('#' + index).addClass('is-invalid')
nextStep = false
}
})
return nextStep
},
validate(){
if(this.current_step === 1){
if(this.is_valid(this.rules))
return true
}
if(this.current_step === 2)
return true
if(this.current_step === 3)
return true
if(this.current_step === 4)
return true
if(this.current_step === 5)
return true
},
goToStep(value){
if(!this.validate())
return
this.current_step = value
},
submitForm(){
alert("submit")
},
advanceStep(){
if(!this.validate())
return
if(this.max_step === 5)
return this.submitForm()
this.current_step++
if(this.max_step < this.current_step)
this.max_step = this.current_step
}
}
})
</script>
谁能清理我的代码并帮助我添加表单验证
解决方案
基本思想是您不验证表单本身,而是验证表单中显示的数据。
您可能会认为“但它们是相同的”或“这是一个细微的区别”,但不是。
使用jQuery,您正在浏览表单 UI - 应用程序的一部分,这是许多其他事情的最终结果。不要那样做。将表单数据存储在Vue的 data 选项中,并且只显示验证结果。
Vue.component('InputField', {
props: ['error', 'value'],
computed: {
inputValue: {
get() {
return this.value
},
set(val) {
this.$emit("update:value", val)
}
},
},
template: `
<div
class="input-field-wrapper"
:class="{ error: error }"
>
<label>
INPUT:
<input
type="text"
placeholder="Type in something"
v-model="inputValue"
/>
<span v-if="error">this field is required!</span>
</label>
</div>
`
})
new Vue({
el: "#app",
data() {
return {
form: [],
canSubmit: false,
}
},
methods: {
handleAddInput(id) {
this.form.push({
id,
error: null,
value: null,
})
},
handleFormValidate() {
this.form = this.form.map(({ id, error, value }) => {
return {
id,
error: !value,
value,
}
})
return this.form.every(({
error
}) => !error)
},
handleResetValidation() {
this.form = this.form.map(field => {
return {
...field,
error: false
}
})
},
handleSubmitForm() {
this.canSubmit = this.handleFormValidate()
},
},
template: `
<div>
<button
@click="handleAddInput(form.length + 1)"
>ADD INPUT FIELD +</button>
<button
@click="handleFormValidate"
>VALIDATE FORM</button>
<button
@click="handleResetValidation"
>RESET VALIDATION</button>
<hr />
<form>
<input-field
v-for="(inputField, i) in form"
:key="inputField.id"
:error="inputField.error"
:value.sync="inputField.value"
></input-field>
<hr />
<button type="submit" @click.prevent="handleSubmitForm">SUBMIT FORM</button>
</form>
FORM CAN BE SUBMITTED: {{ canSubmit }}
</div>
`
})
.input-field-wrapper {
padding: 8px 16px;
color: black;
}
.input-field-wrapper.error {
color: white;
background: red;
transition: all 0.1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
这个怎么运作
上面的代码片段非常简单:
- 它有 data 属性 (
form
) 存储我们想要通过表单获取的所有数据和非常重要的错误状态 - 在ADD INPUT FIELD +
form
属性中推送一个新对象 - 模板为它在data 属性
InputField
中找到的每个对象呈现一个组件form
- 该
InputField
组件实际上什么都不做,只呈现一个文本输入元素(带有错误类,如果输入字段未验证)并将文本输入的值发送回父级(以便可以将其存储在其form
数据中) - 在VALIDATE FORM上,我们循环遍历
form
数据,检查value
每个元素,并设置error
ifvalue
不验证(这里的规则是一个简单的“它是否有值?”,但可以进行任何验证)。状态在组件 ( )error
上向下传递,并且该组件立即对状态更改做出反应InputField
:error="inputField.error"
- 在SUBMIT FORM上,我们运行验证方法并输出验证结果(它可能是实际提交表单的一个守卫)
- 在RESET VALIDATION我们清除每个
form
项目的错误状态(从而重置InputFields
组件中的错误显示)
您可以看到,如果您以“数据驱动”方式设置组件,则无需直接接触 DOM(这是非常罕见的,您确实无法避免通过合理的工作量来干预 DOM) . 如果你将数据和 UI 解耦,你就有更多的自由来制定应用程序的逻辑。
而且你不需要jQuery来完成这项工作。
推荐阅读
- shopify - 将液体对象分配给 Shopify 中的变量
- laravel - 如何获取 Laravel belongsTo 关系的所有记录(相关和非相关)?
- reactjs - 如果我使用 CSS 模块,如何在反应中添加另一个类名?
- qiime - 在 MacOS Mojave 上安装 qiime1 时出错
- r - y轴上具有多个变量的折线图逐步
- python - 如何在Python中初始化数据类中的属性时调用类公共方法?
- asp.net - C# DataTable 返回空白行
- r - 如何在带有lm的R中的多元线性回归中使用权重?
- postgresql - postgresql 将 csv 复制到表中
- javascript - 使用 javascript 和一些跨浏览器支持向 svg 添加内容