QQ图片20230405164057

按照蓝桥题库里的标签分类,蓝桥web题型应该是这样子的↓不过身体状况不允许,我已无时间整理,留下这几个空标题,以后闲来无事把所有的题补上罢。请转至模拟题

CSS3

ES6

ECharts

ElementUI

HTML5

JS

Seletor?

1
document.querySelector()

JS函数封装

Node.js

接口怎么写?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const http = require('http')
const app = http.createServer()
const data = [……]
app.on("request", function(req, res) {
// UTF-8?
res.setHeader("Content-type", "text/html;charset=utf8");
// 判断一下路径?以/news为例
if (req.url === '/news') {
res.end(JSON.stringify(data))
} else {
res.end("404 NOT FOUND")
}
})
app.listen(8080, () => {
console.log("is running!")
})

Vue.js

jQuery

模拟题

话说以下的题在哪可以找到?

image-20230407163538477

JS基础

数据类型检测-一

完善 main.jsgetType 函数中的 TODO 部分,返回传入值的对应数据类型。

传入值以及 getType 函数返回值(大小写可忽略)按照如下方式对应:

传入值 返回值
‘s’ string
0 number
false boolean
undefined undefined
Symbol() symbol
function fn(){} function
123n bigint
null null
{} object
[] array
new Date date
new Map map
new Set set
/a/ regexp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @description: 数据类型检测
* @param {*} data 传入的待检测数据
* @return {*} 返回数据类型
*/
function getType(data) {
// TODO:待补充代码
if(typeof data != "object") return typeof data
if(!data) return "null"
return data.__proto__.constructor.toString().split(" ")[1].replace("()", "").toLowerCase()
}

module.exports = {
getType
}

我不是很能理解这个!

梅楼封的一天-一

image-20230405171552500
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
/**
* @description:
* @param {*} str
* @param {*} rule
* @param {*} symbol
* @param {*} dealPhone
* @return {*}
*/
const toDesensitization = (str, rule, symbol = "*", dealPhone = true) => {
// 结果集
let ans = {
"ids": [],
"newStr": ""
}
// 空字符串处理
if (!str) return null
if (!rule) return str
// 电话号码脱敏
if (dealPhone) {
str = str.replace(/(\d{3})\d{5}(\d{3})/, `$1${symbol.repeat(5)}$2`)
}
// 敏感词脱敏
let regex = new RegExp(Array.isArray(rule) ? rule.join('|') : rule, 'g')
ans.newStr = str.replace(regex, (match, index) => {
ans.ids.push(index)
return symbol.repeat(match.length)
})
// 返回结果集
return ans
};

module.exports = toDesensitization;

平地起高楼-二

image-20230406102227590
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function convertToTree(regions, rootId = "0") {
// TODO: 在这里写入具体的实现逻辑
// 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
// 如果不存在 rootId 下的子节点,则返回一个空数组
function travNode(region, rootId) {
// 太巧秒了,我没有这种巧妙的JS脑,希望做完这个题之后会长出来
return region.filter(el => rootId === el.pid)
.map(el => (el.children = travNode(region, el.id), el))
}

return travNode(regions, rootId)
}

module.exports = convertToTree; // 检测需要,请勿删除

收快递了-二

算是承接上一道题,此题思路是深搜,运用递归搜索出最终数组集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function findRegion(regions, regionName) {
// TODO: 在这里写入具体的实现逻辑
// 需要从树状结构的行政信息中,遍历找到目标区域的行政信息,如输入:成都市,返回 [四川省,成都市]
// 如果所输入的位置信息不存在,则返回 null
let ans = null
for (let region of regions) {
if (region.name === regionName) {
ans = [regionName]
break
} else {
if (!region.children) continue
let kidans = findRegion(region.children, regionName)
if (kidans) {
ans = [region.name, ...kidans]
break
}
}
}
return ans
}

module.exports = findRegion; // 检测需要,请勿删除

promise√

芝麻开门-二

过辣!

图片描述

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

  1. 点击“点击弹出对话框,输入咒语”按钮会调用 mPrompt 函数,mPrompt 调用后页面显示对话框。mPrompt 函数必须返回一个 promise 对象。
  2. 在对话框中的输入框中输入文字后,点击确认按钮,对话框消失, promise 返回成功,promise 成功的值为输入的值。
  3. 只有当成功的值为“芝麻开门”时门自动打开(已实现)。
  4. 点击取消,对话框消失,promise 返回失败,失败的值为 false
  5. 对话框的显示隐藏请使用 DOM 节点的添加删除实现。
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
/* 简单考察了Promise */

