第十五届蓝桥杯(Web 应用开发)模拟赛 1期-大学组

1. 动态的 Tab 栏

/* TODO: 请在此补充代码实现tab栏动态固定 */
  /* position:fixed; */
  position: sticky;
  top: 0;

2. 冰墩墩心情刻度尺

// TODO: 待补充代码
BingDunDun.className='BingDunDun not-satisfied'
range.onchange = (e) => {
  let value = Number(e.target.value); // value 进度条的值
  // TODO: 待补充代码
  console.log(value);
  if(value===25){
    BingDunDun.className='BingDunDun a-little-unsatisfied'
  }else if(value===50){
    BingDunDun.className='BingDunDun ordinary'
  }else if(value===75){
    BingDunDun.className='BingDunDun satisfied'
  }else if(value===100){
    BingDunDun.className='BingDunDun great'
  }else{
    BingDunDun.className='BingDunDun not-satisfied'
  }
};

3. 迷惑的 this

 //事件处理函数
  handle() {
    // TODO:待补充代码  
    let inputEl=document.querySelector("input");
    inputEl.addEventListener('input',(value)=>{
      this.handleInput(value)
    })
  },

4. 魔法失灵了

//TODO:待修复代码
    // let { value }={ ...data }
    let { value }=toRefs(data)

    function update(val) {
        value = val
    }

5. 燃烧你的卡路里

