You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListView值保存实现:切换品牌时留存商品数量输入数据

嗨,这个需求其实挺常见的,核心就是在切换品牌时把当前商品的输入值存起来,等下次切回来再回填就行。我给你准备了两种实现思路,一种是原生JavaScript的,另一种是Vue的(如果用框架的话会更省心),你可以根据自己的技术栈来选:

核心逻辑说明

不管用哪种方式,核心都是用一个存储对象来记录每个品牌下各商品的输入数量:

  • 键可以按「品牌ID-商品ID」的格式,或者按品牌分组存储(后者更清晰)
  • 切换品牌前,先把当前页面所有输入框的值存入存储对象
  • 渲染新品牌的商品时,从存储对象里取出对应的值回填到输入框中

原生JavaScript实现示例

这种方案不需要依赖任何框架,直接用原生DOM操作就能完成:

1. HTML结构

<div class="container">
  <div class="brand-list">
    <h3>商品品牌</h3>
    <ul>
      <!-- 品牌列表通过JS动态生成 -->
    </ul>
  </div>
  <div class="product-list">
    <h3>商品列表</h3>
    <div id="product-container">
      <!-- 商品列表通过JS动态生成 -->
    </div>
  </div>
</div>

2. 基础样式

.container {
  display: flex;
  gap: 20px;
  padding: 20px;
}
.brand-list {
  width: 200px;
  border-right: 1px solid #eee;
}
.brand-list ul {
  list-style: none;
  padding: 0;
}
.brand-list li {
  padding: 8px 12px;
  cursor: pointer;
  margin-bottom: 4px;
  border-radius: 4px;
}
.brand-list li.active {
  background-color: #007bff;
  color: white;
}
.product-item {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.product-item input {
  width: 60px;
  padding: 4px;
}

3. 核心JS逻辑

// 模拟品牌数据
const brands = [
  { id: 'brand1', name: '品牌A' },
  { id: 'brand2', name: '品牌B' },
  { id: 'brand3', name: '品牌C' }
];

// 模拟各品牌对应的商品
const brandProducts = {
  brand1: [
    { id: 'prod1', name: '商品A1' },
    { id: 'prod2', name: '商品A2' }
  ],
  brand2: [
    { id: 'prod3', name: '商品B1' },
    { id: 'prod4', name: '商品B2' }
  ],
  brand3: [
    { id: 'prod5', name: '商品C1' }
  ]
};

// 存储已输入的数量,结构:{ 品牌ID: { 商品ID: 数量值 } }
const inputStorage = {};
let currentBrandId = null;

// 获取DOM元素
const brandListEl = document.querySelector('.brand-list ul');
const productContainerEl = document.getElementById('product-container');

// 初始化品牌列表
function initBrandList() {
  brands.forEach(brand => {
    const li = document.createElement('li');
    li.textContent = brand.name;
    li.dataset.brandId = brand.id;
    li.addEventListener('click', () => switchBrand(brand.id));
    brandListEl.appendChild(li);
  });
  // 默认选中第一个品牌
  brands.length > 0 && switchBrand(brands[0].id);
}

// 切换品牌的核心函数
function switchBrand(brandId) {
  // 1. 先保存当前品牌的输入值(如果有当前品牌)
  currentBrandId && saveCurrentBrandInputs(currentBrandId);
  
  // 2. 更新当前品牌状态并高亮选中项
  currentBrandId = brandId;
  document.querySelectorAll('.brand-list li').forEach(li => {
    li.classList.toggle('active', li.dataset.brandId === brandId);
  });
  
  // 3. 渲染新品牌的商品并回填存储的值
  renderProducts(brandId);
}

// 保存当前品牌的输入值
function saveCurrentBrandInputs(brandId) {
  if (!inputStorage[brandId]) inputStorage[brandId] = {};
  const inputEls = document.querySelectorAll('.product-item input');
  inputEls.forEach(input => {
    const productId = input.dataset.productId;
    inputStorage[brandId][productId] = input.value.trim() || '';
  });
  
  // 可选:存入localStorage实现页面刷新不丢失数据
  localStorage.setItem('productInputStorage', JSON.stringify(inputStorage));
}

// 渲染商品列表
function renderProducts(brandId) {
  const products = brandProducts[brandId] || [];
  productContainerEl.innerHTML = '';
  
  products.forEach(product => {
    const productItem = document.createElement('div');
    productItem.className = 'product-item';
    // 从存储中取已保存的值,没有则为空
    const savedValue = inputStorage[brandId]?.[product.id] || '';
    
    productItem.innerHTML = `
      <span>${product.name}</span>
      <input type="number" min="0" data-product-id="${product.id}" value="${savedValue}">
    `;
    productContainerEl.appendChild(productItem);
  });
}

// 初始化时从localStorage读取已保存的数据(可选)
const savedStorage = localStorage.getItem('productInputStorage');
savedStorage && Object.assign(inputStorage, JSON.parse(savedStorage));

// 启动初始化
initBrandList();

Vue.js实现示例(更简洁)

如果你的项目用Vue框架,借助响应式数据可以更轻松地实现,不需要手动操作DOM:

<template>
  <div class="container">
    <div class="brand-list">
      <h3>商品品牌</h3>
      <ul>
        <li 
          v-for="brand in brands" 
          :key="brand.id"
          :class="{ active: currentBrandId === brand.id }"
          @click="switchBrand(brand.id)"
        >
          {{ brand.name }}
        </li>
      </ul>
    </div>
    <div class="product-list">
      <h3>商品列表</h3>
      <div 
        class="product-item"
        v-for="product in currentProducts"
        :key="product.id"
      >
        <span>{{ product.name }}</span>
        <input 
          type="number" 
          min="0"
          v-model="inputStorage[currentBrandId][product.id]"
        >
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      brands: [
        { id: 'brand1', name: '品牌A' },
        { id: 'brand2', name: '品牌B' },
        { id: 'brand3', name: '品牌C' }
      ],
      brandProducts: {
        brand1: [
          { id: 'prod1', name: '商品A1' },
          { id: 'prod2', name: '商品A2' }
        ],
        brand2: [
          { id: 'prod3', name: '商品B1' },
          { id: 'prod4', name: '商品B2' }
        ],
        brand3: [
          { id: 'prod5', name: '商品C1' }
        ]
      },
      currentBrandId: 'brand1',
      inputStorage: {}
    }
  },
  computed: {
    // 计算当前品牌对应的商品列表
    currentProducts() {
      return this.brandProducts[this.currentBrandId] || [];
    }
  },
  created() {
    // 初始化存储结构
    this.brands.forEach(brand => {
      this.$set(this.inputStorage, brand.id, {});
      // 给每个商品初始化空值
      this.brandProducts[brand.id]?.forEach(prod => {
        this.$set(this.inputStorage[brand.id], prod.id, '');
      });
    });
    
    // 可选:从localStorage读取已保存的数据
    const savedStorage = localStorage.getItem('productInputStorage');
    savedStorage && Object.assign(this.inputStorage, JSON.parse(savedStorage));
  },
  methods: {
    switchBrand(brandId) {
      // 因为用了v-model,数据已经实时同步到inputStorage,直接切换即可
      this.currentBrandId = brandId;
    }
  },
  watch: {
    // 监听存储变化,自动保存到localStorage(可选)
    inputStorage: {
      deep: true,
      handler(val) {
        localStorage.setItem('productInputStorage', JSON.stringify(val));
      }
    }
  }
}
</script>

<style scoped>
.container {
  display: flex;
  gap: 20px;
  padding: 20px;
}
.brand-list {
  width: 200px;
  border-right: 1px solid #eee;
}
.brand-list ul {
  list-style: none;
  padding: 0;
}
.brand-list li {
  padding: 8px 12px;
  cursor: pointer;
  margin-bottom: 4px;
  border-radius: 4px;
}
.brand-list li.active {
  background-color: #007bff;
  color: white;
}
.product-item {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.product-item input {
  width: 60px;
  padding: 4px;
}
</style>

内容的提问来源于stack exchange,提问作者Александр Волошиновский

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:24:53