Skip to content

每日一题:新增地址

作者:江月迟迟
发表于:2024-12-10
字数统计:1579 字
预计阅读6分钟

介绍

网购大家应该再熟悉不过,网购中有个很难让人忽略的功能就是地址管理,接下来就让我们通过完善代码来探索下地址管理中常用功能的实现吧~

本题需要在已提供的基础项目中使用 JS 知识完善代码,最终实现需求中的具体功能。

准备

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

txt
├── effect.gif
├── index.html
├── css
├── images
└── js
    ├── data.js
    └── index.js

其中:

  • effect.gif 是最终实现的效果图。
  • index.html 是主页面。
  • css 是样式文件夹。
  • images 是图片文件夹。
  • js/data.js 是省市区列表数据。
  • js/index.js 是需要补充代码的 js 文件。

注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:

bash
cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/9790/08.zip && unzip 08.zip && rm 08.zip

在浏览器中预览 index.html 页面,显示如下所示:

初始效果

目标

请在 js/index.js 文件中补全代码,最终实现以下需求:

  1. 实现省市二级联动功能。
  • 页面加载后省份下拉列表数据正常渲染
  • 省份列表中选取某个数据后,对应市区数据渲染在其右侧的市区列表中。效果如下:

省市联动效果

  1. 实现对提交的表单信息的验证功能。
  • 填写表单信息,其中地址、联系人和手机号必填项,有一项为空则点击保存按钮会弹出提示窗点击提示窗周围的半透明蒙层后,该窗口关闭。效果如下:

弹窗提示效果

  1. 实现选择标签显示激活样式功能。
  • 点击标签列表中的某个标签(例如:公司),该标签显示激活样式(即 .active**),其他未选择标签显示默认样式**。效果如下:

标签显示激活样式

  1. 实现新增地址被正确渲染功能。
  • 点击保存按钮,表单数据将以列表的形式显示在原有数据的上方,即整个地址列表的首位。效果如下:

表单提交后在地址列表中的显示效果

  • 表单数据

    在地址列表中

    显示时

    ,对应的

    标签

    有其不同的

    样式

    ,具体如下:

    • 家:.home
    • 公司:.company
    • 学校:.school

完成后的效果见文件夹下面的 gif 图,图片名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。

规定

  • 请勿修改 js/index.js 文件外的任何内容。
  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成无法判题通过。

判分标准

  • 实现省市二级联动功能,得 7 分。
  • 实现表单信息验证功能,得 2 分。
  • 实现标签动态选取功能,得 3 分。
  • 实现新增地址渲染功能,得 8 分。

总通过次数: 274 | 总提交次数: 335 | 通过率: 81.8%

难度: 中等 标签: 2022, 国赛, Web 前端, JavaScript

js
function provinceInit() {
  var province = document.getElementById("param_province");
  province.length = provinces.length;
  for (var i = 0; i < provinces.length; i++) {
    province.options[i].text = provinces[i];
    province.options[i].value = provinces[i];
  }
}

// 选择省份后对应城市下拉列表内容渲染
function provincechange() {
  // TODO:请补充代码实现功能
  var province = document.getElementById("param_province");
  console.log(province.value);
  console.log(province.selectedIndex);
  const city = document.getElementById('param_city')
  city.length = citys[province.selectedIndex].length
  for(let i = 0; i < city.length; i++) {
    city.options[i].text = citys[province.selectedIndex][i]
    city.options[i].value = citys[province.selectedIndex][i]
  }
}

/**
 * 为标签绑定单击事件。
 * 事件效果为:
 * 1、鼠标点击该标签后该标签样式显示 class=active;
 * 2、其他已选标签的 active 样式被移除;
 * 3、将选中的标签对应下标(即选择器为 “mark a” 选中的标签对应的下标)更新到 id=param_mark 的隐藏的 input 中。
 */
function addClick() {
  // TODO:请补充代码实现功能
  const label = document.querySelectorAll('.mark a')
  console.log(label);
  label.forEach(item => {
    item.addEventListener('click', e => {
      for(let i of label) {
        i.classList.remove('active')
      }
      item.classList.add('active')
      labelValue = item.innerHTML
      console.log(labelValue);
    })
  })
}
// 提交信息后,读取并显示在页面中
function saveInfo() {
  // TODO:请补充代码实现功能
  const address = document.getElementById('param_address')
  const name = document.getElementById('param_name')
  const phone = document.getElementById('param_phone')
  console.log(address.value);
  console.log(name.value);
  console.log(phone.value);
  if (!address.value || (address.value && address.value.trim() === '') ||
  !name.value || (name.value && name.value.trim() === '') ||
  !phone.value || (phone.value && phone.value.trim() === '') 
  ) {
    document.getElementsByClassName('warning-dialog')[0].style.display = 'block'
    return
  }

  const province = document.getElementById('param_province')
  const city = document.getElementById('param_city')
  
  const addressList = document.querySelector('.address-list')
  const addressContainer = document.querySelector('.address')
  const userInfoContainer = document.querySelector('.user-info')
  addressList.style.display = 'block'
  addressContainer.style.display = 'none'
  userInfoContainer.style.display = 'none'
  addressList.style.zIndex = 2

  addressList.insertAdjacentHTML('afterbegin', `
  <li>
      <div class="show-area">
          <label class="${addressMap[labelValue]}">${labelValue}</label>
          <span>${province.value + city.value}</span>
      </div>
      <div class="show-address">
          <span>${address.value}</span>
          <a><img src="./images/edit.png" /></a>
      </div>
      <div class="show-info">
          <span>${name.value}</span>
          <span>${phone.value}</span>
      </div>
  </li>
`);
}

// 切换新增地址和地址管理的显隐
function back() {
  if (document.getElementById("main_title").innerHTML == "地址管理") {
    document.getElementById("main_title").innerHTML = "新增地址";
    document.querySelector(".address-list").style.display = "none";
    document.querySelector(".address").style.display = "block";
    document.querySelector(".user-info").style.display = "block";
  }
}
// 页面加载后的初始化操作
function init() {
  // 初始化省份下拉列表内容
  provinceInit();
  // 为标签绑定单击事件
  addClick();
}

window.onload = function () {
  // 初始化
  init();
};