我有一个页面,它使用 Alpine.js 模板来添加和删除用于输入人员详细信息的表单字段集,并且还应该根据作为隐藏输入传递的人数来更新价格。
添加人员时它工作正常,再次删除人员时也一样。但是如果您在删除后尝试添加,则总数会不正确。
代码如下
<div x-data="add()" x-init="addNew">
<div>
<label for="price">Price:</label>
<input type="text" name="price" id="price" value="100">
</div>
<template x-for="(field, index) in fields" :key="index">
<div>
<p>Person: <span x-text="`${index + 1}`"></span></p>
<div>
<label :for="`first_name_${index + 1}`">First name:</label>
<input
x-model="field.first_name"
type="text"
:name="`first_name_${index + 1}`"
:id="`first_name_${index + 1}`"
>
</div>
<div>
<label :for="`last_name_${index + 1}`">Last name:</label>
<input
x-model="field.last_name"
type="text"
:name="`last_name_${index + 1}`"
:id="`last_name_${index + 1}`"
>
</div>
<button type="button" @click="remove(index)">Remove</button>
</div>
</template>
<button type="button" @click="addNew">Add</button>
</div>
<script>
let priceInput = document.getElementById('price'),
count = 1;
function calcTotal(count) {
if(count==1) priceInput.value = 200;
if(count==2) priceInput.value = 375;
if(count>2) priceInput.value = 550;
}
function add() {
return {
fields: [],
addNew() {
this.fields.push({
first_name: '',
last_name: '',
});
calcTotal(count);
count++;
},
remove(index) {
this.fields.splice(index, 1);
count = index;
calcTotal(count);
}
}
}
</script>
并且我创建了一个CodePen。
价格从 1 人 200 开始,2 人 375,3 人或以上最高 550。如果你用 CodePen 测试,你会发现如果你把 3 个人加起来然后再减回 1 个人,总数就会正确。
但是当您回到 1 并再次添加另一个时,总数不会更新,直到您添加第 3 个(即 375 而不是 550)。
我需要做什么来修复它?
另外,与此特定问题无关,当我创建 CodePen 并选择 Alpine 作为 js 依赖项时,它会自动添加 Alpine 3.1.4.0,但我的项目最初是用 2.xx 创建的,在 CodePen 中使用 3.x 时,不会渲染任何内容<template>
。2 和 3 之间有什么不同导致这种情况?
您设置和更新
count
变量的方式完全错误。我已为您修复了脚本:如您所见,我默认将计数设置为 0,因为您用来
x-init
添加新字段,这会将计数增加到 1(在您的情况下为 2,即使只有一个字段)。我改变了函数中的变量名,
calcTotal
以防止变量冲突。我将其改为
addNew
确保它先递增然后计算,因为您首先添加新字段。我将其改为remove
确保它先递减然后计算,因为您首先删除字段。我不使用它index
来设置计数,因为那根本没有意义(想象一下你有 5 个人,你删除了第 2 个,所以现在只剩下 2 个了??)。this.fields.length
提示:您甚至可以通过仅使用和删除 count 变量来使其更简单(calcTotal(this.fields.length)
)。变量count比index大 1 (因为index从 0 开始),但当你删除一行时,它们会相等。此外,如果你在中间删除一行,count变量的结果会不一致。
这是完整的 AlpineJs 工作版本:
我将所有 Javascript 移到了 Alpine 对象中。
现在,价格字段使用x-model与priceInput变量绑定,因此无需监听器即可自动更新。
由于数组fields[]已经有自己的长度,因此我用它来代替count变量。
我已经为数组行添加了一个唯一的 id,因为当使用splice()压缩数组时,索引也会被压缩,并且Alpine可能会丢失引用。
我还添加了一个 $watch,因此当修改数组时,calcTotal()函数会自动执行。如果您愿意,由于在编辑first_name和last_name时也会调用 calcTotal() 函数,因此您可以删除 $watch 并在addNew()和remove()方法中启用calcTotal()的显式调用
初始化已移至Alpine 对象的init()函数中