const incantations = "芝麻开门";
function init(el) {
document.querySelector(".wrapper .btn").addEventListener("click", () => {
mPrompt()
.then((res) => {
if (res === incantations) {
document
.querySelectorAll("#door .doors")[0]
.classList.add("door-left");
document
.querySelectorAll("#door .doors")[1]
.classList.add("door-right");
}
})
.catch((err) => {
console.log(err);
});
});
}
/**
* @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)

return new Promise((res, rej) => {
document.getElementById("cancel").onclick = function() {
div.remove()
rej(false)
}
document.getElementById("confirm").onclick = function() {
let val = document.getElementsByTagName("input")[0]
div.remove()
res(val.value)
}
})
}

封装Promisefy函数-三

以 Node.js 中常用的读取文件操作为例,封装一个 Promisefy 函数,将回调形式调用的读取文件方法转换成一个 Promise 的版本。

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
const fs = require('fs')
const path = require('path')
const textPath = path.join(__dirname, '/test.md')

// 读取示例文件
fs.readFile(textPath, 'utf8', (err, contrast) => {
// 通过promisefy转化为链式调用
const readFileSync = promisefy(fs.readFile)

readFileSync(textPath, 'utf8')
.then((res) => {
console.log(res === contrast) // 此处结果预期:true,即promise返回内容与前面读取内容一致
})
.catch((err) => {})
})

const promisefy = (fn) => {
// TODO 此处完成该函数的封装
return (textPath, type) => {
return new Promise((resolve, reject) => {
fn(textPath, type, (err, contrast) => {
if (err) {
reject(err)
} else {
resolve(contrast)
}
})
})
}
}

module.exports = promisefy // 请勿删除该行代码

​ 这段代码是对 Node.js 内置模块 fsreadFile 函数进行了封装,将其转化为返回 Promise 的形式,以实现更方便的异步操作。

具体来说,promisefy 函数接收一个函数 fn 作为参数,该函数需要具有以下特点:

  • 其最后一个参数为回调函数,该回调函数接收两个参数 errresult,其中 err 表示错误信息,result 表示返回结果。
  • 在执行过程中可能发生错误,此时需要调用回调函数并传入错误信息。
  • 在执行结束后需要调用回调函数并传入结果。

promisefy 函数返回一个新函数,该函数的参数与 fn 相同,但是该函数返回一个 Promise 对象,实现了对 fn 函数的封装,将其转化为 Promise 形式的异步操作。

​ 在该代码中,首先使用 fs.readFile 函数读取一个文件内容,并将其与另一个使用 promisefy 函数封装后的 readFileSync 函数返回的结果进行比较,以验证封装后的函数能够正常工作。

逃离二向箔-一

图片描述
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
// 使用 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({ max, el }) {
this.max = max;
this.requestQueue = [];
this.el = document.querySelector(el);
setTimeout(() => {
this.requestQueue.length > 0 && this.run();
});
this.startTime = Date.now();
}
addRequest(request) {
this.requestQueue.push(request);
}
async run() {
// TODO:待补充代码
let lque = []
while (this.requestQueue.length > 0) {
let req = this.requestQueue.shift()()
lque.push (
req.then(res => {
this.render(res)
}).catch(rej => {
this.render(rej)
}).finally(() => {
lque.shift()
})
)
if (lque.length >= this.max) {
await Promise.race(lque)
}
}
}
render(context) {
const childNode = document.createElement("li");
childNode.innerText = context;
this.el.appendChild(childNode);
}
}

let requestControl = new RequestControl({ max: 10, el: "#app" });
for (let i = 0; i < 25; i++) {
const request = createRequest(i);
requestControl.addRequest(request);
}


module.exports = {
requestControl,
};

JS样式选择器√

  • querySelector

蓝桥校园一卡通-三

过辣!

救命我的HTML/CSS基础烂到家了

介绍:

每年大一新生报道时,都需要办一张校园一卡通,无论吃饭、洗澡、买东西、甚至去图书馆借书都要用,小蓝想帮助学校做一个制卡界面,但是用 js 做用户输入验证不知道怎么写,快来帮助小蓝完成这个页面吧!

请在 index.html 文件中补全代码,具体需求如下:

  1. 完成表单验证:
  • 姓名:2-4 个汉字,验证错误在对应的表单项(class=form-group)添加类 class=has-error,并在下方显示报错信息(即 id=vail_name 的元素显示)。

tips: 正则中用 [\u4e00-\u9fa5] 表示汉字。

  • 学号: 1-12 位纯数字,错误即在对应的表单项(class=form-group)添加类 class=has-error,并在下方显示报错信息(即 id=vail_studentId 的元素显示)。
  1. 表单验证通过过后,正确显示卡片。在卡片(class=info)元素下的(class=item)的元素中按照顺序分别显示表单提交的内容:姓名:xxx,学号:xxx, 学院:xxx。
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
<body>
<div id="app">
<div class="form">
<div class="card" id="cardStyle">
<div class="cardName">蓝桥校园一卡通</div>
<div class="info">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<div class="content">
<div class="form-group">
<label for="studentName">姓名</label>
<input type="text" class="form-control" id="studentName" placeholder="请输入姓名" aria-describedby="inputSuccess2Status">
<span id="vail_name" style="display: none;" class="help-block"> 姓名错误提示</span>
</div>
<div class="form-group">
<label for="studentId">学号</label>
<input type="number" class="form-control" id="studentId" placeholder="请输入学号">
<span id="vail_studentId" style="display: none;" class="help-block"> 学号提示</span>
</div>
<div class="form-group">
<label for="college">学院</label>
<select id="college" class="form-control">
<option value="软件工程学院">软件工程学院</option>
<option value="信息技术学院">……</option>
</select>
</div>
<button id="submit">制卡</button>
</div>
</div>
</div>

<script>
// 获取DOM元素对象
const studentName = document.getElementById("studentName"); // 姓名
const studentId = document.getElementById("studentId"); // 学号
const college = document.getElementById("college"); // 学院
const submit = document.getElementById("submit"); // 制卡按钮
const cardStyle = document.getElementById("cardStyle"); // 卡片
const item = document.querySelectorAll(".item") // 卡片项

submit.onclick = () => {
// TODO 待补充代码
let hanzi = /^[\u4e00-\u9fa5]{2,4}$/.test(studentName.value)
let shuzi = /^\d{1,12}$/.test(studentId.value)
if (!hanzi) {
document.querySelector(".form-group").classList.add("has-error")
document.querySelector("#vail_name").style.display = "block"
return
} else {
document.querySelector(".form-group").classList.remove("has-error")
document.querySelector("#vail_name").style.display = "none"
}

if (!shuzi) {
document.querySelector(".form-group:nth-child(2)").classList.add("has-error")
document.querySelector("#vail_studentId").style.display = "block"
console.log("测试测试" + shuzi)
return
} else {
document.querySelector(".form-group:nth-child(2)").classList.remove("has-error")
document.querySelector("#vail_studentId").style.display = "none"
}

document.querySelector(".item").innerHTML = "姓名:" + studentName.value
document.querySelector(".item:nth-child(2)").innerHTML = "学号:" + studentId.value
document.querySelector(".item:last-child").innerHTML = "学院:" + college.value

// 添加 showCard 类显示放大一卡通的动画,请勿删除
cardStyle.classList.add('showCard')
}
</script>
</body>

JQ样式选择器√

大电影

过辣!

跟纸鹤大佬学到一个简明化代码的小技巧↓

选择器选择的元素命名:$this $dom元素

优雅……实在是!!!!!太优雅了!

图片描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// TODO:待补充代码
const $toast = $("#toast__container")
$(".card-body-option-favorite img").on('click', function(){
const solid = './images/solid.svg'
const hollow = './images/hollow.svg'
const $this = $(this)

if ($this.attr('src') === hollow) {
$this.attr('src', solid)

$toast.show()
setTimeout(() => {
$toast.fadeOut()
}, 2000)
} else {
$this.attr('src', hollow)
console.log($this+'!!!')
}
})

$(".toast__close").on('click', function(){
$toast.fadeOut()
})

传送门-国

.html的代码很有意思,这说明这个toFunction()也很有意思。

1
2
3
4
5
6
7
8
9
<div id="lift">
<a class="default-color active-color" onclick="toFunction.call(this,0)"
>顶部</a
>
<span class="line"></span>
<a class="default-color" onclick="toFunction.call(this,960)">中间</a>
<span class="line"></span>
<a class="default-color" onclick="toFunction.call(this,2000)">底部</a>
</div>

$(window).scrollTop()

解题如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$(window).scroll(function () {
// 页面滚动到指定范围,对应的侧边按钮字体变色
// TODO:请补充代码实现功能
let top = $(window).scrollTop()
if (top < 960) {
console.log("顶部")
$(".default-color").eq(0).addClass("active-color").siblings().removeClass("active-color")
} else if (top < 1920) {
console.log("中间")
$(".default-color").eq(1).addClass("active-color").siblings().removeClass("active-color")
} else {
console.log("底部")
$(".default-color").eq(2).addClass("active-color").siblings().removeClass("active-color")
}
});

/**
* @param {Object} scrollTopVal:到达指定位置需要滚动的高度
* 点击按钮,滚动到指定位置
*/
function toFunction(scrollTopVal) {
// TODO:请补充代码实现功能
$(window).scrollTop(scrollTopVal)
}

