AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 78610825
Accepted
Tyssen
Tyssen
Asked: 2024-06-12 13:50:34 +0800 CST2024-06-12 13:50:34 +0800 CST 2024-06-12 13:50:34 +0800 CST

Alpine.js 函数在添加/删除项目时更新总数不正确

  • 772

我有一个页面,它使用 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 之间有什么不同导致这种情况?

javascript
  • 2 2 个回答
  • 22 Views

2 个回答

  • Voted
  1. Best Answer
    Yinci
    2024-06-12T14:26:49+08:002024-06-12T14:26:49+08:00

    您设置和更新count变量的方式完全错误。我已为您修复了脚本:

    <script>
      let priceInput = document.getElementById('price'),
          count = 0;
    
      function calcTotal(total) {
        console.log(total);
        if(total==1) priceInput.value = 200;
        if(total==2) priceInput.value = 375;
        if(total>2)  priceInput.value = 550;
      }
    
      function add() {
        return {
          fields: [],
          addNew() {
            this.fields.push({
              first_name: '',
              last_name: '',
            });
            ++count;
            calcTotal(count);
          },
          remove(index) {
            this.fields.splice(index, 1);
            --count;
            calcTotal(count);
          }
        }
      }
    </script>
    

    如您所见,我默认将计数设置为 0,因为您用来x-init添加新字段,这会将计数增加到 1(在您的情况下为 2,即使只有一个字段)。

    我改变了函数中的变量名,calcTotal以防止变量冲突。

    我将其改为addNew确保它先递增然后计算,因为您首先添加新字段。我将其改为remove确保它先递减然后计算,因为您首先删除字段。我不使用它index来设置计数,因为那根本没有意义(想象一下你有 5 个人,你删除了第 2 个,所以现在只剩下 2 个了??)。

    this.fields.length提示:您甚至可以通过仅使用和删除 count 变量来使其更简单( calcTotal(this.fields.length))。

    • 1
  2. TUPKAP
    2024-06-12T15:25:23+08:002024-06-12T15:25:23+08:00

    变量count比index大 1 (因为index从 0 开始),但当你删除一行时,它们会相等。此外,如果你在中间删除一行,count变量的结果会不一致。

    这是完整的 AlpineJs 工作版本:

    <div x-data="add()">
    
        <div>
            <label for="price">Price:</label>
            <input type="text" name="price" x-model="priceInput"">
        </div>
    
        <template x-for="(field, index) in fields" :key="field.id">
    
            <div>
    
                <p>Person: <span x-text="`${index + 1}`"></span></p>
    
                <div>
    
                    <label>
    
                        First name:
    
                        <input
                                x-model="field.first_name"
                                type="text"
                                :name="`first_name_${index + 1}`"
                        >
    
                    </label>
    
                </div>
    
                <div>
    
                    <label>
    
                        Last name:
    
                        <input
                                x-model="field.last_name"
                                type="text"
                                :name="`last_name_${index + 1}`"
                        >
    
                        </label>
    
                </div>
    
                <button type="button" @click="remove(index)">Remove</button>
    
            </div>
    
        </template>
    
        <button type="button" @click="addNew">Add</button>
    
    </div>
    
    <script>
    
        function add() {
    
            return {
    
                fields: [],
                priceInput: 100,
    
                init() {
                    
                    this.$watch('fields', () => this.calcTotal());
                    this.addNew();
                },
    
                calcTotal() {
    
                    const count = this.fields.length;
    
                    if (count === 1) {
                        this.priceInput = 200;
                    }
                    else if (count === 2) {
                        this.priceInput = 375;
                    }
                    else if (count > 2) {
                        this.priceInput = 550;
                    }
                },
    
                addNew() {
    
                    this.fields.push ({
    
                        id: Date.now(),
                        first_name: '',
                        last_name: '',
                    });
    
                    // this.calcTotal();  //-- enable this if $watch is removed
                },
    
                remove(index) {
    
                    this.fields.splice(index, 1);
    
                    // this.calcTotal();  // -- enable this if $watch is removed
                }
            }
        }
    
    </script>
    

    我将所有 Javascript 移到了 Alpine 对象中。

    现在,价格字段使用x-model与priceInput变量绑定,因此无需监听器即可自动更新。

    由于数组fields[]已经有自己的长度,因此我用它来代替count变量。

    我已经为数组行添加了一个唯一的 id,因为当使用splice()压缩数组时,索引也会被压缩,并且Alpine可能会丢失引用。

    我还添加了一个 $watch,因此当修改数组时,calcTotal()函数会自动执行。如果您愿意,由于在编辑first_name和last_name时也会调用 calcTotal() 函数,因此您可以删除 $watch 并在addNew()和remove()方法中启用calcTotal()的显式调用

    初始化已移至Alpine 对象的init()函数中

    • 1

相关问题

  • 合并排序不起作用 - Javascript代码:即使在调试后也无法找到错误

  • select.remove() 方法工作得很奇怪[关闭]

  • useOpenWeather() 中总是出现 401 res -react-open-weather lib [重复]

  • 输入元素没有只读属性,但字段仍然不可编辑[关闭]

  • 如何编辑 D3.js RadialTree 的第一个节点半径?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行?

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    何时应使用 std::inplace_vector 而不是 std::vector?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Martin Hope
    Aleksandr Dubinsky 为什么 InetAddress 上的 switch 模式匹配会失败,并出现“未涵盖所有可能的输入值”? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge 为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini 具有指定基础类型但没有枚举器的“枚举类”的用途是什么? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer 何时应使用 std::inplace_vector 而不是 std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB 为什么 GCC 生成有条件执行 SIMD 实现的代码? 2024-02-17 06:17:14 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve