蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组 | 精品题解
Posted 海底烧烤店ai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组 | 精品题解相关的知识,希望对你有一定的参考价值。
🧑💼 个人简介:一个不甘平庸的平凡人🍬
🖥️ Nodejs专栏:Node.js从入门到精通
🖥️ TS知识总结:十万字TS知识点总结
👉 你的一键三连是我更新的最大动力❤️!
📢 欢迎私信博主加入前端交流群🌹
📑 目录
- 🔽 前言
- 1️⃣ 数据类型检测
- 2️⃣ 渐变色背景生成器
- 3️⃣ 水果叠叠乐
- 4️⃣ element-ui 组件二次封装
- 5️⃣ http 模块应用
- 6️⃣ 新课上线啦
- 7️⃣ 成语学习
- 8️⃣ 学海无涯
- 9️⃣ 逃离二向箔
- 🔟 梅楼封的一天
- 🔼 结语
🔽 前言
新一期的蓝桥杯大赛开始报名已经有一段时间了,最近博主的粉丝朋友们有很多都已经在积极备考了,也有很多朋友私信我说让我多发发题解,于是我就去蓝桥杯官网碰碰运气,看能不能找到好的题目(因为今年是蓝桥杯开放Web应用开发方向的第二年,官网上的备赛题目比较少),正巧发现蓝桥杯正在举行线上模拟赛,我便花了一些时间做题、总结、写作,于是这篇文章就诞生了。
如标题所见,这是 Web 应用开发模拟赛 1 期大学组 的题解,关于蓝桥杯更多的题解博主会在之后的文章中陆续更新,欢迎大家关注订阅!
话不多说,开撕!
本篇只会大概提出题目要求,关于题目的更多细节可自行去模拟赛主页查询:Web 应用开发模拟赛 1 期大学组
1️⃣ 数据类型检测
这一题大致的意思就是写一个能够判断参数数据类型的函数,咋一看感觉非常的简单,可再仔细一看题目要求,足足需要判断14种类型!如果你的基础知识不牢固是有很大机率通不过这题的,从题目的通过率就可以看出:
作为第一题,虽然只有5分,并且挑战人数是10道题中最多的,但通过率确是10道题中最低的,这恰恰反应了大家的基础核心知识不牢固,所以还是简易大家多补补基础核心知识。
要求:
虽然有14种类型需要判断,但其实只需要一行代码就能通过这题:
/**
* @description: 数据类型检测
* @param * data 传入的待检测数据
* @return * 返回数据类型
*/
function getType(data)
// TODO:待补充代码
return Object.prototype.toString.call(data).slice(8,-1)
javascript中判断数据类型主要有以下几种方式:
-
typeof 可以用来区分除了
null
类型以外的原始数据类型(undefined
、number
、string
、symbol
、boolean
)和对象类型中的函数,针对其它类型时typeof
一律返回object
类型。 -
instanceof 运算符用于检测构造函数的
prototype
属性是否出现在某个实例对象的原型链上,所以它不能用来判断原始数据类型的数据。并且
instanceof
的结果并不一定是可靠,因为在ES7
的规范中可以通过自定义Symbol.hasInstance
方法来覆盖insanceof
的默认行为 -
Object.prototype.toString.call 能够满足大部分场景下的需求,但它无法区分数字类型和数字对象类型(同理还有字符串类型和字符串对象类型等,)
Object.prototype.toString.call(2).slice(8,-1) // "Number" // new Number(2)实际是一个数字对象类型 Object.prototype.toString.call(new Number(2)).slice(8,-1) // "Number"
ES7
规范中可以使用Symbol.toStringTag
自定义Object.prototype.toString
方法的行为,所以该方法判断数据类型也不一定是完全可靠的。 -
Array.isArray 用来判断是否是数组
所以这题对于知道Object.prototype.toString.call
方法的同学来说,几乎就是秒解!
2️⃣ 渐变色背景生成器
这题所实现的渐变色背景生成器还是非常有意思的,推荐大家去看一下它完整的源码(代码非常少):
主要考察的就是通过JavaScript来修改自定义的 CSS 变量,题中主要的代码如下(并不是全部代码,不需要我们了解与实现的代码这里就没有贴出,原题可自行查阅蓝桥官网)
html:
<div class="controls">
<input id="color1" type="color" name="color1" value="#00dbde" />
<input id="color2" type="color" name="color2" value="#fc00ff" />
</div>
CSS:
/* 注意这里定义的 CSS 变量,它们会用于生成渐变色背景 */
:root
--color1: #00dbde;
--color2: #fc00ff;
const inputs = document.querySelectorAll(".controls input");
/**
* 上面已经选取了两个取色器
* 请添加相应的 JS 事件处理函数并绑定到合适的事件监听器上(提示:change 事件)
* 这样我们就可以用取色器选取颜色来生成下方的渐变色背景啦
* */
inputs.forEach((item)=>
item.addEventListener("change",function (e)
document.querySelector("html").style.setProperty(`--$e.target.id`, e.target.value);
)
)
遍历获取到的两个取色盘元素(input.color
),分别对其添加change
事件,然后通过document.querySelector("html").style.setProperty
方法修改html
元素(根元素,也即是:root
)上css变量的值即可。
这一题题目参考信息中给出了如何使用CSS变量的介绍,根据这个提示来做这题还是非常简单的。
3️⃣ 水果叠叠乐
这简直就是简易般的羊了个羊:
这一题有个坑,就是点击元素时是需要将这个被点击的元素克隆一份添加到下方的栏中,而不是直接将被点击的元素移动到下方的栏中。
具体实现代码如下
HTML:
<ul id="card">
<li data-id="1" id="fruit-one">
<img src="./images/pineapple.svg" alt="" />
</li>
<!-- 多个li... -->
</ul>
<!-- 图片位置 -->
<!-- 卡槽位置 -->
<div class="fixed">
<div class="gradient-border" id="box"></div>
</div>
JavaScript:
$("#card li").on("click", function (e)
// TODO: 待补充代码
if($("#box li").length===7) return;
// 向box中添加当前点击元素的克隆
$("#box").append($(this).clone());
// 隐藏当前点击元素
$(this).hide();
// 找到与当前点击元素类别一样的其它所有元素
const list=$(`#box li[data-id=$this.getAttribute('data-id')]`);
if (list.length>=3)
// each是jQuery遍历元素的方法
list.each((i,item)=>
// 移除元素
item.remove()
)
);
我们知道DOM
的事件处理函数中的this
指的是触发事件的DOM
元素,我这里使用$()
包裹this
($(this)
)的目的是使this
变成JQ
对象,从而能够使用jQuery
提供的方法,如clone
克隆元素。
4️⃣ element-ui 组件二次封装
需要封装element-ui
的表格组件,实现点击表格组件左侧radio
时选中该行,题目要求说了一大堆,其实实际实现只需修改两行代码就行:
<!-- TODO:完善单选按钮组件,实现需求(DOM 结构不能修改) -->
<template slot-scope="scope">
<el-radio v-model="currentRow" :label="scope.$index"> </el-radio>
</template>
5️⃣ http 模块应用
要求就是使用原生http
模块,搭建起来一个简单的Node
服务器,并返回 “hello world”
,考察的就是基础的原生知识,如果你对Node
还不了解,可以订阅我的
Node.js从入门到精通专栏(私信进群能够享返现活动)。
// TODO: 待补充代码
const http = require("http");
const app = http.createServer();
app.on("request",function (req,res)
res.end("hello world")
)
app.listen(8080)
6️⃣ 新课上线啦
就是按照官方给的最终效果图,去实现下面这个页面:
没啥技术含量,全靠堆HTML和CSS,这里就不放代码了。
但这个题是我认为是整场模拟赛里最坑人的题,特别废时间,我建议这个题要么放到最后再写(因为完成度50%以上就能得到分,其它题不行),要么完成差不多后就直接去做下面的题,别死扣细节,不然吃亏的都是你!
7️⃣ 成语学习
这个题也是非常的有意思,不过需要我们写的代码并不多,大多都是官方已经给出了。
//TODO 点击文字后,在idiom从左到右第一个空的位置加上改文字
getSingleWord(val)
for (let i = 0; i < this.idiom.length; i++)
if (!this.idiom[i])
this.idiom[i] = val
this.$set(this.idiom, i, val)
return
// TODO 校验成语是否输入正确答案
// 猜中成语 result 为 true;
// 猜错成语 result 为 false;
// 例1:tip=‘形容非常感激或高兴’,idiom=["热","泪","盈","眶"],则result返回true
// 例2:tip=‘形容非常感激或高兴’,idiom=["泪","眼","盈","眶"],则result返回false
// 例3:tip=‘在繁忙中抽出空闲来’,idiom=["忙","里","偷","闲"],则result返回true
confirm()
const target = this.arr.find(item => item.tip === this.tip);
if (target.word === this.idiom.join(''))
this.result = true
else
this.result = false
这里使用的是vue2,需要注意的一点就是当我们直接修改data里的数组中的元素时,视图并不会响应式更新,如果你了解vue2的响应式原理,应该明白这是vue2响应式的一个缺陷所在,我们必须使用$set
来修改触发从而引发视图更新。
其实题中原有的代码已经显示了这一点,如clear
函数:
clear(i)
this.idiom[i] = ""
this.$set(this.idiom, i, "")
,
8️⃣ 学海无涯
这一题稍微有点复杂,但只要自己理清楚思路,还是能够做出来的,先看一下效果:
题中使用了Echarts,了解Echarts的朋友知道 Echarts 的表格有x轴和y轴的数据(都是数组形式),所以我们知道只要将题中给我们的数据转换成对应的格式就行了。
复杂的地方在于数据处理,原数据如下:
"data":
"2月": [
30, 40, 30, 20, 10, 20, 30, 69, 86, 12, 32, 12, 23, 40, 50, 61, 39, 28,
20, 35, 20, 38, 43, 52, 30, 39, 52, 70
],
"3月": [
36, 48, 52, 30, 39, 52, 20, 18, 25, 33, 21, 36, 44, 63, 32, 89, 98, 23,
25, 36, 29, 31, 42, 23, 45, 56, 98, 83, 25, 28, 48
]
我的思路就是将原数据转换成两个对象,一个代表周的x轴y轴数据,一个代表月的x轴y轴数据,所以两个对象的结构是一模一样,转成后的两个对象如下:
// 周数据
weekData =
x: ['2月第1周', '2月第2周', '2月第3周', '2月第4周', '3月第1周', '3月第2周', '3月第3周', '3月第4周', '3月第5周'],
y: [180, 274, 253, 324, 277, 240, 332, 378, 101]
// 月数据
monthData =
x: ['2月', '3月'],
y: [1031, 1328]
现在我们根据代码来一点点了解我是如何转换的:
// TODO:待补充代码
let weekData =
x:[],
y:[]
, monthData =
x:[],
y:[]
// 定义一个函数:用来修改option对象并重置Echarts图标
function mySetOption(data)
// 修改x轴数据
option.xAxis.data = data.x;
// 修改y轴数据
option.series[0].data = data.y;
// 重置图表
myChart.setOption(option);
// 添加点击事件
document.querySelector(".tabs").addEventListener("click",function (e)
if (e.target.id==="week")
mySetOption(weekData)
else if(e.target.id==="month")
mySetOption(monthData)
)
// 获取数据
axios.get('./data.json').then(res=>
const data = res.data.data
for (const key in data)
// weekCount代表一周数据的和,monthCount代表一月数据的和,weekNum代表第几周
let weekCount = monthCount =0,
weekNum = 1;
for (let i = 0; i < data[key].length; i++)
// 数据累加
weekCount += data[key][i];
monthCount += data[key][i];
// 每一周的最后一天或不足一周的最后一天进行push数据
if ((i+1) % 7 === 0 || ((data[key].length - i <= 7) && (i === data[key].length - 1)))
weekData.x.push(`$key第$weekNum++周`)
weekData.y.push(weekCount)
// 重置周数据的和为0
weekCount = 0
monthData.x.push(key)
monthData.y.push(monthCount)
// 获取到数据后调用一次mySetOption重置图表
mySetOption(weekData)
)
代码不算难,相信大家根据代码里的注释都能够理解,着重说一下上面我使用的 if 表达式:
(i+1) % 7 === 0 || ((data[key].length - i <= 7) && (i === data[key].length - 1))
要明白我们求每一周的总数居时需要在第二周开始前将
weekCount
归零,我选择了在每周的最后一天(且已经push
了数据)重置weekCount
,而不是在每周的第一天(计算数据之前)重置weekCount
,是因为我感觉这样做判断比较好写。
首先(i+1) % 7 === 0
判断了是每星期的最后一天,如:第一周的星期日,在数组中下标为6,加上1对7取余就得0。
((data[key].length - i <= 7) && (i === data[key].length - 1)
中data[key].length - i <= 7
代表剩余的数据不足7条,i === data[key].length - 1
代表到了数组最后一项。之所以做这么一个判断,是为了适配天数不是7的倍数的情况,如3月31天,计算完前4周的数据后剩余3天的数据(31-4x7),这3天也要求和作为第5周的数据,所以需要在最后一天结算这三天。
9️⃣ 逃离二向箔
这个题目很有意思,让我瞬间想起了三体宇宙,顿时感觉这题不简单,结果还正如我所想,题中考察的是promise
以及JavaScript
中的事件执行机制(先执行同步代码再执行异步代码),对于promise
,相信大多数人都会比较头疼,这一题考察的角度也比较刁钻,让我们一起来看一看吧!
题目的大致要求就是有一个数组,里面存放了很多需要发射的飞船(一个返回promise
对象的函数),然后给了我们一个最大数量,我们只能一次性发送这个最大数量的飞船,当有一个飞船发射成功(promise
执行结束),我们才能继续发射下一个飞船。
完整代码:
// 使用 promise 模拟请求 + 3000ms后完成得到发射后结果
function createRequest(i)
return function ()
return new Promise((resolve, reject) =>
const start = Date.now();
setTimeout(() =>
if (Math.random() >= 0.05)
resolve(
`第$i + 1艘曲率飞船达到光速,成功逃离,用时$Date.now() - start`
);
else
reject(
`第$i + 1艘曲率飞船出现故障,无法达到光速,用时$
Date.now() - start
`
);
, 3000 + i * 100);
);
;
class RequestControl
constructor(蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-职业院校组 | 精品题解
蓝桥杯Web第十四届蓝桥杯Web模拟赛 3 期 | 精品题解(下)