网页 PPT-三

过辣!

介绍:

除了使用办公软件来制作 PPT,利用前端技术其实我们也可以制作一个在浏览器播放的 PPT,这样的 PPT 更加方便传播和查看,而且可以最大限度地利用前端技术的布局和交互能力。本题请实现一个讲授 HTML 基础知识的网页 PPT。

请在 js/index.js 文件中补全代码,具体需求如下:

  1. 补充 switchPage 函数,实现根据 activeIndex 切换 PPT 页面的功能(切换页面请通过控制 section 元素的 display 属性实现),切换页面的同时需要改变左下角的页码 (class="page"),格式为 "当前页码 / 总页码",注意。
  2. 在播放到第一页时给“上一张”按钮 (class="btn left") 添加 disable 类,并在播放到最后一页时给“下一张”按钮 (class="btn right") 添加 disable 类,其他情况下则都不添加。
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
const sectionsCount = $("section").length;
let activeIndex = 0;

// 监听用户按下空格和方向键的事件
$(document).on("keydown", (e) => {
e.preventDefault();
if (e.key === " " || e.key === "ArrowRight") {
goRight();
}
if (e.key === "ArrowLeft") {
goLeft();
}
});

// 监听按钮点击事件
$(".btn.left").click(goLeft);
$(".btn.right").click(goRight);

// 切换下一张的函数
function goLeft() {
if (activeIndex === 0) {
return;
}
activeIndex -= 1;
switchPage();
}

// 切换上一张的函数
function goRight() {
if (activeIndex+1 === sectionsCount) {
return;
}
activeIndex += 1;
switchPage();
}

function switchPage() {
// TODO: 请补充该函数,实现根据activeIndex切换页面的功能,
// 并且在到达最后一页或第一页时给相应的按钮添加disable类
$(".page").text((activeIndex + 1) + ' / ' + sectionsCount)

$(`section:nth(${activeIndex})`).css("display", "block").siblings("section").css("display", "none")

if (activeIndex >= sectionsCount - 1) {
$(".right").addClass("disable")
$(`section:nth(${activeIndex})`).css("display", "flex")
} else if (activeIndex <= 0) {
$(".left").addClass("disable")
$(`section:nth(${activeIndex})`).css("display", "flex")
} else {
$(".right").removeClass("disable")
$(".left").removeClass("disable")
}
}

宝贵的一票-二

完成 index.html 文件中的 TODO 部分。

  1. 点击添加选项,页面中新增一个选项。选项前文字按照:选项 1,选项 2,选项 3 …… 顺序排列,当页面中的选项大于 2 个时,选项后面跟随删除按钮(即 x 图标)。带有删除图标的选项 DOM 结构如下:
1
2
3
4
5
6
7
8
9
10
<div class="mb-3 row item">
<label class="col-sm-2 col-form-label txt">选项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>
  1. 点击删除按钮,删除当前选项,并且选项前文字按照:选项 1,选项 2,选项 3 …… 顺序排列,当选项数量小于等于 2 个时,选项后面无删除按钮。

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

图片描述

我的逻辑好差,像这种多拐几个弯的就不会了。

