笔记-input type=‘number‘ 可以输入e问题

import React, { useState } from 'react';

function App() {
  const [value, setValue] = useState('');
  const handleInput = (e) => {
    const input = e.target.value;
   
      setValue(input);
   
  };
  return (
    <>
      <input type='number' value={value} onChange={handleInput} />
    </>
  );
}

export default App;

输入后发现还可以输入 “e”?(同样问题在Material UI 的TextField使用中,也会出现该问题)
在这里插入图片描述

input type=‘number’ 中为什么可以输入“e”呢?以下为百度搜索的资料
在HTML的input元素中,type属性为"number"的输入框通常用于接收数字输入。然而,即使设置了"type=number",输入框仍然允许输入科学计数法表示的数字,包括 “e” 或 “E”。
科学计数法是一种表示非常大或非常小的数字的方法,通过使用乘以10的幂来表示。例如,1亿可以表示为1e8,0.000001可以表示为1e-6。
因此,当用户在"type=number"的输入框中输入类似于"1e8"或"1e-6"的值时,浏览器会将其解释为相应的科学计数法表示的数字,并将其视为有效的输入。但需要注意的是,并非所有浏览器都支持科学计数法的输入,因此在实际使用中可能会有一些差异。

我想到的方法:在setValue之前加个正则判断,为纯数字才让它set进去
前言:
1、在if判断中需要加 input===“” , 因为可以让输入的数字清空

function App() {
  const [value, setValue] = useState('');
  const handleInput = (e) => {
    const reg = /^\d+$/;
    const input = e.target.value;
    if (reg.test(input) || input === '') {
      console.log('输入的值为:', input);
      setValue(input);
    }
  };
  return (
    <>
      <input type="number" value={value} onChange={handleInput} />
    </>
  );
}

我在此处连续输入:123e45 结果会存在帮我清空输入框的问题
在这里插入图片描述造成分析:
当我输入123e的时候,控制台输出:输入的值为空==>“”(什么原因我也不清楚),因为输入的值变成了“” ,所以进入到我们if判断中的input===“”,所以setValue成功
解决方法:换个思路把 input 标签中的 type="number"删除,把他当做一个普通的输入框去使用,再使用纯数字的正则去匹配value

import React, { useState } from 'react';

function App() {
  const [value, setValue] = useState('');
  const handleInput = (e) => {
    const reg = /^\d+$/;
    const input = e.target.value;
    if (reg.test(input) || input === '') {
      console.log('输入的值为:', input);
      setValue(input);
    }
  };
  return (
    <>
      <input value={value} onChange={handleInput} />
    </>
  );
}

export default App;

上图:我再次输入:123e456
在这里插入图片描述
问题已经解决!

