使用 v 模型的值作为 if 语句的条件是否正确?



如何将v-model="item.checked"作为if的条件放在validations()下面?

<table>
<tr v-for="(item, i) of $v.timesheet.items.$each.$iter" >
<div>
<td>
<input 
type="checkbox" 
v-model="item.checked" 
v-on:click="disable(i)"
/>
</td>
<td>
<input 
type="text" 
:id="'total_hour-' + i"
/>
</td>
</div>
</tr>
<tr>
<div>
<td>
<button 
type="button" 
class="btn btn-sm btn-primary" 
@click="itemCount++"
>Add Row
</button>
</td>
</div>
</tr>
</table>
<script>
import { required, minLength } from "vuelidate/lib/validators";
export default {
data() {
return {
itemCount: 1,
timesheet: { items: [{ total_hour: "", checked: false }] },
}
},
methods: {            
disable(index){
const check = 
document.getElementById('total_hour-' + index).disabled
$('#total_hour-' + index).attr('disabled', !check);
}
},
watch: {
itemCount(value, oldValue) {
if (value > oldValue) {
for (let i = 0; i < value - oldValue; i++) {
this.timesheet.items.push({
total_hour: "",
checked: false,
})
}
} else {
this.timesheet.items.splice(value);
}
}
},
validations() {
if (  ?  ) {
return {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { total_hour: {required} }
}
}
}
} else {
return {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: { total_hour: {} }
}
}
}
}
}
}
</script>

所以据我所知,只有当checked为真时,您才希望total_hour是必需的字段。Vuelidate为此提供了一个很好的内置验证器,名为requiredIf。它是一个上下文化的验证器,所以你可以引用同级属性。

import { required, requiredIf, minLength } from 'vuelidate/lib/validators';
export default {
...
validations: {
timesheet: {
items: {
required,
minLength: minLength(1),
$each: {
total_hour: {
required: requiredIf('checked'),
},
},
},
},
},
}

我在你的代码中看到的另一个问题是,你试图迭代$v字段。$v字段用于获取字段的验证状态,您不应该设置$v字段。使用它们作为组件的v-model将使vue设置$v字段。试试这个:

<tr v-for="(item, i) in timesheet.items">

所以,有一些事情可以改进你的代码。

用方法替换watcher

观察者很难调试并且可能导致副作用。它们应该只在真正必要的时候使用。相反,创建一个方法,它添加一行:

addRow() {
this.timesheet.items.push({
total_hour: "",
checked: false,
})
}

对于删除一行,执行相同的操作。只需创建一个方法。

为每个条目创建一个组件

通过为时间表项创建子组件,您可以更容易地处理验证,并且可以更好地对单个条目的更改做出反应。

<table>
<TimesheetItemRow
v-for="(item) of $v.timesheet.items.$each.$iter"
:item="item"
/>
<tr>
...
</tr>
</table>

为了跟踪父组件中的所有时间表项,您可能希望从子组件向父组件发出一个事件,其中包含新条目数据。

不要使用jQuery或JavaScript代码来操作DOM

和以前一样,这些东西应该只在非常非常边缘的情况下使用。像Vue.js这样的前端框架的一个好处是,你不需要这样做。

现在,每个条目都有一个组件,很容易在模板

中直接禁用输入这是时间表项目组件的一些(未经测试的)代码:

<template>
<tr>
<td>
<input 
type="checkbox" 
value="item.checked
@click="onClickCheckbox"
/>
</td>
<td>
<input 
type="text" 
@input="onUpdateTotalHour"
:disabled="!item.checked
/>
</td>
</tr>
</template>
<script>
import { required } from "vuelidate/lib/validators";
export default {
props: {
item: {
type: Object
}
},
methods: {
onClickCheckbox (value) {
this.$emit('on-click-checkbox', value)
},
onUpdateTotalHour (value) {
this.$emit('on-update-total-hour', value)
}
},
validations () {
if (this.item.checked) {
return {
item: {
total_hour: { required }
}
}
}
return {
item: {
total_hour: {}
}
}
}
}
</script>

父组件需要跟踪所有的项,并且需要对发出的事件做出反应。

最新更新