发布时间:2023-04-22 文章分类:WEB开发, 电脑百科 投稿人:李佳 字号: 默认 | | 超大 打印

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

🧑‍💼 个人简介:一个不甘平庸的平凡人🍬
🖥️ 蓝桥杯专栏:蓝桥杯题解/感悟
🖥️ TS知识总结:十万字TS知识点总结
👉 你的一键三连是我更新的最大动力❤️!
📢 欢迎私信博主加入前端交流群🌹

📑 目录

  • 🔽 前言
  • 1️⃣ 凭空消失的 TA
  • 2️⃣ 用户名片
  • 3️⃣ 芝麻开门
  • 4️⃣ 宝贵的一票
  • 5️⃣ 粒粒皆辛苦
  • 6️⃣ 618 活动
  • 7️⃣ 资讯接口
  • 8️⃣ 绝美宋词
  • 9️⃣ 平地起高楼
  • 🔟 收快递了
  • 💠 偷梁换柱(职业院校组)
  • 💠 大电影(职业院校组)
  • 💠 乾坤大挪移心法(职业院校组)
  • 💠 不能说的秘密(职业院校组)
  • 🔼 结语

🔽 前言

第十四届蓝桥杯 Web 应用开发模拟赛第二期昨天正式开始了(本来写的是今天正式开始了,结果没想到这篇文章写到了凌晨 1 点 😵‍💫),博主也是第一时间为大家带来了题解!这篇题解包含了大学组职业院校组的所有内容。

因为自己在做题时忘记保存代码了,所以写这篇题解时我不得不又重新做了一遍,看在博主这么肝的份上,大佬们给个一键三连加关注吧!🤗

关于蓝桥杯更多的题解请前往专栏:蓝桥杯题解/感悟,欢迎大家的订阅!

本篇只会大概提出题目要求,关于题目的更多细节可自行去模拟赛主页查询:Web 应用开发模拟赛 2 期大学组

话不多说,开撕!

1️⃣ 凭空消失的 TA

题目说在 index.html 中未正常显示表单组件 myform,先运行看一下效果:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解
发现 myform组件里的立即创建取消这两个文本被渲染了,这说明 index.html 确实是引入了 myform,但为何myform没有正常显示呢?

一开始我以为是myform组件里出了问题,可检查一遍后并没有发现问题,最后回到index.html才发现,是因为index.html中未引入element-uijs文件,我们加一行代码引入一下就解决了:

 <!-- 引入 element-ui 样式 -->
 <link rel="stylesheet" href="./element-ui-2.15.10/index.css" />
 <!-- 新增:引入 element-ui js文件 -->
 <script src="./element-ui-2.15.10/index.js"></script>

2️⃣ 用户名片

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

要求是需要将这个卡片垂直居中,并且还需要将卡片中左侧文字水平居中,看了一下HTML结构,发现它们都有一个共同的类名center

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

所以对center类名定义样式就行了:

/* TODO 待补充代码 */
.center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}

上述代码利用定位将元素垂直水平方向各偏移父元素position: relative)的50%,这个时候元素还不是居中(因为定位偏移的中心点不在元素的中心上而是在元素的边界上):

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

使用transform将元素在水平和垂直的负方向移动自身的50%(transform运动的中心点在元素的中心位置):

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

这里深入说一下一个CSS选择器优先级的问题:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

图中所示,作用于同一元素的.user-card .points(后代选择器)的样式优先生效于.center (类选择器)的样式,这就映证了网上说的后代选择器的优先级小于类选择器的说法是不够准确的

其实,后代选择器和类选择器没有可比性,后代选择器是选择器组合方式的一种,它是一种组合本身没有任何优先级(严格的用词叫特殊性) 可言。比如.user-card .points在计算特殊性(优先级)时,是分别计算「.user-card」和「.points」的特殊性(优先级),完全不用考虑它们之间是用后代关联的。

按照权重来说.user-card .points的样式优先生效于.center的样式,是因为.user-card .points含有两个类选择器,它的权重比.center高。

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

关于CSS选择器权重、优先级的问题在实际开发中是比较重要的,如果你看到这里对它们还不是很了解,建议你去网上多看看关于它们的内容。