代码如下:

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
<script>
let initRender = (txt) => {
return `
<div class="mb-3 row">
<label class="col-sm-2 col-form-label txt">${txt}</label>
<div class="col-sm-9">
<input type="text" class="form-control">
</div>
</div>
`;
};
$(
(function () {
// 初始化的时候渲染两条数据,且不带删除符号
for (let index = 0; index < 2; index++) {
let initList = initRender(`选项${index + 1}`);
$(".list").append(initList);
}
// 点击加号逻辑
$(".add").click(function () {
// TODO 待补充代码
let $list = $(".list")
let len = $list.children().length

if(len === 2) {
$list.children().each((index, item) => {
$(item).append(`
<div class="col-sm-1">
<!-- 删除图标 -->
<img class="del-icon" src="./images/x.svg" alt="" />
</div>
`)
})
}

if (len < 2) {
$list.append(initRender(`选项${len+1}`))
} else {
$list.append(`
<div class="mb-3 row item">
<label class="col-sm-2 col-form-label txt">选项${len+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) {
$(item).children()[2].remove()
}
})
});
})()
);
</script>

水果叠叠乐-一

怎么自如删除添加更改DOM元素啊555555

背景样式很好,很适合拿来做登录注册背景

这个找不到官方题解,只能看到CSDN一个很繁琐的

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>水果叠叠乐</title>
<script src="./js/jquery.min.js"></script>
<link rel="stylesheet" href="./css/style.css" />
</head>
<body>
<div id="stars"></div>
<div id="stars2"></div>
<div id="stars3"></div>
<ul id="card">
<li data-id="1" id="fruit-one">
<img src="./images/pineapple.svg" alt="" />
</li>
<li data-id="1" id="fruit-two">
<img src="./images/pineapple.svg" alt="" />
</li>
<li data-id="2" id="fruit-three">
<img src="./images/apple.svg" alt="" />
</li>
<li data-id="2" id="fruit-four">
<img src="./images/apple.svg" alt="" />
</li>
<li data-id="2" id="fruit-five">
<img src="./images/apple.svg" alt="" />
</li>
<li data-id="1" id="fruit-six">
<img src="./images/pineapple.svg" alt="" />
</li>
<li data-id="3" id="fruit-seven">
<img src="./images/avocado.svg" alt="" />
</li>
<li data-id="3" id="fruit-eight">
<img src="./images/avocado.svg" alt="" />
</li>
<li data-id="3" id="fruit-nine">
<img src="./images/avocado.svg" alt="" />
</li>
<li data-id="4" id="fruit-ten">
<img src="./images/grapes.svg" alt="" />
</li>
<li data-id="4" id="fruit-eleven">
<img src="./images/grapes.svg" alt="" />
</li>
<li data-id="4" id="fruit-twelve">
<img src="./images/grapes.svg" alt="" />
</li>
</ul>
<!-- 图片位置 -->
<!-- 卡槽位置 -->
<div class="fixed">
<div class="gradient-border" id="box"></div>
</div>
<script>
$("#card li").on("click", function (e) {
// TODO: 待补充代码
if($("#box li").length == 7) return
$(this).hide()
$("#box").append($(this).clone())
const list = $(`#box li[data-id = ${this.getAttribute('data-id')}]`)
if(list.length = 3) {
list.each((i, item) => {
item.remove()
})
}
});
</script>
</body>
</html>

折叠手风琴-习

用JQ实现手风琴图片展示效果

1
2
3
4
5
$(function() {
$(".option").click(function() {
$(this).addClass('active').siblings().removeClass('active')
})
})

.siblings()——返回某元素的所有同级元素

1
2
$("li.start").siblings().css({"color":"red","border":"2px solid red"});
// 返回带有类名start的每个li元素的所有同级元素

渐变色-一

代码见/Project/LittleProgram/渐变色

JQ & AJAX√

权限管理-三

左侧选择框内选项被全部移至右侧,所有用户权限均变为管理员
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
$(function () {
// 使用 ajax 获取 userList.json 数据并渲染到页面
getData();

// 为按钮添加事件
$("#add").click(function () {
// TODO:补充代码,实现功能
let $rt = $("#rightSelect")
$("#leftSelect").val().forEach((item) => {
$rt.append($("<option>").val(item).text(item))
$(`#leftSelect option[value=${item}]`).remove()

$(`#userList td:contains(${item})`).siblings().text('管理员')
})
});
$("#addAll").click(function () {
// TODO:补充代码,实现功能
let $lt = $("#leftSelect")
let $rt = $("#rightSelect")
$rt.append($lt.children())

$("#userList tr").not(":eq(0)").each(function() {
$(this).find("td:last-child").text('管理员')
})
});
$("#remove").click(function () {
// TODO:补充代码,实现功能
let $lt = $("#leftSelect")
$("#rightSelect").val().forEach((item) => {
$lt.append($("<option>").val(item).text(item))
$(`#rightSelect option[value=${item}]`).remove()

$(`#userList td:contains(${item})`).siblings().text('普通用户')
})
});
$("#removeAll").click(function () {
// TODO:补充代码,实现功能
let $lt = $("#leftSelect")
let $rt = $("#rightSelect")
$lt.append($rt.children())

$("#userList tr").not(":eq(0)").each(function() {
$(this).find("td:last-child").text('普通用户')
})
});
});

/**
* 修改权限
* @param {Object} right 要修改的权限
* @param {Object} changeList 要修改权限的用户列表
*/
function changeAccess(right, changeList) {
// TODO:补充代码,实现功能

}
// 异步获取数据
function getData() {
// TODO:补充代码,实现功能
$.get('./js/userList.json', (res) => {
res.forEach(element => {
$("#userList").append(`
<tr>
<td>${element.name}</td>
<td>${element.right ? '管理员' : '普通用户'}</td>
</tr>
`)
});
})
}

Element√

心愿便利贴-三

完成效果
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>心愿便利贴</title>
<!-- 引入element-ui样式 -->
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="./css/wish.css">
<!-- 引入element-ui组件库 -->
<script src="./js/vue.min.js"></script>
<script src="./js/index.js"></script>
</head>

<body>
<div id="app">
<h1>心愿便利贴</h1>
<div class="container">
<!-- TODO 待修改的代码 -->
<div class="card" :class="item.css" v-for="(item,index) in wishList" :key="index">
<div class="header">
<img class="close" @click="closeCard(index)" src="./images/ding.png" alt="close">
</div>
<el-image v-if="item.pic" style="width: 100px; height: 100px" :src="item.pic"
:preview-src-list="picList">
</el-image>
<div class="content">
{{item.content}}
</div>
<div class="name">{{item.name}}</div>
</div>
</div>
<div class="form">
<el-form ref="form" :rules="rules" label-position="left" :model="form" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input id="firstName" v-model="form.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="许愿内容" prop="content">
<el-input type="textarea" id="content" placeholder="请输入内容" v-model="form.content" show-word-limit>
</el-input>
</el-form-item>
<el-form-item label="图片上传">
<el-upload ref="uploadRef" action="#" :limit="1" list-type="picture-card" :on-remove="handleRemove"
:on-change="getPic" :auto-upload="false">
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{file}">
<img class="el-upload-list__item-thumbnail" :src="file.url">
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
</el-form-item>
<el-form-item>
<el-button id="onSubmit" type="primary" @click="onSubmit">发布</el-button>
<el-button @click="onRest">重置</el-button>
</el-form-item>
</el-form>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="form.pic" alt="">
</el-dialog>
</div>
</div>
</body>
<script>
const app = new Vue({
el: "#app",
data: {
wishList: [],
form: {
name: '',
content: '',
pic: ''
},
rules: {
// TODO 待补充验证的代码
name: [
{ required: true, message: '请输入姓名', trigger: 'blur' },
{ min: 2, max: 4, message: '长度在2到4个字符', trigger: 'blur' }
],
content: [
{ required: true, message: '请输入许愿内容', trigger: 'blur' },
{ min: 1, max: 30, message: '长度在1到30个字符', trigger: 'blur' }
]
},
num: 1,
picList: [],
textarea: '',
dialogVisible: false,
disabled: false
},
methods: {
// 提交方法
onSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
let obj = this.form;
obj.css = 'item' + this.num;
this.num++;
if (this.num > 4) {
this.num = 1;
}
this.wishList.push(obj)
this.form = {};
this.$refs.uploadRef.uploadFiles.pop()
console.log(this.wishList);
} else {
this.$message({
message: '提交错误!请检查输入内容',
type: 'warning'
});
return false;
}
});
},
// 关闭许愿卡
closeCard(index) {
this.wishList.splice(index, 1)
},
// 重置表单
onRest() {
this.$refs['form'].resetFields();
},
// 图片删除
handleRemove(file) {
let index = this.$refs.uploadRef.uploadFiles.findIndex(e => e.uid === file.uid);
this.$refs.uploadRef.uploadFiles.splice(index, 1);
},
// 模拟上传图片
getPic(e) {
this.form.pic = e.url;
this.picList.push(e.url)
},
// 预览图片
handlePictureCardPreview(file, fileList) {
this.form.pic = file.url;
this.dialogVisible = true;
}
}
});
</script>

</html>

饿了么第二次封装-一

目标:(实现单选选中效果)

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
<template>
<div class="main">
<el-table
ref="singleTable"
highlight-current-row
:data="tableData"
stripe
border
style="width: 100%"
>
<el-table-column label="单选" width="80">
<!-- TODO:完善单选按钮组件,实现需求(DOM 结构不能修改) -->
<!-- TODO:完善单选按钮组件,实现需求(DOM 结构不能修改) -->
<template slot-scope="scope">
<!-- 绑定change方法调用setCurrent -->
<el-radio
v-model="currentRow"
:label="scope.$index"
@change="setCurrent(scope.row)"
>
&nbsp;
</el-radio>
</template>

</el-table-column>

<el-table-column label="日期" width="180">
<template slot-scope="scope">
📅<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>

<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
<div class="tools">
<el-button @click="setCurrent(tableData[1])">选中第二行</el-button>
<el-button @click="setCurrent()">取消选择</el-button>
</div>
</div>
</template>

<script>
module.exports = {
props: {
tableData: {
type: Array,
default: () => [],
},
},
data() {
return {
currentRow: null,
};
},
methods: {
setCurrent(row) {
this.currentRow = this.tableData.indexOf(row) // 新增
this.$refs.singleTable.setCurrentRow(row); // 设置当前选中行
},
},
};
</script>
<style scoped>
.main {
width: 60%;
margin: 0 auto;
}
.tools {
margin-top: 20px;
text-align: center;
}
</style>

Vuex√

消失的Token-三

只有 user 模块通过 namespaced: true 开启了命名空间功能。因此,在调用 user 模块中的 gettersmutations 时,需要使用以下特定语法↓

1
'模块名/模块中的getters或mutations'
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
<script src="./components/login.js"></script>
<script src="./components/panel.js"></script>
<script>
// TODO 修改下面错误代码
var app = new Vue({
el: '#app',
data() { },
computed: {
welcome() {
return store.getters.welcome
},
username() {
return store.getters['user/username']
},
token() {
return store.getters['user/token']
}
},
methods: {
// 回车/点击确认的回调事件
login(username) {
username && store.commit('user/login', { username, token: 'sxgWKnLADfS8hUxbiMWyb' })
username && store.commit('say', '登录成功,欢迎你回来!')
}
}
})
</script>

vue√

趣购-三

请在 trolley.vue 文件中的 TODO 部分补全代码:

  • 用鼠标按下拖动图片到购物车(即 id="trolley" 的节点)中,然后松开鼠标,购物车会添加拖动的商品,并显示购物车商品数量。

  • 下方(即 class="result" 的方框)会显示购物车中商品的详情,详情以商品名 x 数量的形式展示,商品之间通过空格间隔。

  • 下方(即 class="result" 的方框)同时还会显示购物车中商品的总价。

    完成效果
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
<!-- TODO: 补充拖拽事件,请不要改动任何 id 属性 -->
<template>
<div class="container">
<div class="good-list">
<div v-for="good in goods" :key="good.name" class="good" draggable @dragstart="dragstart($event, good)">
<img :src="good.cover" />
<span>{{ good.name }}</span>
<span>¥{{ good.price }}</span>
</div>
</div>
<div id="trolley" class="trolley" @dragover.prevent="" @drop="drop">
<span id="bought" class="bought" v-if="bought.length !== 0">{{
bought.length
}}</span>
<img src="./images/trolley.jpeg" />
</div>
<div class="result">
<div>
购物车商品:<span id="goods">{{ goodsDetail }}</span>
</div>
<div>
购物车商品总计:<span id="total">{{ totalPrice }}</span>
</div>
</div>
</div>
</template>
<style>
......
</style>
<script>
module.exports = {
data() {
return {
goods: [
{
name: "畅销书",
price: 30,
cover: "./images/book.jpeg",
},
{
name: "收纳箱",
price: 60,
cover: "./images/box.jpeg",
},
{
name: "纸巾",
price: 20,
cover: "./images/paper.jpeg",
},
{
name: "电视",
price: 1000,
cover: "./images/tv.jpg",
},
],
bought: [],
};
},
// TODO: 请补充实现代码
computed: {
totalPrice() {
return this.bought.reduce((t, v) => v.price + t, 0);
},
goodsDetail() {
let r = this.bought.reduce((t, v) => {
return (t[v.name] ? t[v.name]++ : (t[v.name] = 1), t);
}, {});
let detail = '';
for (let i in r) {
detail += i + '*' + r[i];
}
return detail;
},
},
methods: {
dragstart(event, good) {
event.dataTransfer.setData('good', JSON.stringify(good));
},
drop(e) {
this.bought.push(JSON.parse(e.dataTransfer.getData('good')));
}
},
};
</script>

绝美宋词-二

图片描述

见 => E:\Project\LittlePrograms\poem

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<title>绝美宋词</title>
<link rel="stylesheet" href="css/style.css" />
<script src="./js/vue.min.js"></script>
<script src="./js/axios.min.js"></script>
</head>

<body>
<div id="app">
<h1 style="text-align: center">输入关键字,找一首词</h1>
<!-- TODO:待补充代码 -->
<div class="search-form">
<input v-model="search" type="text" id="search" class="search" placeholder="词牌名 词句 词人"/>
<ul class="suggestions">
<li v-for="item of showList">
<span class="poet" v-html="highlight(item.poetry_content)"></span>
<span class="title">
<span v-html="highlight(item.title)"></span>
-
<span v-html="highlight(item.author)"></span>
</span>
</li>
</ul>
</div>
</div>
<script>
let vm = new Vue({
el:'#app',
// TODO:待补充代码
data() {
return {
search: '',
poemList: [],
showList: [],
}
},

created() {
axios.get('./data.json').then(res => {
this.poemList = res.data
})
},

watch: {
search(newVal) {
if (!newVal) {
this.showList = []
return
}
this.showList = this.poemList.filter((item) => {
return item.author.includes(newVal) || item.title.includes(newVal) || item.poetry_content.includes(newVal)
})
},
},

methods: {
highlight(str) {
console.log(str)
return str.replaceAll(this.search, `<span class="highlight">${this.search}</span>`)
}
}
})
</script>
</body>
</html>

成语学习-一

为了达成这种效果↓

图片描述

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./js/vue.min.js"></script>
<title>成语学习</title>
<style>
* {
margin: 0;
padding: 0;
}
#app {
margin: auto;
}
.title {
text-align: center;
padding: 10px 0;
background-image: linear-gradient(-225deg, #69EACB 0%, #EACCF8 48%, #6654F1 100%);
}
.idiom_tips_box {
text-align: center;
margin: 30px 0;
}
.detailed_description {
border-radius: 20px;
padding: 15px 30px;
border-radius: 4px;
font-size: 16px;
}
.idiom_box {
display: flex;
align-items: center;
justify-content: center;
margin: 20px auto;
}
.item_box {
height: 120px;
width: 120px;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
border-radius: 8px;
margin-right: 10px;
background: rgb(248, 243, 243);
border: 1px solid #999
}
.optional_words_region {
margin: auto;
margin-top: 50px;
text-align: center;
display: flex;
flex-wrap: wrap;
}
.words {
display: block;
width: 50px;
height: 50px;
margin: 5px;
background: orange;
border: 1px solid black;
border-radius: 4px;
font-size: 40px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.words:hover {
background: rgb(247, 113, 3);
color: rgb(248, 243, 243);
}
.confirm_btn_box {
margin: 10px auto;
display: flex;
justify-content: center;
cursor: pointer;
}
.confirm_btn {
margin-top: 30px;
border-radius: 8px;
padding: 10px 30px;
color: white;
background: #409eff
}
</style>
</head>
<body>
<!-- {word:"热泪盈眶",means:"形容非常感激或高兴"} -->
<!-- {word:"才华横溢",means:"指才华充分显露出来"} -->
<!-- {word:"聚沙成塔",means:"比喻积少成多"} -->
<!-- {word:"名垂青史",means:"形容功业巨大,永远流传"} -->
<!-- {word:"绝无仅有",means:"形容极其稀少"} -->
<!-- {word:"衣衫褴褛",means:"形容身上衣服破破烂烂"} -->
<!-- {word:"焕然一新",means:"形容呈现出崭新的面貌"} -->
<!-- {word:"并驾齐驱",means:"比喻齐头并进,不分前后"} -->
<!-- {word:"博大精深",means:"形容思想和学识广博高深"} -->
<!-- {word:"忙里偷闲",means:"在繁忙中抽出空闲来"} -->
<div id="app">
<div class="title">成语学习</div>
<!-- 提示-描述 -->
<div class="idiom_tips_box">
<span class="detailed_description">提示:{{tip}}</span>
</div>
<!-- 选中的成语 -->
<div class="idiom_box">
<div class="item_box" v-for="item,index in idiom" @click="clear(index)">{{item}}</div>
</div>
<div :style="result == null ? 'color:#ccc' : result ? 'color : red' : ''" style="text-align:center">
{{result == null ? '请点击下方文字组织正确的成语(点击框内文字可清除)' : result ? '答案正确' : '答案错误'}}</div>
<!-- 可选区域 -->
<div class="optional_words_region">
<!-- <div>{{word}}</div> -->
<span class="words" v-for="(item,index) in words.split('')" :key="index" @click="getSingleWord(item)">
{{item}}
</span>
</div>
<!-- 确定 -->
<div class="confirm_btn_box">
<span class="confirm_btn" @click="confirm">确定</span>
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
tip: "",
arr: [
{ word: "热泪盈眶", tip: "形容非常感激或高兴" },
{ word: "才华横溢", tip: "指才华充分显露出来" },
{ word: "聚沙成塔", tip: "比喻积少成多" },
{ word: "名垂青史", tip: "形容功业巨大,永远流传" },
{ word: "绝无仅有", tip: "形容极其稀少" },
{ word: "衣衫褴褛", tip: "形容身上衣服破破烂烂" },
{ word: "焕然一新", tip: "形容呈现出崭新的面貌" },
{ word: "并驾齐驱", tip: "比喻齐头并进,不分前后" },
{ word: "博大精深", tip: "形容思想和学识广博高深" },
{ word: "忙里偷闲", tip: "在繁忙中抽出空闲来" }
],
words: '',
idiom: ["", "", "", ""],
result: null
},
created() {
this.tip = this.arr[parseInt(Math.random() * this.arr.length)].tip
this.arr.forEach(item => {
this.words += item.word
});

let words = this.words.split("");
words = this.shuffle(words)
this.words = words.join("")

},
methods: {
//乱序方法
shuffle(arr) {
let temp, length = arr.length;
for (let i = 0; i < length - 1; i++) {
let index = Math.floor(Math.random() * (length--));
temp = arr[index];
arr[index] = arr[length];
arr[length] = temp;
}
return arr;
},
//TODO 点击文字后,在idiom从左到右第一个空的位置加上该文字
getSingleWord(val) {
for (let i = 0; i < 4; i++) {
if (this.idiom[i] === '') {
this.$set(this.idiom, i, val)
break
} else {
continue
}
}

},
clear(i) {
this.idiom[i] = ""
this.$set(this.idiom, i, "")
},
// TODO 校验成语是否输入正确答案
// 猜中成语 result 为 true;
// 猜错成语 result 为 false;
// 例1:tip=‘形容非常感激或高兴’,idiom=["热","泪","盈","眶"],则result返回true
// 例2:tip=‘形容非常感激或高兴’,idiom=["泪","眼","盈","眶"],则result返回false
// 例3:tip=‘在繁忙中抽出空闲来’,idiom=["忙","里","偷","闲"],则result返回true
confirm() {
let i = 0
for (i = 0; i < this.arr.length; i++) {
if (this.tip === this.arr[i].tip) {
break
} else {
continue
}
}
if (this.arr[i].word === this.idiom.join('')) {
this.result = true
} else {
this.result = false
}
}
}
})
</script>
</body>
</html>