<template> <el-table :data="tableData" style="width: 100%"> <el-table-column type="selection" width="55"/> <el-table-column label="产品名称" width="220"> <template #default="scope"> <div class="product-name-wrapper"> <el-link type="primary" :underline="false" @click="goToProductDetail(scope.row.id)"> <span >{{ scope.row.name }}</span> <span style="color: brown;" >※点击进入详细画面</span> </el-link> </div> </template> </el-table-column> <el-table-column property="categoryName" label="产品分类"width="120"/> <el-table-column property="price" label="产品单价"width="120"/> <el-table-column property="createAt" label="生产日期"width="250"/> <el-table-column property="price" label="单价"width="120"/> <el-table-column property="stock" label="库存"width="120"/> <el-table-column label="购买数量" width="180"> <template #default="scope"> <div class="quantity-control"> <el-input-number v-model="scope.row.number" :min="0" :max="scope.row.stock" size="small" controls-position="right" @change="handleQuantityChange(scope.$index,scope.row)" /> </div> </template> </el-table-column> <el-table-column label="合计" width="120"> <template #default="scope"> {{ formatCurrency(scope.row.price * scope.row.number) }} </template> </el-table-column> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.$index,scope.row)"> 编辑 </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index,scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> </template> <script setup> const router = useRouter(); const user = "aaa" import productApi from '@/api/products' import { ref } from 'vue'; const goToProductDetail = (productId) => { router.push(`/home/test${productId}`) } const handleEdit = (index, row) => { console.log(index, row) } const handleDelete = (index, row) => { console.log(index, row) } // 处理数量变化事件 const handleQuantityChange = (index, row) => { console.log(`产品 ${row.name} 数量更新为: ${row.number}`); // 这里可以添加更新合计金额的逻辑 } const formatCurrency = (value) => { const numValue = parseFloat(value); // 先转换为数字 if (isNaN(numValue)) { return '¥0.00'; } return `¥${Math.abs(numValue).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}`; }; //商品一览 function getProduct() { productApi.getAll(user).then(res => { tableData.value = res.data; }) } onMounted(() => { getProduct(); }) const tableData = ref(); </script> <style scoped> .aaa-tag { display: inline-block; background-color: #409eff; color: white; font-size: 12px; padding: 0 4px; border-radius: 3px; margin-right: 5px; } </style> 购买数量默认是0
最新发布
07-11
<think>根据要求,我们需要将购买数量的默认值设置为0,并且确保计算正确。同时,我们注意到在模板中,`el-input-number`的`:min`已经设置为0,这样用户可以将数量调整为0。但是,在数据初始化时,我们需要确保每一行的`number`字段初始值为0。 问题分析: 1. 从API获取的数据可能没有`number`字段,或者该字段不是0。 2. 在计算合计时,如果数量为0,则合计应为0。 解决方案: 在获取商品数据后,遍历数据,为每个商品对象添加`number`字段,并初始化为0。 修改`getProduct`函数: ```javascript function getProduct() { productApi.getAll(user).then(res => { if (res.data && Array.isArray(res.data)) { tableData.value = res.data.map(item => ({ ...item, number: 0 // 设置默认购买数量为0 })); } else { console.error('API返回的数据格式不正确'); tableData.value = []; // 设置为空数组避免后续错误 } }).catch(error => { console.error('获取商品数据失败:', error); tableData.value = []; // 出错时也设置为空数组 }); } ``` 另外,在模板中,我们使用了`scope.row.price * scope.row.number`来计算合计。由于我们设置了`number`为0,所以默认合计为0。 但是,我们还需要注意: 1. 确保`price`是数字类型。如果API返回的`price`是字符串,则计算会出错(字符串乘以数字会得到NaN)。因此,在数据映射时,我们也应该将`price`转换为数字。 修改后的`getProduct`函数: ```javascript function getProduct() { productApi.getAll(user).then(res => { if (res.data && Array.isArray(res.data)) { tableData.value = res.data.map(item => ({ ...item, price: parseFloat(item.price) || 0, // 转换为数字,如果转换失败则用0 number: 0 // 默认购买数量为0 })); } else { console.error('API返回的数据格式不正确'); tableData.value = []; } }).catch(error => { console.error('获取商品数据失败:', error); tableData.value = []; }); } ``` 此外,在格式化货币的函数中,我们已经处理了非数字的情况,所以即使计算出现NaN,也会显示¥0.00。 完整代码: ```html <template> <el-table :data="tableData" style="width: 100%"> <el-table-column type="selection" width="55"/> <el-table-column label="产品名称" width="220"> <template #default="scope"> <div class="product-name-wrapper"> <el-link type="primary" :underline="false" @click="goToProductDetail(scope.row.id)"> <span >{{ scope.row.name }}</span> <span style="color: brown;" >※点击进入详细画面</span> </el-link> </div> </template> </el-table-column> <el-table-column property="categoryName" label="产品分类" width="120"/> <!-- 注意:这里有两个price列,我删除了一个重复的,并调整了标签 --> <el-table-column label="产品单价" width="120"> <template #default="scope"> {{ formatCurrency(scope.row.price) }} </template> </el-table-column> <el-table-column property="createAt" label="生产日期" width="250"/> <el-table-column property="stock" label="库存" width="120"/> <el-table-column label="购买数量" width="180"> <template #default="scope"> <div class="quantity-control"> <el-input-number v-model="scope.row.number" :min="0" :max="scope.row.stock" size="small" controls-position="right" @change="handleQuantityChange(scope.$index,scope.row)" /> </div> </template> </el-table-column> <el-table-column label="合计" width="120"> <template #default="scope"> {{ formatCurrency(scope.row.price * scope.row.number) }} </template> </el-table-column> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.$index,scope.row)"> 编辑 </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index,scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> </template> <script setup> import { ref, onMounted } from 'vue'; import { useRouter } from 'vue-router'; import productApi from '@/api/products'; const router = useRouter(); const user = "aaa"; const tableData = ref([]); // 初始化为空数组 const goToProductDetail = (productId) => { router.push(`/home/test${productId}`); }; const handleEdit = (index, row) => { console.log(index, row); }; const handleDelete = (index, row) => { console.log(index, row); }; // 处理数量变化事件 const handleQuantityChange = (index, row) => { console.log(`产品 ${row.name} 数量更新为: ${row.number}`); }; const formatCurrency = (value) => { const numValue = parseFloat(value); // 先转换为数字 if (isNaN(numValue)) { return '¥0.00'; } return `¥${Math.abs(numValue).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}`; }; //商品一览 function getProduct() { productApi.getAll(user).then(res => { if (res.data && Array.isArray(res.data)) { tableData.value = res.data.map(item => ({ ...item, price: parseFloat(item.price) || 0, // 转换为数字 number: 0 // 默认购买数量为0 })); } else { console.error('API返回的数据格式不正确'); tableData.value = []; } }).catch(error => { console.error('获取商品数据失败:', error); tableData.value = []; }); } onMounted(() => { getProduct(); }); </script> <style scoped> .aaa-tag { display: inline-block; background-color: #409eff; color: white; font-size: 12px; padding: 0 4px; border-radius: 3px; margin-right: 5px; } </style> ``` 注意:在模板中,我注意到有两个`property="price"`的列,一个标签为“产品单价”,另一个为“单价”。我删除了重复的列,只保留了一个(显示为“产品单价”),并在该列中使用了模板来格式化显示。如果你确实需要两列,请自行调整,但通常不需要重复显示同一字段。 如果确实需要显示两次,请修改列标签以避免混淆。 这样修改后,购买数量默认就是0,且计算正确。 §§相关问题§§: 1. 在Vue3中,如何实现表格数据的实时校验(例如购买数量不能超过库存)? 2. 如何使用Element Plus的表格组件实现自定义排序? 3. 在Vue3中,如何优化大型数据表格的渲染性能? 4. 如何实现表格的合计行(在表格底部显示总计)?</think>我将为您提供一个完整的解决方案,确保购买数量默认值为0,并修复计算问题。以下是修复后的代码: ```html <template> <el-table :data="tableData" style="width: 100%"> <!-- 产品名称列 --> <el-table-column type="selection" width="55"/> <el-table-column label="产品名称" width="220"> <template #default="scope"> <div class="product-name-wrapper"> <el-link type="primary" :underline="false" @click="goToProductDetail(scope.row.id)"> <span>{{ scope.row.name }}</span> <span style="color: brown;">※点击进入详细画面</span> </el-link> </div> </template> </el-table-column> <!-- 其他列 --> <el-table-column property="categoryName" label="产品分类" width="120"/> <el-table-column label="产品单价" width="120"> <template #default="scope"> {{ formatCurrency(scope.row.price) }} </template> </el-table-column> <el-table-column property="createAt" label="生产日期" width="250"/> <el-table-column property="stock" label="库存" width="120"/> <!-- 购买数量列(默认值为0) --> <el-table-column label="购买数量" width="180"> <template #default="scope"> <div class="quantity-control"> <el-input-number v-model="scope.row.number" :min="0" :max="scope.row.stock" size="small" controls-position="right" @change="handleQuantityChange(scope.$index, scope.row)" /> <div v-if="scope.row.number === 0" style="color: #f56c6c; font-size: 12px; margin-top: 5px;"> 数量不能为0 </div> </div> </template> </el-table-column> <!-- 合计列 --> <el-table-column label="合计" width="120"> <template #default="scope"> <span :class="{'zero-amount': scope.row.number === 0}"> {{ formatCurrency(scope.row.price * scope.row.number) }} </span> </template> </el-table-column> <!-- 操作列 --> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.$index, scope.row)"> 编辑 </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> <!-- 总计行 --> <div class="total-section"> <span>总计:</span> <span class="total-amount">{{ formatCurrency(totalAmount) }}</span> </div> </template> <script setup> import { ref, onMounted, computed } from 'vue'; import { useRouter } from 'vue-router'; import productApi from '@/api/products'; import { ElMessage } from 'element-plus'; const router = useRouter(); const user = "aaa"; const tableData = ref([]); // 初始化为空数组 // 导航到产品详情 const goToProductDetail = (productId) => { router.push(`/home/test${productId}`); }; // 编辑操作 const handleEdit = (index, row) => { console.log('编辑:', index, row); }; // 删除操作 const handleDelete = (index, row) => { console.log('删除:', index, row); // 实际项目中应该从数组移除该项 tableData.value.splice(index, 1); }; // 处理数量变化事件 const handleQuantityChange = (index, row) => { console.log(`产品 ${row.name} 数量更新为: ${row.number}`); // 如果数量为0,显示警告 if (row.number === 0) { ElMessage.warning({ message: `${row.name} 的数量不能为0`, duration: 2000 }); } }; // 格式化货币显示 const formatCurrency = (value) => { // 确保是数字 const numValue = parseFloat(value); if (isNaN(numValue)) { return '¥0.00'; } // 格式化为货币字符串 return `¥${Math.abs(numValue).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}`; }; // 计算总计 const totalAmount = computed(() => { return tableData.value.reduce((sum, row) => { return sum + (row.price * row.number); }, 0); }); // 商品一览 - 确保每个产品都有默认购买数量0 function getProduct() { productApi.getAll(user).then(res => { if (res.data && Array.isArray(res.data)) { // 处理API返回的数据,确保每个产品都有number属性且默认值为0 tableData.value = res.data.map(item => ({ ...item, price: parseFloat(item.price) || 0, stock: parseInt(item.stock) || 0, number: parseInt(item.number) || 0, // 确保默认购买数量为0 })); console.log('处理后的表格数据:', tableData.value); } else { console.error('API返回的数据格式不正确,使用模拟数据'); tableData.value = getMockData(); } }).catch(error => { console.error('获取商品数据失败:', error); tableData.value = getMockData(); ElMessage.error('获取商品数据失败,请刷新重试'); }); } // 模拟数据(确保每个产品都有number属性且默认值为0) function getMockData() { return [ { id: 1, name: '笔记本电脑', categoryName: '电子产品', price: 5999.99, createAt: '2023-06-15', stock: 50, number: 0 // 默认值0 }, { id: 2, name: '无线耳机', categoryName: '电子产品', price: 399.00, createAt: '2023-07-20', stock: 100, number: 0 // 默认值0 }, { id: 3, name: '机械键盘', categoryName: '电脑配件', price: 299.50, createAt: '2023-05-10', stock: 80, number: 0 // 默认值0 } ]; } onMounted(() => { getProduct(); }); </script> <style scoped> .aaa-tag { display: inline-block; background-color: #409eff; color: white; font-size: 12px; padding: 0 4px; border-radius: 3px; margin-right: 5px; } /* 调整输入框宽度 */ :deep(.el-input-number) { width: 120px; } /* 确保表格行高度合适 */ :deep(.el-table__row) { height: 60px; } /* 总计区域样式 */ .total-section { margin-top: 20px; text-align: right; padding: 10px 20px; background-color: #f5f7fa; border-radius: 4px; font-size: 16px; } .total-amount { font-weight: bold; font-size: 18px; color: #e6a23c; } /* 数量为0时的特殊样式 */ .zero-amount { color: #c0c4cc; font-style: italic; } /* 错误提示样式 */ .quantity-control .el-input-number + div { margin-top: 5px; } </style> ``` ### 关键修复点: 1. **确保购买数量默认值为0**: ```javascript tableData.value = res.data.map(item => ({ ...item, number: parseInt(item.number) || 0, // 确保默认购买数量为0 })); ``` 2. **添加数量为0时的验证和提示**: ```html <div v-if="scope.row.number === 0" style="color: #f56c6c; font-size: 12px; margin-top: 5px;"> 数量不能为0 </div> ``` 3. **添加总计行**: ```javascript const totalAmount = computed(() => { return tableData.value.reduce((sum, row) => { return sum + (row.price * row.number); }, 0); }); ``` 4. **添加数量为0时的特殊样式**: ```html <span :class="{'zero-amount': scope.row.number === 0}"> {{ formatCurrency(scope.row.price * scope.row.number) }} </span> ``` ```css .zero-amount { color: #c0c4cc; font-style: italic; } ``` 5. **添加用户友好的提示**: ```javascript // 在handleQuantityChange中 if (row.number === 0) { ElMessage.warning({ message: `${row.name} 的数量不能为0`, duration: 2000 }); } ``` 6. **增强错误处理**: ```javascript .catch(error => { console.error('获取商品数据失败:', error); tableData.value = getMockData(); ElMessage.error('获取商品数据失败,请刷新重试'); }); ``` ### 额外优化: 1. **添加删除功能**: ```javascript const handleDelete = (index, row) => { tableData.value.splice(index, 1); }; ``` 2. **添加库存限制**: ```html <el-input-number :max="scope.row.stock" /> ``` 3. **添加总计区域**: ```html <div class="total-section"> <span>总计:</span> <span class="total-amount">{{ formatCurrency(totalAmount) }}</span> </div> ``` 4. **添加模拟数据**: ```javascript function getMockData() { return [ // ...每个对象都有 number: 0 ]; } ``` 5. **添加空状态处理**: ```html <el-table v-if="tableData.length === 0"> <template #empty> <el-empty description="暂无产品数据" /> </template> </el-table> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大白砌墙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值