3️⃣ 芝麻开门

这题简单的考察了Promise,最终实现以下效果:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解
代码:

/**
 * @description: 调用函数,开启弹窗,记录输入框的内容,并通过 promise 异步返回输入框中的内容
 * @return {Promise}
 */
function mPrompt() {
  // 弹窗必须使用以下结构 template 保存的是弹窗的结构字符串,可以先转化为 DOM 再通过 appendChild 方式插入到 body 中
  const template = `
        <div class="modal">
            <div class="message-box">
                <div class="message-header">请输入咒语</div>
                <div class="message-body">
                    <input type="text">
                </div>
                <div class="message-footer">
                    <button class="btn btn-small" id='cancel'>取消</button>
                    <button class="btn btn-small btn-primary" id='confirm'>确定</button>
                </div>
            </div>
        </div>
    `;
  const div = document.createElement("div");
  // TODO:待补充代码
  div.innerHTML=template
  document.body.append(div);
  let val = div.getElementsByTagName("input")[0];
  return  new Promise((resolve, reject) => {
    document.getElementById("cancel").onclick = function() {
      div.remove()
      reject(false)
    }
    document.getElementById("confirm").onclick = function() {
        div.remove()
        resolve(val.value)
    }
  });
}

代码很简单,按照题目要求返回一个Promise对象,并在点击事件中做出不同的处理(rejectresolve)即可。

4️⃣ 宝贵的一票

要求是实现一个动态列表的表单,可以新增选项和删除选项,最终效果:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解
添加的思路:

删除的思路:

代码:

// 点击加号逻辑
$(".add").click(function () {
  // TODO 待补充代码
  // 当前列表长度
  let cl = $(".list").children().length;
  // 长度为2时为前两个选项加上x号
  if (cl === 2) {
    $(".list").children().each((index,item)=>{
      $(item).append(`  
        <div class="col-sm-1">
            <img class="del-icon" src="./images/x.svg" alt="" />
        </div>`)
    })
  }
  if (cl < 2) {
    // 当前列表长度小于2时,添加不带x号的选项
    $(".list").append(initRender(`选项${cl + 1}`));
  }else {
    // 当前列表长度大于等于2时,添加带x号的选项
    $(".list").append(`<div class="mb-3 row item">
          <label class="col-sm-2 col-form-label txt">选项${cl + 1}</label>
          <div class="col-sm-9">
            <input type="text" class="form-control" />
          </div>
          <div class="col-sm-1">
            <!-- 删除图标 -->
            <img class="del-icon" src="./images/x.svg" alt="" />
          </div>
        </div>`);
  }
});
// 点击 x 删除逻辑,列表小于 2 项时不显示删除图标
$(document).on("click", ".del-icon", function () {
  // TODO 待补充代码
  // 删除这一条
  $(this).parent().parent().remove()
  // 遍历
  $(".list").children().each((index,item)=>{
  	// 修改剩下的列表序号
    $(item).children('label').text(`选项${index + 1}`)
    if($(".list").children().length <= 2) {
      // 列表长度小于等于2时,请求x号
      $(item).children()[2].remove()
    }
  })
});

5️⃣ 粒粒皆辛苦

这是一道ECharts题,从历届蓝桥杯Web比赛、模拟赛等可以看出每一次比赛都至少会有一道ECharts的题,不过这些ECharts题涉及到的ECharts的内部并不过,大部分都只是考察你对数据的处理,比如这一题,本质就是对数据格式的转换。

源数据格式:

{
    "2017": { "wheat": 431, "soybean": 142, "potato": 232, "corn": 642 },
    "2018": { "wheat": 417, "soybean": 156, "potato": 258, "corn": 643 },
    "2019": { "wheat": 416, "soybean": 168, "potato": 269, "corn": 650 },
    "2020": { "wheat": 436, "soybean": 174, "potato": 277, "corn": 680 },
    "2021": { "wheat": 441, "soybean": 186, "potato": 289, "corn": 692 },
    "2022": { "wheat": 445, "soybean": 201, "potato": 315, "corn": 706 }
}

字段对应表:

英文名称 中文名称
wheat 小麦
soybean 大豆
potato 马铃薯
corn 玉米

需要转换成的数据格式:

[
	['全部', '2017', '2018', '2019', '2020', '2021', '2022'],
 	['小麦', 431, 417, 416, 436, 441, 445],
    ['大豆', 142, 156, 168, 174, 186, 201],
	['马铃薯', 232, 258, 269, 277, 289, 315],
	['玉米', 642, 643, 650, 680, 692, 706]
]

代码:

// TODO: 待补充代码
let dataObj = {
  wheat: ["小麦"],
  soybean: ["大豆"],
  potato: ["马铃薯"],
  corn: ["玉米"]	
};
let sourceTip = ["全部"];
// 获取数据
axios.get("./data.json").then(res=>{
  let data = res.data.data;
  for (const key1 in data) {
    sourceTip.push(key1);
    for (const key2 in data[key1]) {
      dataObj[key2].push(data[key1][key2]);
    }
  }
  let newSource = [];
  newSource.push(sourceTip);
  for (const key in dataObj) {
    newSource.push(dataObj[key]);
  }
  option.dataset.source = newSource;
  myChart.setOption(option);
})

代码和逻辑都比较简单,就不多说了。

6️⃣ 618 活动

就是按照官方给的最终效果图,去实现下面这个页面:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

没啥技术含量,全靠堆HTML和CSS,这里就不放代码了。

但这个题是我认为是整场模拟赛里最坑人的题,特别废时间,我建议这个题要么放到最后再写(因为完成度50%以上就能得到分,其它题不行),要么完成差不多后就直接去做下面的题,别死扣细节,不然吃亏的都是你!

7️⃣ 资讯接口

题目要求使用 NodeJS 去创建一个服务器并响应一个/news接口:

  1. 通过在 app.js 书写代码,创建一个服务器,使服务在 8080 端口运行。
  2. 访问 /news 返回资讯数据,访问其他任意路径均返回字符串 404 。

代码:

// TODO: 待补充代码
const http = require("http");
// 创建http服务
const app = http.createServer();
app.on("request",(req,res)=>{
    res.setHeader("Content-type", "text/html;charset=utf8");
    switch (req.url) {
        case '/news':
            res.end(JSON.stringify([
                {
                  "channelId": "5572a108b3cdc86cf39001cd",
                  "name": "国内焦点"
                },
                {
                  "channelId": "5572a108b3cdc86cf39001ce",
                  "name": "国际焦点"
                }
              ]))
            break;
        default:
            res.end('404')
            break;
    }
})
app.listen(8080);

8️⃣ 绝美宋词

相当于是使用Vue做一个搜索功能:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

代码:

<body>
  <div id="app">
    <h1 style="text-align: center">输入关键字,找一首词</h1>
    <!-- TODO:待补充代码 -->
    <div class="search-form">
      <input @input="search" v-model="val" type="text" id="search" class="search" placeholder="词牌名 词句 词人"/>
      <ul class="suggestions">
        <li v-for="item in showList" :key="item.title">
          <span class="poet" v-html="highlight(item.poetry_content)"></span>
          <span class="title" v-html="highlight(item.title) + '-' + highlight(item.author)"></span>
        </li>
      </ul>
    </div>
  </div>
  <script>
    let vm = new Vue({
      el:'#app',
      // TODO:待补充代码
      data:{
        val:'', // 输入内容
        list:[], // 源数据
        showList:[] // 进行展示的数据
      },
      created(){
      	// 获取数据
        axios.get("./data.json").then(res=>{
          this.list = res.data
        })
      },
      methods:{
      	// 搜索函数
        search(){
          if (this.val) {
          	// 输入内容不为空,使用filter过滤
            this.showList = this.list.filter(item=>{
              return item.poetry_content.includes(this.val) || item.title.includes(this.val) || item.author.includes(this.val)
            })
          }else {
          	// 输入内容为空,重置数据
            this.showList = []
          }
        },
        // 替换关键字进行高亮的函数
        highlight(str){
          let reg = new RegExp(this.val,'g');
          // replace第二个参数中$&代表插入匹配的子串。
          return str.replace(reg, `<span class="highlight">$&</span>`)
        }
      }
    })
  </script>