node接口√

资讯接口-二

  1. 通过在 app.js 书写代码,创建一个服务器,使服务在 8080 端口运行。
  2. 访问 /news 返回资讯数据,访问其他任意路径均返回字符串 404
Url 请求方式 参数 响应结果
news GET 显示资讯数据

数据需要设置为 utf8 格式,资讯数据格式如下:

1
2
3
4
5
6
7
8
9
10
[
{
"channelId": "5572a108b3cdc86cf39001cd",
"name": "国内焦点"
},
{
"channelId": "5572a108b3cdc86cf39001ce",
"name": "国际焦点"
}
]

555写接口!!!!

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
// TODO: 待补充代码
const http = require("http")
const app = http.createServer();
const data = [
{
"channelId": "5572a108b3cdc86cf39001cd",
"name": "国内焦点"
},
{
"channelId": "5572a108b3cdc86cf39001ce",
"name": "国际焦点"
}
]

app.on("request", function(req,res) {
res.setHeader("Content-type", "text/html;charset=utf8");
if (req.url === '/news') {
res.end(JSON.stringify(data))
} else {
res.end('404 NOT FOUND')
}
})

app.listen(8080, () => {
console.log("running")
})

http应用-一

  1. 通过在 app.js 书写代码,创建一个服务器,使服务在 8080 端口运行。
  2. 通过 node app.js 运行代码,使服务处于运行状态,点击右侧 【web 服务】,页面上显示 “hello world” 。
