蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 2 | 精品题解
Posted 海底烧烤店ai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 2 | 精品题解相关的知识,希望对你有一定的参考价值。
🧑💼 个人简介:一个不甘平庸的平凡人🍬
🖥️ 蓝桥杯专栏:蓝桥杯题解/感悟
🖥️ TS知识总结:十万字TS知识点总结
👉 你的一键三连是我更新的最大动力❤️!
📢 欢迎私信博主加入前端交流群🌹
📑 目录
- 1️⃣ 凭空消失的 TA
- 2️⃣ 用户名片
- 3️⃣ 芝麻开门
- 4️⃣ 宝贵的一票
- 5️⃣ 粒粒皆辛苦
- 6️⃣ 618 活动
- 7️⃣ 资讯接口
- 8️⃣ 绝美宋词
- 9️⃣ 平地起高楼
- 🔟 收快递了
- 💠 偷梁换柱(职业院校组)
- 💠 大电影(职业院校组)
- 💠 乾坤大挪移心法(职业院校组)
- 💠 不能说的秘密(职业院校组)
- 🔼 结语
1️⃣ 凭空消失的 TA
题目说在 index.html
中未正常显示表单组件 myform
,先运行看一下效果:
发现 myform
组件里的立即创建
和取消
这两个文本被渲染了,这说明 index.html
确实是引入了 myform
,但为何myform
没有正常显示呢?
一开始我以为是myform
组件里出了问题,可检查一遍后并没有发现问题,最后回到index.html
才发现,是因为index.html
中未引入element-ui
的js
文件,我们加一行代码引入一下就解决了:
<!-- 引入 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️⃣ 用户名片
要求是需要将这个卡片垂直居中,并且还需要将卡片中左侧文字水平居中,看了一下HTML结构,发现它们都有一个共同的类名center
:
所以对center
类名定义样式就行了:
/* TODO 待补充代码 */
.center
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
上述代码利用定位将元素垂直水平方向各偏移父元素(position: relative
)的50%,这个时候元素还不是居中(因为定位偏移的中心点不在元素的中心上而是在元素的边界上):
使用transform
将元素在水平和垂直的负方向移动自身的50%(transform
运动的中心点在元素的中心位置):
这里深入说一下一个CSS选择器优先级的问题:
图中所示,作用于同一元素的.user-card .points
(后代选择器)的样式优先生效于.center
(类选择器)的样式,这就映证了网上说的后代选择器的优先级小于类选择器的说法是不够准确的。
其实,后代选择器和类选择器没有可比性,后代选择器是选择器组合方式的一种,它是一种组合,本身没有任何优先级(严格的用词叫特殊性) 可言。比如.user-card .points
在计算特殊性(优先级)时,是分别计算「.user-card」和「.points」的特殊性(优先级),完全不用考虑它们之间是用后代关联的。
按照权重来说.user-card .points
的样式优先生效于.center
的样式,是因为.user-card .points
含有两个类选择器,它的权重比.center
高。
关于CSS选择器权重、优先级的问题在实际开发中是比较重要的,如果你看到这里对它们还不是很了解,建议你去网上多看看关于它们的内容。
3️⃣ 芝麻开门
这题简单的考察了Promise
,最终实现以下效果:
代码:
/**
* @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
对象,并在点击事件中做出不同的处理(reject
,resolve
)即可。
4️⃣ 宝贵的一票
要求是实现一个动态列表的表单,可以新增选项和删除选项,最终效果:
添加的思路:
- 添加选项时先获取当前选项的个数,如果当前选项个数以及为2了,那么就需要先向前两个选项添加删除号(x)。
- 当前选项的个数小于2时,再添加一各选项,选项的总数也不会超过2,所以这时只需添加普通的选项即可。
- 当前选项的个数大于或等于2时,需要添加带有删除号(x)的选项。
删除的思路:
- 点击删除号(x)时先删除当前选项。
- 遍历余下的选项列表,更新它们的序号。
- 在遍历的时候判断余下的选项个数,若剩余的选项小于等于2了,需要删除每个选项后面的删除号(x)。
代码:
// 点击加号逻辑
$(".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 活动
就是按照官方给的最终效果图,去实现下面这个页面:
没啥技术含量,全靠堆HTML和CSS,这里就不放代码了。
但这个题是我认为是整场模拟赛里最坑人的题,特别废时间,我建议这个题要么放到最后再写(因为完成度50%以上就能得到分,其它题不行),要么完成差不多后就直接去做下面的题,别死扣细节,不然吃亏的都是你!
7️⃣ 资讯接口
题目要求使用 NodeJS
去创建一个服务器并响应一个/news
接口:
- 通过在
app.js
书写代码,创建一个服务器,使服务在 8080 端口运行。 - 访问
/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
做一个搜索功能:
代码:
<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蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-职业院校组 | 精品题解
蓝桥杯Web第十四届蓝桥杯Web模拟赛 3 期 | 精品题解(下)