</body>

因为需要将关键字包上一层<span class="highlight"></span>来进行高亮,所以我使用了v-html指令来确保数据能以html的格式进行渲染,并配合replace替换关键字。

9️⃣ 平地起高楼

相当于是一道算法题,将一维数据转成树形结构,源数据:

[
  {
    id: "51", // 区域 id
    name: "四川省", // 区域名字
    pid: "0", // 区域的父级区域 id
  },
  {
    id: "5101",
    name: "成都市",
    pid: "51", // 成都的父级是四川省,所以 pid 是 51
  },
  // ...
];

转换成树结构:

[
  {
    id: "51", // 地址 id
    name: "四川省", // 地址名
    pid: "0", // 该地址的父节点 id
    children: [
      {
        id: "5101",
        name: "成都市",
        pid: "51",
        children: [
          {
            id: "510101",
            name: "市辖区",
            pid: "5101",
            children: [], // 如果该区域节点没有子集,children 则为空数组!!!
          },
          // ...
        ],
      },
      // ...
    ],
  },
  // ...
];

这题说复杂也复杂,说简单也简单,关键在于你怎么想了,想复杂的话能写几十行代码,想简单的话几行代码即可,我这里使用递归的方式进行解答。

首先需要先知道,convertToTree函数接收的参数regions代表一维数据数组,rootId代表树形结构中根节点的pidconvertToTree函数返回的是指定根节点(pid=rootId的)的树结构,所以我们只需逐渐降低rootId,递归调用convertToTree函数不断获取下一层的树形结构即可。

代码:

function convertToTree(regions, rootId = "0") {
  // TODO: 在这里写入具体的实现逻辑
  // 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
  // 如果不存在 rootId 下的子节点,则返回一个空数组
  let arr = [];
  for (let i = 0; i < regions.length; i++) {
    if (regions[i]['pid'] === rootId) {
      regions[i].children = convertToTree(regions,regions[i]['id']);
      arr.push(regions[i])
    }
  }
  return arr
}
module.exports = convertToTree; // 检测需要,请勿删除

从整个过程来看,convertToTree函数执行一次就找到了一层数据,每一个数据被找到时就开始以该数据为根节点去递归调用convertToTree函数找下一层的数据。每一次调用convertToTree函数就会遍历一遍regions数组,如果最终的树形结构有三层,那么就需要遍历三遍regions数组。

如果你不想定义新的变量(如上面定义的arr)或者想炫技,你可以使用数组的reduce方法进行递归,说到这你可能会有疑问:reduce不是用来求和的吗?如果单纯的将reduce归类于求和函数,你的知识面就太过单薄了。

先来看看怎么使用reduce解答吧:

function convertToTree(regions, rootId = "0") {
  // TODO: 在这里写入具体的实现逻辑
  // 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
  // 如果不存在 rootId 下的子节点,则返回一个空数组
  return  regions.reduce((res,current)=>{
    if (current['pid'] === rootId) {
      current.children = convertToTree(regions,current['id']);
      res.push(current);
    }
    return res;
  },[])
}
module.exports = convertToTree; // 检测需要,请勿删除

reduce的第二个参数是一个空数组,所以:

使用reduce跟使用for循环原理一样,只是看上去会给人一种很高级的感觉。

🔟 收快递了

这一题使用的是上一题我们转换后的树形结构:

[
  {
    id: "51", // 地址 id
    name: "四川省", // 地址名
    pid: "0", // 该地址的父节点 id
    children: [
      {
        id: "5101",
        name: "成都市",
        pid: "51",
        children: [
          {
            id: "510101",
            name: "市辖区",
            pid: "5101",
            children: [],
          },
          // ...
        ],
      },
      // ...
    ],
  },
  // ...
];

要求是:

我是思路是:

function findRegion(regions, regionName) {
  // TODO: 在这里写入具体的实现逻辑
  // 需要从树状结构的行政信息中,遍历找到目标区域的行政信息,如输入:成都市,返回 [四川省,成都市]
  // 如果所输入的位置信息不存在,则返回 null
  let arr = [],pid;
  // 根据name获取字对象的pid
  function getPid(list) {
    for (let i = 0; i < list.length; i++) {
      if (list[i].name === regionName) {
         arr.push(list[i].name)
         // 查询到pid了
         pid = list[i].pid
         return
      }else if (list[i].children.length > 0) {
        getPid(list[i].children)
      }
    }
  }
  // 根据pid查询父对象
  function addfName(list,pfid) {
    for (let i = 0; i < list.length; i++) {
      if (list[i].id === pfid) {
         arr.push(list[i].name)
         pid = list[i].pid
         if (pid !== '0') {
          // 表示还没到根节点,更新pid后从regions开始新的递归查询
          addfName(regions,pid)
         }
         return
      }else if (list[i].children.length > 0) {
        addfName(list[i].children,pid)
      }
    }
  }
  getPid(regions)
  addfName(regions,pid)
  return arr.length > 0 ? arr.reverse() : null
}
module.exports = findRegion; // 检测需要,请勿删除

arr数组 push name的过程是从树的底层向顶层进行的,所以最后得到的arr顺序是反的,需要reverse反向以下。

这种解法性能消耗较大,在比赛有限的时间中也想不到好的替换方法(因为博主是个算法菜鸟😬),如果大佬们有好的解法,欢迎在评论区或加入我们的交流群进行交流。

下面是职业院校组与大学组不一样的几个题:

💠 偷梁换柱(职业院校组)

考察了数据拦截,可以使用Object.defineProperty 或者 Proxy,要求:

使用Object.defineProperty:

// 请不要更改这个对象里面的内容
let person = {
  age: 0,
};
// TODO:在这里写入具体的实现逻辑
// 对 person 的 age 属性更新行为进行拦截
// 如果输入的年龄在 0 - 150 之间,则认为是合法
// 否则,如果小于 0,则返回 0;如果大于 150,则返回 150
function defineReactive(obj, key, value) {
  Object.defineProperty(obj, key, {
      get() {
          return value;
      },
      set(newVal) {
          if (newVal !== value) {
            newVal > 0
            	? newVal > 150
            		? (value = 150)
            		: (value = newVal)
            	: (value = 0)
          }
      }
  })
}
defineReactive(person,'age',person.age)
module.exports = person; // 检测需要,请勿删除

注意,千万不要直接这样写:

Object.defineProperty(person,'age',{
  set:(newVal)=>{
       newVal > 0
       	? newVal > 150
       		? (person.age = 150)
       		: (person.age = newVal)
       	: (value = 0)
  },
  get:()=>{
    return person.age
  }
})

直接这样写会陷入死循环,因为在Setter中访问了person.age,这又会导致触发Getter并且对person.age赋值又会触发person.age,一直触发下去,完全就是一个死循环,这也就是为什么我们在上面的代码块中套了一层defineReactive函数的原因。

defineReactive函数中的value相当于是闭包中的变量,它其实并不是真正的person.age,所以对value的一切操作都不会导致死循环。

使用Proxy:

// 请不要更改这个对象里面的内容
let person = {
  age: 0,
};
// TODO:在这里写入具体的实现逻辑
// 对 person 的 age 属性更新行为进行拦截
// 如果输入的年龄在 0 - 150 之间,则认为是合法
// 否则,如果小于 0,则返回 0;如果大于 150,则返回 150
person = new Proxy(person,{
  get: function(obj, key) {
      return  obj[key];
  },
  set: function(obj, key, value) {
    value > 0
    ? value > 150
      ? (obj[key] = 150)
      : (obj[key]  = value)
    : (obj[key] = 0)
  }
})
module.exports = person; // 检测需要,请勿删除

💠 大电影(职业院校组)

要求实现一个收藏的功能:

完成后,最终页面效果如下:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

代码:

// TODO:待补充代码
let timer;
$(".card-body-option-favorite img").each((i,t)=>{
  $(t).click(function(){
    if ($(this).attr('src') === './images/hollow.svg') {
    	// 切换图片路径
        this.src = "./images/solid.svg"
        // 显示弹窗
      	$('#toast__container').show()
      	// 添加定时器,两秒后关闭弹窗
	    timer = setTimeout(()=>{
	        $('#toast__container').hide()
	    },2000)
    } else {
      this.src = "./images/hollow.svg"
    }
  })
})
// 点击弹窗的关闭按钮
$('.toast__close').click(function () {
  $('#toast__container').hide()
  if (timer) {
    clearTimeout(timer)
  }
})

💠 乾坤大挪移心法(职业院校组)

这时一道很常见的循环调用的题,要求如下:

代码:

function mentalMethod(...args) {
    // TODO 待补充代码  
    let a =''
    a += args.join(',')
    let fn = function (...rest) {
        if (rest.length > 0) {
        	// 如果原本a有值,需要在加新值之前添加一个,分割
            a += a.length > 0 ? ',' + rest.join(',') :rest.join(',');
            // 继续返回fn这个函数
            return fn
        }else {
        	// 没有参数代表是最后一次调用,这时直接返回结果
            return '战胜' + a
        }
    }
    return fn
}

这题是利用了闭包,在外界调用fn函数时能够使用函数mentalMethod内层的变量。

💠 不能说的秘密(职业院校组)

题目要求实现一个随机密码生成器,完善 generatePassword.js 中的 generatePassword 函数,实现根据规则随机生成密码的功能。密码长度已由 input 框(id=passwordLength)的属性进行了限制最小 4,最大 20

最终效果:

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解

思路:

代码:

/**
 * @function_name generatePassword ->生成密码的函数
 * @param {*} lower 是否小写
 * @param {*} upper 是否大写
 * @param {*} number 是否是数字
 * @param {*} symbol 是否是特殊符号
 * @param {*} length 密码长度
 * @return {*} string
 */
function generatePassword(lower, upper, number, symbol, length) {
  //TODO:待补充代码
  // 特殊字符
  let sy = '!@#$%^&*(){}[]=<>/,.';
  // 存放字典的数组
  let arr = [];
  // 密码结果
  let str = '';
  // 向str中添加字符的函数,list代表字典。
  function addStrItem(list) {
  	// 表示从list中随机选一个字符添加到str中
    str += list[Math.floor(Math.random()*list.length)]
  }
  // 添加大写字母
  if (upper) {
    // 生成全部大写字母数组
    // Array(26)表示生成长度为26的空数组
    // fill用来向数组中填充内容,不填充内容是无法正常使用数组遍历的方法的
    let upperList = Array(26).fill('').map((item,index) => {
      return String.fromCharCode(index + 65)
    });
    // 添加到字典中
    arr.push(...upperList)
    // 此时就在所有大写字母中随机选一个添加到str中,确保了该选项对应的值在密码中存在。
    addStrItem(upperList)
  }
  // 添加小写字母
  if (lower) {
    let lowerList = Array(26).fill('').map((item,index) => {
      return String.fromCharCode(index + 97)
    })
    arr.push(...lowerList)
    addStrItem(lowerList)
  }
  // 添加数字
  if(number) {
    let numberList = Array(10).fill('').map((item,index)=>index)
    arr.push(...numberList);
    addStrItem(numberList)
  }
  if(symbol){
    letsymbolList = sy.split('')
    arr.push(...letsymbolList);
    addStrItem(letsymbolList)
  }
  // 添加剩余长度的字符
  while (str.length < length) {
    addStrItem(arr)
  }
  return str
}

静态 String.fromCharCode() 方法返回由指定的 UTF-16 代码单元序列创建的字符串。

🔼 结语

至此,《 第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 》的题解就结束了,这期模拟赛整体上来说并不算很难,但考察的知识点还是比较多的,特别是对基础知识以及常见算法的考察(相信你在做题的过程中也能察觉到),所以博主还是建议大家在做题的过程中好好总结,好好复习,祝大家都能在正式比赛中取得满意的成绩!

记录一下考试成绩,因各种原因导致显示的解题时间有误,本人实际是做了大概三个小时左右,大学组十个题满分才 150,最后得出的 178 分应该也是受解题时间的影响。
【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解
总结来说,比较耗时的题就是第 6 题了,大家可以注意一下,在正式比赛时做好规划。

如果本篇文章对你有所帮助,还请客官一件四连!❤️

【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 2 期 | 精品题解