1
2
3
4
5
6
7
// TODO: 待补充代码
const http = require("http");
const app = http.createServer();
app.on("request",function (req,res) {
res.end("hello world")
})
app.listen(8080)

Echarts√

商品销量和销售额实时展示看板-三

过辣!

请在 js/index.js 文件中补全代码。

最终效果可参考文件夹下面的 gif 图,图片名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 指定图表的配置项和数据
const charData = {
title: {
text: '云课课程销量和销售额看板',
width: 100,
height: 50,
textStyle: {
lineHeight: 50,
},
left: 'center',

},
grid: {
top: 80,
},
tooltip:{
show: true,
},
xAxis: {
data: [],
},
// TODO:补全 `yAxis` 的设置,要求“销售额”(即,配置项 `name`)的位置(即,配置项 `position`)在图表的左侧,“销量”(即,配置项 `name`)的位置(即,配置项 `position`)在图表的右侧。
yAxis: [{
type: 'value',
name: '销售额',
position: 'left',
},
{
type: 'value',
name: '销量',
position: 'right',
}],
series: [
{
name: '销售额',
type: 'line',
data: [],
yAxisIndex: 0,
smooth: true
},
{
name: '销量',
type: 'bar',
data: [],
yAxisIndex: 1,
smooth: true
}
]
};

