2024第十五届蓝桥杯第一次模拟赛web组题解

https://www.lanqiao.cn/problem-list/28/

3. 迷惑的 this

1
2
3
4
5
handle() {
this.inputEl.addEventListener('input',(e)=>{
this.handleInput(e)
})
}

这个回调的调用者是this也就是search对象

这样就不行:

1
2
3
4
5
6
7
8
9
handle() {
// TODO:待补充代码
function deal(e) {
this.handleInput(e)
}
this.inputEl.addEventListener('input',(e)=>{
deal(e)
})
},

原因:**this指向调用者**。

deal的调用者是一个箭头函数,而箭头函数的thiswindow

(箭头函数不会创建自己的 this 上下文,所以 this 会在词法上指向外层的上下文,这里的外层上下文是全局上下文。)

4. 魔法失灵了

1
2
3
4
5
6
7
8
9
// 原先会响应式丢失
// let { value }={ ...data }

let { value }= toRefs( data)
// 返回的是ref,需要用.value

function update(val) {
value.value = val
}

5. 燃烧你的卡路里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const sortItem = (arr, pro, compare) => {
// TODO 根据 compare 匹配食材对象后返回这个对象
function comp(a,b){
if(a[pro]>b[pro]) return -1;
if(a[pro]==b[pro]) return 0;
if(a[pro]<b[pro]) return 1;
}
arr.sort(comp)
console.log(arr);
for(let i=0;i<arr.length;i++){
if(arr[i][pro]<=compare)
return arr[i]
}
};

6 司龄统计

考点:Echarts,动态属性名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 按照年龄分组的函数
const groupByAge = (peoples) => {
// 动态属性名(计算属性)
const obj = {};
peoples.forEach((element) => {
let age = element.age;
if (!obj[age]) {
// if(!obj.age){ 这样会查找`age`这个字符串
obj[age] = [];
}
obj[age].push(element);
});
return obj;
};

const app = Vue.createApp({
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
xAxisData.value=Object.keys(groupedPeople.value)
seriesData.value=Object.values(groupedPeople.value).map((item)=> item.length)
// 更新 echars 数据
updateData(xAxisData.value, seriesData.value);
});

return {
groupedPeople,
};
},
});

app.mount("#app");

7 不翼而飞的余额

  • store
  • router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setup() {
const depositAmount = Vue.ref() // 输入框中的的值->存款金额
const store = useMoneyStore() // 引入 store

// TODO:待补充代码,完善点击存款按钮事件
function deposit() {
store.addDeposit(depositAmount.value)
depositAmount.value=null
}
return {
deposit,
store,
depositAmount
}
}
1
2
3
4
5
6
7
8
9
const useMoneyStore = defineStore('money', () => {
const balance = ref(23);
const addDeposit=(add)=>{
balance.value+=add
}
return {
balance,addDeposit
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
},
]
})

8 个性化推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const http = require("http");
const fs = require("fs");
const path = require("path");
const qs = require("querystring");
const data = require("../data.json");

const server = http.createServer((req, res) => {
// 起始页路由处理
if (req.url === "/") {
// 读取 index.html 内容 如何读取文件
const indexPage = fs.readFileSync(path.join(__dirname, "../index.html"), {
encoding: "utf8",
});

// 将读取的 index.html 内容写入响应中,并返回给前端展示
res.writeHead(200, { "Content-Type": "text/html" });
res.write(indexPage);
res.end();
}
// 个性化页面路由处理
else if (req.url.startsWith("/customized")) {
let body = "";
req.on("data", (chunk) => {
body += chunk;
});

req.on("end", () => {
let { interested = [] } = qs.parse(body);
// console.log(data);
let result = "";
if (interested.length===0) {
// console.log(interested);
result = `<div class="unselect">你还未选择任何感兴趣的标签!</div>`;
} else {
// 当interested只选了一个的时候,这会是一个字符串而不是数组
if(! Array.isArray(interested)) interested=[interested]
// console.log(interested, '\n 11111');
const findContent = (target) => {
for (const item of data) {
if (item.tag == target) {
return item;
}
}
console.log("findContent");
};

const list = [];
const set = new Set();
// 枚举用户的兴趣列表
for (const interest of interested) {
// console.log(interest);
const content = findContent(interest);
list.push(content);
set.add(content);
}
// console.log(list);
// 读取相关兴趣
for(const content of list){
// continue
// console.log(content); continue;
if(!content.relevance.length) continue
// C++的关联列表是空的,这里会报错
for (const relevance of content.relevance) {
const relevanceContent = findContent(relevance);
if (!set.has(relevanceContent)) {
list.push(relevanceContent);
set.add(relevanceContent);
}
}
}
console.log(list);
result=list.map((item)=> `<div class="interest">
<div class="tag">${item.tag}</div>
<div>${item.content}</div>
</div>`).join('')
}
let indexPage = fs.readFileSync(path.join(__dirname, "../customized.html"), {
encoding: "utf8",
});
indexPage=indexPage.replace('<body></body>', `<body>` + result+`</body>`)
res.write(indexPage)
res.end();
});
}
});

server.listen(8080, () => {
console.log("server is running in port 8080");
});

9 贪吃蛇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
nextStep() {
// TODO:待补充代码
// debugger
for (let i = this.snakeBody.length - 1; i >= 1; i--) {
this.snakeBody[i] = {
...this.snakeBody[i - 1]
}
}
switch (this.direction) {
case 'right':
this.snakeBody[0].left += this.size
break;
case 'down':
this.snakeBody[0].top += this.size
break;
case 'left':
this.snakeBody[0].left -= this.size
break;
case 'up':
this.snakeBody[0].top -= this.size
break;
}
// debugger
// 或者
this.snakeBody.unshift(newHead);
this.snakeBody.pop();
// 结合unshift和pop,也能达到向后移动的效果
}

10 自定义表单验证器

1
2
3
watch(inputValue, (newValue) => {
emit('update:modelValue', newValue)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const is_email = (val) => {
// TODO:目标 2 待补充代码
let [before, behind] = val.split('@')

// 没有@或@后面没有字母
if (typeof(behind)!='string') return false
let userReg = /[0-9a-zA-Z]+/
if (!before.match(userReg)) return false

let [firstBehind, lastBehind] = behind.split('.')
let firstBehindReg = /^[0-9a-zA-Z]+$/
if (!firstBehind.match(firstBehindReg)) return false

let lastBehindReg = /^[0-9a-zA-Z]{2,4}$/
if (!lastBehind.match(lastBehindReg)) return false
console.log(111);
return true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// FormValidator.js
for (let key in props.formData) {
for (let rule of props.rules[key]) {
// 若某个字段对应的错误信息为多个时,将按照验证规则数组的顺序优先显示,即只显示第一个错误信息。
if (key in errors) break

// rule有两种
if ('validator' in rule) {
rule.validator(rule, props.formData[key], (error) => {
if (error) errors.value[key] = error.message;
})
} else {
if ('required' in rule) {
if (rule.required && props.formData[key] === '') {
errors.value[key] = rule.message
}
}
if ('type' in rule && rule.type === 'email') {
if (!validateByType(rule.type, props.formData[key])
|| props.formData[key].length < 8 || props.formData[key].length > 20) {
errors.value[key] = rule.message
}
}
}
}
}

2024第十五届蓝桥杯第一次模拟赛web组题解
https://asxjdb.github.io/2024/03/20/2024第十五届蓝桥杯第一次模拟赛web组题解/
作者
Asxjdb
发布于
2024年3月20日
许可协议