//目标一 
//html
<el-drawer title="我是标题" v-model="drawer" :with-header="false" size="60%"  :direction="direction" >
//js
      <const submit = async() => {
    // TODO 待添加的代码 功能显示抽屉组件
    drawer.value=true

6. 司龄统计 

目标

找到 js/index.js 中的,完成其中的 TODO 部分,完成以下目标:

  1. 找到 groupByAge 函数,groupByAge 接收一个参数,参数为数组对象,age 代表司龄,name 代表人名,返回一个根据司龄进行分组的对象,key 是司龄,value 是一个数组,其中包含了所有当前司龄的人的对象。
  • 参数格式示例如下:
 [
  { name: "杰克", age: 1 },
  { name: "丽莎", age: 2 },
  { name: "艾娃", age: 5 },
  { name: "约翰", age: 1 },
  { name: "豪尔赫", age: 2 },
]

  • 返回值为 object,格式示例如下:
// 根据司龄(`age`)进行分组,司龄对应司龄人数的数组:
{
   1: [{ name: '杰克', age: 1 }, { name: '约翰', age: 1 }], // 司龄为 1 的数组 
   2: [{ name: '丽莎', age: 2 }, { name: '豪尔赫', age: 2 }], // 司龄为 2 数组 
   5: [{ name: '艾娃', age: 5 } ]// 司龄为 5 数组 
}

  1. 正确设置 ECharts 图表中的 x 轴和 y 轴数据,x 轴表示司龄,从小到大排序,y 轴表示司龄对应的人数个数。如 1 年司龄的有 4 人,则 y 轴对应的数据为 4。

完成后效果如下:

完成效果

题解 

const groupByAge = (peoples) => {
  // TODO:待补充代码,按照年龄进行分组
  let ageres=new Object();
  for(let i=0;i<peoples.length;i++){
    let age=peoples[i].age;
    if(ageres[age]){
      let arr1=ageres[age];
      arr1.push(peoples[i]);
      ageres[age]=arr1;
    }else{
      let arr2=new Array();
      arr2.push(peoples[i]);
      ageres[age]=arr2;
    }
  }
  return ageres;
};
 setup() {
    const { updateData } = useECharts();
    let xAxisData = Vue.ref([]); // X 轴数据,司龄从小到大排列
    let seriesData = Vue.ref([]); // Y 轴数据,司龄对应的人数
    const groupedPeople = Vue.ref([]); // table 中显示的数据
    Vue.onMounted(async () => {
      const data = await (await fetch("./mock/data.json")).json();
      groupedPeople.value = groupByAge(data); //把请求回来的数据变成需要的数据格式
      // TODO: 设置 Echars X 轴数据 xAxisData 和 Y 轴数据 seriesData
      console.log(groupedPeople.value);
      let arrX=[];
      let arrY=[];
      for(key in groupedPeople.value){
       arrX.push(key);
       arrY.push(groupedPeople.value[key].length)
      }
      xAxisData.value=arrX;
      seriesData.value=arrY
      // 更新 echars 数据
      updateData(xAxisData.value, seriesData.value);
    });

    return {
      groupedPeople,
    };
  },

7. 不翼而飞的余额——route

目标

完善 index.htmljs/store.js 和 component/DepositPage.js 中的代码。实现以下效果:

  1. 找到 index.html 中的 TODO 部分,为项目配置 history 模式路由,浏览器中访问 / 的时候显示 WalletPage 组件,访问 /deposit 的时候显示 DepositPage 组件。

tips: 目标 1 完成后点击 deposit 按钮或底部的导航的 deposit 导航文字,均会跳转到 DepositPage 存款页面。

  1. 找到 DepositPage.js 中的 TODO 部分,在 DepositPage 页面中的 (id = deposit-balance)元素正确显示钱包余额(store 中的 balance)。
  2. 完善 js/store.js 和 component/DepositPage.js中的 TODO 部分,在 DepositPage 页面中,在输入框(input)输入数字(只考虑正整数),点击 “Deposit” 按钮(button)后,余额 = 现在的余额 + 输入框中输入的金额,在 DepositPage 页面正确显示钱包余额(两个页面的余额相同)。初始余额为 23。

完成后效果如下:

完成效果

题解 

//目标1——路由
<script>
    const { createApp } = Vue;
    const { createPinia } = Pinia;
    const { createRouter,createWebHistory} = VueRouter;  // TODO:待补充代码,在此引入路由相关 API 
    const app = createApp({});
    app.use(createPinia());
    
    const router = createRouter({
     // TODO:待补充代码,为项目配置 history 模式的路由
     history:createWebHistory(),
    routes:[
      {path:"/",component:WalletPage},
      {path:"/deposit",component:DepositPage}
    ]
    })

    app.use(router)
    // 注册组件
    app.mount("#app");
  </script>
//目标二:插值语法
 <!-- TODO:待补充代码,在 # deposit-balance 中正确显示钱包余额  -->  
           <span id="deposit-balance">{{store.balance}}</span>


  return {
      deposit,
      store
    }
 // TODO:待补充代码,完善点击存款按钮事件
    function deposit() {
     console.log(depositAmount);
     store.balance+=depositAmount.value
     depositAmount.value=''
    }
    return {
      deposit,
      store,
      depositAmount
    }

8. 个性化推荐

目标

请在 js/index.js 文件中补全代码,最终实现个性化推荐的功能。

首先,在终端运行以下命令启动服务器:

node ./js/index.js

当看到终端输出:server is running in port 8080,表明服务器启动成功。

并在浏览器中通过 8080 端口预览 index.html 页面,显示如下所示:

起始页面

在完成勾选后,点击确认,页面会发送 post 请求并跳转到新的页面,你需要根据用户的勾选项,从 data.json 中查询对应的数据,并读取 customized.html 文件的内容,两者结合生成结果页面数据,并返回给前端浏览器:

  1. 如果用户没有勾选任何标签,直接点击确认,新页面给与提示:

提示

 提示信息的 DOM 结构如下:

<div class="unselect">你还未选择任何感兴趣的标签!</div>

  1. 如果用户勾选了标签,则返回对应的标签的查询信息以及相关推荐,比如用户选择了标签 Javascript,除了查询 tag 为 Javascript 的内容,也需要查询 Javascript 的相关推荐标签 HTML5CSS3 的内容(即 relevance 字段对应的数据),一并返回。
    • 注意:不再需要进一步查询相关推荐的相关推荐,即不需要查询 HTML5 的相关推荐标签的内容。
    • 多个标签之间的相关标签可能重复,需要对查询内容进行去重,比如选择了标签 Javascript 和 CSS3,最终的去重结果应该是标签 JavascriptCSS3HTML5 的内容。

选择

结果

每一条信息的 DOM 结构如下:

<div class="interest">
    <div class="tag">标签名</div>
    <div>标签内容</div>
</div>

customized.html 文件中已提供基础的样式,请保证你生成的节点带有指定的 class 信息,并填充到 body 中。 在代码更新后,请记得重启服务器!

9. 贪吃蛇 

目标

找到 index.js 文件中的 nextStep 函数,完成函数中的 TODO 部分:

  1. 根据当前蛇的移动方向(this.direction)以及蛇身块的大小(this.size),计算新的蛇头位置,更新蛇身坐标数组 (this.snakeBody),即可实现蛇的正确移动。蛇的移动和增加蛇的长度代码已提供

蛇身坐标示例如下:

 [{ left: 2, top: 0 }, { left: 1, top: 0 }, { left: 0, top: 0 }]` 

蛇的身体是由多个坐标点组成的,每个坐标点包含了 left 和 top 属性,分别表示在游戏界面中的水平和垂直位置,第一个坐标表示当前蛇头的位置。

完成后,效果如下:

完成效果

规定

  • 请勿修改已经提供的代码,以免造成判题无法通过。
  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径等。
  • 满足题目需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动判分

10. 自定义表单验证器

目标

  1. 完成 FormInput.js 中的 TODO 部分,当输入框(class= form-input) 的值变化时,触发事件更新index.html 中组件(form-input)的 v-model 值。(调试 tips:考生可以在点击按钮时通过打印 formData 的值进行查看)。

  2. 完成 js/util.js 中的 is_email 函数,参数是邮箱地址,是合法邮箱返回 true,否则返回 false

合法邮箱包含两个部分:

  1. 用户名部分:

    • 用户名的结尾是 @ 符。
    • @ 符之前为至少 1 位字符(数字或字母)。
  2. 域名部分:

    • 中间必须是 .
    • . 之前为至少 1 位字符(数字、字母)。
    • . 之后为 2 到 4 位字母。

合法邮箱示例: a@b.cn1A@88.com

不合邮箱示例: 1@1.c1@33.cnAb.cn@

  1. 完成 components/FormValidator.js 中通用表单验证函数 validateForm 中的 TODO 部分。如果表单验证通过,则 Promise 为 resolve(true),否则为 resolve(false)(此部分代码已提供)。 index.html 中定义的 formRules 对象对应字段的表单值验证失败时,使用 validateForm 函数中提供的 errors 对象,在对应字段中存储错误信息。若某个字段对应的错误信息为多个时,将按照验证规则数组的顺序优先显示,即只显示第一个错误信息。函数使用的数据通过 props.rules(字段名和对应的验证规则) 和 props.formData(表单数据的键值对) 进行获取。

例: email为空显示了错误信息 邮箱不能为空,则不再显示 邮箱不符合规则或者长度不符 这个错误信息。

errors 数据结构示例:

{
    phone: "请输入密码", // 对应字段为 phone 的错误信息
    email: "邮箱不能为空" // 对应字段为 email 的错误信息
}

表单每个字段对应的验证规则为一个数组,验证规则示例的配置如下:

// 定义表单验证规则
const formRules = {
  phone: [{ validator: validatePass }], // 针对 phone 字段的验证规则
  email: [
    { required: true, message: "邮箱不能为空" }, // 邮箱字段必填规则
    { type: "email", min: 8, max: 20, message: "类型必须为邮箱" }, // 邮箱格式规则
  ],
};

formRules 对应字段说明如下:

注意:自定义验证函数 validator 不会和其他字段同时出现,其他字段均可同时出现。

参数名(Parameter)类型(Type)描述(Description)
validatorFunction表单自定义验证函数,接受三个参数,分别为 rule 表单验证规则数组,value 验证表单的值,callback 回调函数。如果验证成功,callback 函数不做任何处理;如果验证失败,callback 函数接收参数 error 并将其中的文字存储在 errors 对象中,且参数 error 的值为其调用者传递过来的 new Error('这里是错误信息'),其中错误信息是验证失败的具体描述。callback 函数的调用逻辑 index.html 中已经提供,考生只需实现字段验证及 errors 错误信息存储的逻辑即可。
requiredBoolean表示表单字段是否为必填项。
typeString字段类型,通过 FormValidator 中已提供的 validateByType 函数进行验证,该函数接收的参数为 type,类型正确则返回 true,否则返回 false
minNumber指定表单输入的最小长度。
maxNumber指定表单输入的最大长度。
messageString验证失败时的错误信息

完成后示例效果如下:

完成效果

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值