// 以下代码为模拟后端服务器返回数据
let sale = 0;
let count = 0;
// 销售额
const saleObj = {};
// 销量
const countObj = {};
let index = 0;
function Ajax() {
return new Promise((resolve, reject) => {
let randomNum = Math.random();
const randomSum = () => (randomNum * 500 + 900);
const randomCount = () => (randomNum * 50 + 80);
let i = index++ * 10
let key = `10:${i == 0 ? "00" : i}`;
if (index < 7) {
sale = randomSum();
Object.assign(saleObj, { [key]: sale.toFixed(2) })
count = randomCount();
Object.assign(countObj, { [key]: count.toFixed(2) })
}

const respondBody = {
"code": 200,
"msg": "success",
"data": {
saleObj,
countObj
}
};
setTimeout(() => {
resolve(respondBody);
}, 1000)
})
}

async function renderChart() {
const result = await Ajax();
document.querySelector("#result").innerText = JSON.stringify(result);
const myChart = echarts.init(document.getElementById('main'));
// TODO:补全代码,正确给 X 轴的时间,以及 Y 轴的商品的销售额 saleObj 和销量赋值 countObj。
charData.series[0].data = Object.values(saleObj)
charData.series[1].data = Object.values(countObj)
charData.xAxis.data = Object.keys(saleObj)

myChart.setOption(charData, true);
document.querySelector("#data").innerText = JSON.stringify(charData);
}
renderChart();
let times = 0;
let timer = setInterval(() => {
renderChart();
++times == 6 && clearInterval(timer);
}, 2000)

粒粒皆辛苦-二

图片描述

项目见 => E:\Project\LittlePrograms\EchartsTest1

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"code": 200,
"desc": "请求成功",
"data": {
"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 }
}
}

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
91
92
93
94
95
96
97
98
99
100
101
102
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>粒粒皆辛苦</title>
<script type="text/javascript" src="./js/echarts.min.js"></script>
<script src="./js/axios.min.js"></script>
</head>

<body style="height: 100%; margin: 0; overflow: hidden">
<div id="container" style="height: 80%; width: 80%; margin: 5% auto"></div>
<script>
var dom = document.getElementById("container");
var option;
var myChart = echarts.init(dom, null, {
renderer: "canvas",
useDirtyRect: false,
});
let initCharts = () => {
option = {
title: {
text: "近五年 x 市粮食总产量分布以及 2022 年粮食产量比例",
subtext: "单位(万吨)",
},
dataset: {
//source -> 图表显示所需的数据格式(饼形图和折线图共用),请勿手动修改此行
source: [
["全部", "2017", "2018", "2019", "2020", "2021", "2022"],
["小麦", 1, 1, 1, 1, 1, 1],
["大豆", 9, 9, 9, 9, 9, 9],
["马铃薯", 13, 13, 13, 13, 13, 13],
["玉米", 23, 23, 23, 23, 23, 23],
],
},
xAxis: { type: "category" },
yAxis: { gridIndex: 0 },
grid: { top: "55%" },
series: [
{
type: "line",
seriesLayoutBy: "row",
},
{
type: "line",
seriesLayoutBy: "row",
},
{
type: "line",
seriesLayoutBy: "row",
},
{
type: "line",
seriesLayoutBy: "row",
},
{
type: "pie",
id: "pie",
radius: "30%",
center: ["50%", "25%"],
label: {
// 2022 数据的百分比
formatter: "{b} {@2022} ({d}%)",
},
encode: {
itemName: "全部",
value: "2022",
tooltip: "2022",
},
},
],
};
if (option && typeof option === "object") {
// myChart.setOption -> 设置 echarts 数据的方法
myChart.setOption(option);
}
window.addEventListener("resize", myChart.resize);
};
initCharts();

// TODO: 待补充代码
axios.get('./data.json').then(res => {
let data = res.data.data
let source = [
["全部", "2017", "2018", "2019", "2020", "2021", "2022"],
["小麦"],
["大豆"],
["马铃薯"],
["玉米"],
]
for (let item in data) {
source[1].push(data[item].wheat)
source[2].push(data[item].soybean)
source[3].push(data[item].potato)
source[4].push(data[item].corn)
}
option.dataset.source = source
myChart.setOption(option)
})
</script>
</body>
</html>

学海无涯-一

图片描述

比较讨巧的办法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
option.xAxis.data=["2月第1周","2月第2周","2月第3周","2月第4周","3月第1周","3月第2周","3月第3周","3月第4周","3月第5周"]
option.series[0].data=[180,274,253,324,277,240,332,378,101]

myChart.setOption(option);
window.addEventListener("resize", myChart.resize);

const change=function(){
option.xAxis.data=["2月","3月"]
option.series[0].data=[1031,1328]
myChart.setOption(option);

}
var month = document.getElementById("month");
month.addEventListener("click",change)

吐了页面搭建/CSS3

太薄弱了太薄弱了太薄弱了太薄弱了太薄弱了

未做/未理解

习题

关于你的欢迎语-习题-JS

用JS实现特定用户欢迎语的展示(输入框输入的字符串拼接后显示)

1
2
3
4
5
6
7
8
9
10
function generate() {
subject = document.getElementById("subject");
event1 = document.getElementById("event1");
event2 = document.getElementById("event2");
if (subject.length==0 || event1.length==0 || event2.length==0){
return;
}
result = `欢迎用户${subject.value}${event2.value}学习${event1.value}课程!`;
document.getElementById("result").value = result;
}

功能化标签页-习题-JS

用JS实现选项卡切换功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 实现选项卡功能
function init() {
// TODO 待补充代码
let cho = document.querySelectorAll(".tabs>div")
let sho = document.querySelectorAll("#content>div")

for (let i = 0; i < cho.length; i++) {
cho[i].onclick = function() {
for(let a = 0;a<cho.length;a++) {
cho[a].classList.remove('active');
sho[a].classList.remove('active');
}

cho[i].classList.add("active")
sho[i].classList.add("active")
}
}
}
init();

新年贺卡-习题-JS-我万般不解

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
document.addEventListener('DOMContentLoaded', function () {
const greetingDisplay = document.getElementById("greeting-display")
const btn = document.getElementById("btn")
// 点击开始书写按钮
btn.addEventListener("click", () => {
show(greetingDisplay)
})
})

const greetings = [
"新年快乐!",
"接受我新春的祝愿,祝你平安幸福",
"祝你新年快乐,洋洋得意!",
"新的一年,新的开始;心的祝福,新的起点!",
"新年好!祝新年心情好,身体好,一切顺心!",
]

// 随机数函数 从 greetings 随机取一个值并返回
function writeGreeting() {
// TODO 带补充代码
console.log(Math.floor(Math.random()*greetings.length))
return greetings[ Math.floor(Math.random()*greetings.length) ]
}

/*
* @param {*} greetingDisplay 要显示内容的dom元素
*/
// show 将 writeGreeting 函数中返回的内容显示在 greetingDisplay 元素中
function show(greetingDisplay) {
// TODO 待补充代码
greetingDisplay.innerText = writeGreeting()
}

module.exports = { show, writeGreeting }

给页面化个妆-习题-CSS-我的布局啊!

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
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-image: url('../images/background-pic.jpeg');
background-size: cover;
color: #fff;
height: 945;
width: 1920;
}
.nav-bar {
display: flex;
align-items: center;
justify-content: flex-end;
}
.nav-bar img {
height: 50px;
width: 50px;
border-radius: 50%;
margin: 15px;
}

.content-container {
margin: auto;
display: flex;
justify-content: center;
}

.content {
height: 600px;
width: 450px;
border-radius: 10px;
background-color: rgba(0, 0, 0, .45);
text-align: center;
}
.content img {
margin-top: -15%;
height: 200px;
width: 200px;
border-radius: 50%;
}

.content h2 {
font-size: 45px;
font-weight: 800;
color:white;
margin-bottom: 40px;
}

.content input {
flex-wrap: wrap;
font-size: 20px;
border-radius: 5px;
width: 300px;
margin: 10px;
text-align: center;
}

.content button {
width: 80px;
height: 30px;
border-color: #041c32;
background-color: #2d4263;
font-size: 16px;
color:white;
margin: 10px 5px 20px 5px;
}

.content a {
color:white;
}

小兔子爬楼梯-习题-算法

简单啊,优化DP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const climbStairs = (n) => {
let dp0 = 0, dp1 = 1
if (n === 0) {
return dp0
}
let ans = 0
for (let i = 1; i <= n; i++) {
ans = dp0 + dp1
dp0 = dp1
dp1 = ans
}
return ans
}
module.exports = climbStairs;

购物车-习题-vue axios

实现这种效果,就是一个v-for遍历。还有axios请求JSON

图片描述
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<script src="./js/vue.js"></script>
<script src="./js/axios.js"></script>
<link rel="stylesheet" href="./css/element-ui.css">
<link rel="stylesheet" href="./css/index.css">
</head>

<body>
<div class="container" id="app">
<h4>购物车</h4>
<!-- 购物车列表 -->
<div>
<el-card class="box-card" v-for="item in carlist">
<!-- 商品图片 -->
<img :src="item.img">
<div>
<span>
<!-- 商品名称 -->
{{ item.name }}
</span>
<div class="bottom clearfix">
<el-button type="text" class="button" @click="item.num++">+</el-button>
<el-button type="text" class="button">
<!-- 商品数量 -->
{{ item.num }}
</el-button>
<el-button type="text" class="button" @click="item.num?item.num--:item.num">-</el-button>
</div>
</div>
</el-card>
</div>
</div>
</div>

<!-- 引入组件库 -->
<script src="./js/element-ui.js"></script>
<script>
new Vue({
el: "#app",
data: {
carlist: [] //购物车列表
},
created() {
// 在这里使用axios 发送请求
axios.get('./carList.json').then(value => {
this.carlist = value.data
})
},
})
</script>
</body>
</html>

多个斜线开始的路径重定向问题-习题-vue

源码中一个正则表达式的修改

路由器查询中的未定义值现在变为未定义字符串-习题-vue

vue-router v3.4.0 版本代码中存在一个 Bug,路由器查询中的未定义值现在变为未定义字符串。请修复此问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export function resolveQuery (
query: ?string,
extraQuery: Dictionary<string> = {},
_parseQuery: ?Function
): Dictionary<string> {
// ... 省略部分代码
for (const key in extraQuery) {
const value = extraQuery[key]
parsedQuery[key] = Array.isArray(value)
? value.map(castQueryParamValue)
: castQueryParamValue(value)
}
return parsedQuery
}
const castQueryParamValue = value => (value == null ? value : '' + value)

警告已弃用的 addRoutes-习题-vue

其实就是个console.warn

扩展: