26. 封装Promisefy函数
27.偷梁换柱
我们要在输出前,对age做出判断即可
// 请不要更改这个对象里面的内容
let person = {
age: 0,
};
//定义一个输出值
let newAge = 0
// 对 person 的 age 属性更新行为进行拦截
Object.defineProperty(person,'age',{
get(){
return newAge;
},
set(value){
// 如果输入的年龄在 0 - 150 之间,则认为是合法
if(value <= 0){
newAge = 0
}else if(value >=150){
// 否则,如果小于 0,则返回 0;如果大于 150,则返回 150
newAge = 150
}else{
newAge = value
}
}
})
module.exports = person; // 检测需要,请勿删除
28.css考拉
.face {
z-index: 1;
width: 430px;
height: 380px;
background: #a0abb6;
border-radius: 50%;
align-items: center;
/* 创造一个网格布局
6 个纵列(column) --
前后两列两等分 (可用 fr 代表一份),
中间 4 列均为 25px 宽度
4 个横行(row) --
上下均为 50px,中间两等分
*/
display: grid;
grid-template-columns:1fr 25px 25px 25px 25px 1fr;
grid-template-rows:50px 1fr 1fr 50px;
}
.eye {
/*
长为 30px
高为 30px
颜色为 #090b0e
圆角为 50%
位置居中
*/
display: grid;
width: 30px;
height:30px;
background-color: #090b0e;
border-radius: 50%;
}
.eye.left {
/* 按照图示选取 grid-area */
/* 从第二行第二列开始,横跨三行三列*/
grid-area:2/2/3/3;
}
.eye.right {
/* 按照图示选取 grid-area */
grid-area:2/5/3/6;
}
.nose {
/*
高为 100%
颜色为 #3b464f
上方圆角为 50%
下方圆角为 40%
按照图示选取 grid-area
*/
height:100%;
background-color: #3b464f;
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 40%;
border-bottom-left-radius: 40%;
grid-area: 3/2/4/6;
}
.blush {
/*
长为 40px
高为 30px
颜色为 #f6b9bf
圆角为 50%
*/
width: 40px;
height:30px;
background-color: #f6b9bf;
border-radius: 50%;
}
.blush.left {
/* 按照图示选取 grid-area
并调整位置
*/
grid-area: 2/1/3/2;
align-self: end;
justify-self: end;
}
.blush.right {
/* 按照图示选取 grid-area
并调整位置
*/
grid-area: 2/6/3/7;
align-self: end;
justify-self: start;
}
29.别抖了
input.addEventListener("input",debounceFn((e)=>{
const value=input.value;
output.innerText+=`发送API请求,参数:${value} \n`;
},500)); // 延后500ms执行
//fn是执行输出的函数,delay是防抖执行时间
function debounce(fn, delay = 0) {
// TODO: 在这里写入具体的实现逻辑
// 返回一个新的防抖函数
// 即使函数在 delay 时间段内多次被调用,也只会在最后一次函数被调用的 delay 时间结束后执行
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(()=>{
fn(...args)
},delay)
}
}
30.乾坤大挪移心法
这道题,我们可以理解成,反复调用一个函数,并且返回这个函数,直到只剩下0个参数的时候,返回同一个结果,这样不管我们的参数如何,都会返回同一个结果
function mentalMethod(...args) {
// TODO 待补充代码]
//如果含参,继续调用
if (args.length) {
return mentalMethod;
}
return '战胜峨眉,武当,少林'
}
console.log(mentalMethod("峨眉")("武当")("少林")());
console.log(mentalMethod("峨眉", "武当")("少林")());
console.log(mentalMethod("峨眉", "武当", "少林")());
下面是执行演示
31.不能说的秘密
// 特殊字符
let sy = '!@#$%^&*(){}[]=<>/,.';
// 存放字典的数组
let arr = [];
// 密码结果
let str = '';
上面的代码中,定义了特殊字符,一个数组用于存放可以选择字符数组,根据我们的点击规则,将符合内容放进数组里面,例如如果我们点击了大写字母,则将26个大写字母放进这个字典数组里面
定义一个函数,用于添加结果元素
// 向str中添加字符的函数,list代表字典。
function addStrItem(list) {
// 表示从list中随机选一个字符添加到str中
str += list[Math.floor(Math.random()*list.length)]
}
这个函数在每次调用的时候都会返回list数组中的随机值
如果点击了大小写
// 添加大写字母
if (upper) {
// 生成全部大写字母数组
// Array(26)表示生成长度为26的空数组
// fill用来向数组中填充内容,不填充内容是无法正常使用数组遍历的方法的
let upperList = Array(26).fill('').map((item,index) => {
//将数字转换成大写字母
return String.fromCharCode(index + 65)
});
// let upperList = ['A', 'B', 'C', 'D',.....]和上面是一样的
// 添加到字典中
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)
}
完整代码
/**
* @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
}
动态演示
32.分阵营,比高低
原数组
[
{
name: "潇然",
class: 2, // 班级
math: 110, // 数学成绩
language: 92, // 语文成绩
english: 114, // 英语成绩
physics: 56, // 物理成绩
chemistry: 74, // 化学成绩
},
{
name: "张三",
class: 1,
math: 100,
language: 80,
english: 60,
physics: 80,
chemistry: 60,
},
// ...
];
转换成的对象
具体功能说明:
- 接收所有学生成绩的数组。
- 将学生按不同的班级分组,且班级内按照总分降序排列(如果学生 A、B 的总分相同,则按照学生在原数据中的先后顺序进行排列,不要在学生成绩的数据对象中添加多余的字段,确保排序后的对象和排序前一致)。
- 返回分班排序后的对象(如果传入的学生成绩列表为空,则返回一个空对象),形如:
// 返回的结果对象:
// key 是班级号,同一个班级中学生成绩降序排列
{
1: [
{
name: "潇然",
class: 1,
math: 110,
language: 92,
english: 114,
physics: 56,
chemistry: 74,
},
{
name: "张三",
class: 1,
math: 10,
language: 8,
english: 60,
physics: 8,
chemistry: 60,
},
// ...
],
2: [
// ...
],
};
function orderStudentGrade(students) {
// TODO: 在这里写入具体的实现逻辑
// 将学生的成绩按班级分组,同一班级中按照总分从高到底排序
let stuObj = new Map()
students.forEach(element => {
if(!stuObj.has(element.class)) {
stuObj.set(element.class, [])
}
stuObj.get(element.class).push(element)
stuObj.get(element.class).sort((a, b)=> {
const totala = a.math + a.language + a.english +
a.physics + a.chemistry
const totalb = b.math + b.language + b.english +
b.physics + b.chemistry
return totalb - totala
})
});
console.log(stuObj);
// 把键值对列表转换为一个对象
return Object.fromEntries(stuObj)
}
33.调皮的模态框
jquery控制元素隐藏消失
<div class="modal-box">
<div class="btn btn-primary sign-btn btn-lg show-modal " onclick="handleClick()">
立即报名
<div class="modal" id="myModal" tabindex="-1">
<div class="modal-dialog" role="document">
<div class="modal-content">
<button type="button" class="close" onclick="handleOk()"><span aria hidden="true">×</span>
</button>
<h3 class="icon">!</h3>
<h3 class="title">很遗憾</h3>
<p class="description">蓝桥杯第 X 届 算法大赛报名已经结束!</p>
<button class="subscribe" onclick="handleOk()">OK</button>
</div>
</div>
</div>
</div>
</div>
</div>
// 请在这里补充代码,根据需求解决事件冒泡带来的问题,实现模态框的显隐操作。
function handleClick(){
$('#myModal').show()
}
function handleOk(){
$('#myModal').hide()
//该事件不会触发执行当前元素的任何祖辈元素的任何事件处理函数
event.stopPropagation();
}
34.课程列表
- 完成数据请求(数据来源
js/carlist.json
)。在项目目录下已经提供了axios
,考生可自行选择是否使用。- 完成数据分页显示,每页 5 条数据,默认当前页码为第一页(即
pageNum = 1
),按照顺序第一页显示 1-5 条,第二页显示 6-10 条,依此类推。将每条数据显示到list-group
元素中。使用已有代码中list-group
,不要修改list-group
元素的 DOM 结构。动态渲染时,list-group
示例代码可删除。- 当页码为第一页时,上一页为禁用状态(
class=disabled
),点击无任何变化。- 当页码为最后一页时,下一页为禁用状态(
class=disabled
),点击无任何变化。- 在
id
为pagination
元素中正确显示当前页码和总页码(即最大页码)。当前页码变量使用pageNum
,总页码变量使用maxPage
。请勿修改当前页码和总页码的变量名称,以免造成判题无法通过。
let pageNum = 1; // 当前页码,默认页码1
let maxPage; // 最大页数
// TODO:待补充代码
let carlist //课程列表数据
axios('js/carlist.json').then(res=>{
carlist = res.data
//向上取整,给出大于或等于参数的整数
maxPage = Math.ceil(carlist.length / 5)
renderList()
})
//列表
let list = document.querySelector('#list')
//上下页
let pagination = document.querySelector('#pagination')
// 渲染列表
function renderList() {
//调用一遍按钮样式
disabledBtn()
pagination.innerHTML=`共${maxPage}页,当前${pageNum}页`
list.innerHTML = carlist.slice((pageNum - 1) * 5, pageNum * 5).map(item => `
<div class="list-group">
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">${item.name}</h5>
<small>${(item.price / 100).toFixed(2)}元</small>
</div>
<p class="mb-1">${item.description}</p>
</a>
</div>
`).join('')
}
// 渲染按钮样式
function disabledBtn() {
//先清除禁止样式,再根据条件显示
prev.classList.remove('disabled')
next.classList.remove('disabled')
if (pageNum == 1) prev.classList.add('disabled')
if (pageNum == maxPage) next.classList.add('disabled')
}
// 点击上一页
let prev = document.getElementById("prev");
prev.onclick = function () {
// TODO:待补充代码
if (pageNum === 1) return;
pageNum--
renderList()
};
// 点击下一页
let next = document.getElementById("next");
next.onclick = function () {
// TODO:待补充代码
if (pageNum === maxPage) return;
pageNum++
renderList()
};
35.虚拟滚动列表
虚拟列表的实现,实际上就是在首屏加载的时候,只加载可视区域内需要的列表项,当滚动发生时,通过动态计算获得可视区域内的列表项,并将非可视区域内已存在的列表项删除:
- 计算当前可视区域起始数据索引(
startIndex
)。- 计算当前可视区域结束数据索引(
endIndex
)。- 计算当前可视区域的数据,并渲染到页面中。
- 计算(
startIndex
)对应的数据在整个列表中的偏移位置(startOffset
)并设置到列表上。
<!-- TODO:补全 scroll 事件及其相关属性 -->
<template>
<div id="virtual-list" class="virtual-list" @scroll="handel($event)">
<div id="scroll-container" :style="{ height: totalHeight + 'px' }"></div>
<ul
id="list"
class="list"
:style="{ transform: `translateY(${start * itemHeight}px)` }"
>
<li
v-for="item in showingList"
:key="item"
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }"
>
{{ item }}
</li>
</ul>
</div>
</template>
<script>
module.exports = {
data() {
return {
itemHeight: 60, // 每个列表项的高度,请勿更改
length: 10, // 列表项可视范围内的个数,请勿更改
buffer: 5, // 列表项可视范围外,防止出现白屏的 buffer 个数,上方 5 个,下方 5 个,可作为优化项实现
list: [],
totalHeight: 0,
scrollTop: 0,
start: 0,
};
},
computed: {
// 根据start 从数数据中将需要显示的数据切出来
showingList() {
return this.list.slice(
this.start,
this.start + this.length + this.buffer
);
},
},
methods: {
// TODO: 完成事件处理
handel(e) {
// console.log(e.target);
let scrollTop = e.target.scrollTop;
// 根据总scrollTop的高度和每一个item的高度计算出当前显示范围的数据的开始下标
this.start = Math.floor(scrollTop / this.itemHeight);
},
},
mounted() {
// TODO: 完成数据请求
axios.get("./data.json").then(
(res) => {
// 获取接口数据
this.list = res.data;
// 设置虚拟列表盒子的总长度 如果不设置高度,显示空间是挤出来的
this.totalHeight = this.itemHeight * this.list.length;
},
(err) => console.log(err)
);
},
};
</script>
36.新鲜的蔬菜
<body>
<div class="container">
<div class="box" id="box1">
<span class="item">
<img src="./images/cabbage.svg" alt="" />
</span>
</div>
<div class="box" id="box2">
<span class="item">
<img src="./images/chili.svg" alt="" />
</span>
<span class="item">
<img src="./images/chili.svg" alt="" />
</span>
</div>
<div class="box" id="box3">
<span class="item">
<img src="./images/carrot.svg" alt="" />
</span>
<span class="item">
<img src="./images/carrot.svg" alt="" />
</span>
<span class="item">
<img src="./images/carrot.svg" alt="" />
</span>
</div>
</div>
</body>
/* TODO:待补充代码 */
.box{
display: flex;
}
#box1{
justify-content:center;
align-items: center;
}
#box2{
flex-direction: column;
justify-content: space-between;
}
#box2 .item:nth-child(2){
align-self: flex-end;
}
#box3 {
justify-content: space-between;
}
#box3 .item:nth-child(2) {
align-self: center;
}
#box3 .item:nth-child(3) {
align-self: end;
}
37.一加一等于几
- 如果输入的两个参数都能够被转化为数字类型(
NaN
除外),则进行数学的加法运算。- 如果输入的参数中有一个不满足上个条件,则进行字符串的拼接运算(
NaN
虽然也是数字类型,但是由于无法进行加法运算,所以还是进行拼接运算)。
function add(x, y) {
if(parseInt(x) && parseInt(y)){
return parseInt(x) + parseInt(y)
}else{
return x + y
}
}
38.你能看出多少位吗
1.我们先要拿到输入的内容,这是一次连续点击,得到的是字符串
let num = ''//输入的结果
$('.form-edit .num').click(function () {
var oDiv = document.getElementById("input-box");//输入框内容
num += this.innerHTML;
oDiv.innerHTML = getThousandNum(num) //输入框内容赋值为num的处理结果
})
2.实现数据处理函数
function getThousandNum(num) {
var result =''
var count = 0
//num是string类型,就是每次点击数字后所组成的数字字符串
for(var i = num.length -1;i >= 0;i--){
//从最后一位开始遍历,每次遍历到的放在result的前面
result = num.charAt(i) + result
//charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法
count++
//遍历一次,count++,当遍历到了3的倍数,如第3次,第六次之后要先追加','
if( (count % 3) == 0 && i != 0){
//i != 0 的判断目的是如果遍历到了第一位,不需要在第一位前面追加
result = ',' + result
}
}
return result
}
39.水果消消乐
- 点击开始按钮后,该按钮被隐藏,方格上的图片显示后又隐藏。
- 点击方格,方格中的图片显示,页面显示两张图片后,比较图片是否相同。
- 如果图片上的水果相同,方格即可消除,并得 2 分;如果图片上的水果不相同,图片隐藏,并扣 2 分(分数可以为负数)。
- 在文本 “当前分数为:” 的冒号后面会实时统计当前的得分情况。
最终效果:
做之前,我们要想想为什么图片一开始没有显示,检查题目是否在css中设置了隐藏,还是js,最后发现是css:display:none
1.实现图片渐入渐出效果
function startGame() {
//开始按钮隐藏
$('#start').hide()
$('img').show(500).hide(500)
}
2.确定思路,两两一组进行对比,每次点击保存这个点击的元素用来后续隐藏,保存点击的名字,用来比较两次点击是否是一样的水果,动态更新isFirst的布尔值,它标志是否为第一次点击
// TODO:请补充代码
function startGame() {
var isFirst = true //是否第一次点击
var score = 0 //分数
var first,second
var firstName = ''
var secondName = ''
//点击开始按钮,隐藏,图片显示
$('#start').hide()
$('img').show(500).hide(500)
$('.img-box').click(function(){
if(isFirst){ //第一次点击
this.children[0].style.display = 'inline-block'//显示
//存数据
firstName = this.children[0].alt
first = this
//更新状态
isFirst = false
}else{ //再次点击
this.children[0].style.display = 'inline-block'//显示
//存数据
secondName = this.children[0].alt
second = this
//比较两次点击的名字是否一样
if(firstName == secondName){
//一样,将存的元素隐藏
setTimeout(() => {
first.style.visibility = 'hidden'
second.style.visibility = 'hidden'
}, 500);
//更新分数
score += 2
$('#score')[0].innerHTML = `${score}`
//更新状态
isFirst = true
}else{
//不一样,将图片隐藏
setTimeout(() => {
first.children[0].style.display ='none'
second.children[0].style.display ='none'
}, 1000);
score -=2
$('#score')[0].innerHTML = `${score}`
//更新状态
isFirst = true
}
}
})
}
40.验证密码强度
// 请在这里补充代码,实现密码强度的验证
$('.btn-validate').click(function(){
//1.拿到输入的密码
let password = $('#passwordField').val()
//2.设置校验规则
//至少需要一个小写字母
let xiaoxie = /[a-z]/g
//至少需要一个数字
let num = /[0-9]/g
//至少需要一个大写字母
let daxie = /[A-Z]/g
//至少需要一个(除数字和字母外的)特殊字符
let specil = /\W/g
//密码必须大于8
if(password.length > 8){
$('.result').text('低')
//至少需要一个小写字母,至少需要一个数字
if(xiaoxie.test(password) && num.test(password)){
$('.result').text('中')
}
//至少需要一个大写字母,至少需要一个(除数字和字母外的)特殊字符
if(daxie.test(password) && specil.test(password)){
$('.result').text('高')
}
}else{
$('.result').text('无效')
}
})
41.页面发生变化了
1.先将目标红色块添加到监听里面
//添加动画效果的红色目标块
const target = document.querySelector(".animated");
//初始化一个 IntersectionObserver 用于检测目标色块和视图在滚动页面时的交叉关系
var observer = new IntersectionObserver((entries,observer)=>{
//entries-目标监测对象
entries.forEach(item=>{
if(item.isIntersecting){
console.log("看见了");
}
})
})
//将目标块添加到监测对象中
observer.observe(target);
//初始化一个 IntersectionObserver 用于检测目标色块和视图在滚动页面时的交叉关系
var observer = new IntersectionObserver((entries,observer)=>{
//entries-目标监测对象
entries.forEach(item=>{
//当目标块到了可视区域
if(item.isIntersecting){
//添加动画效果
target.classList.add("visible")
}
if(!item.isIntersecting){
//css中有此类控制显示隐藏
target.classList.remove("visible")
}
})
})
42.寻找小狼人
结果展示:
点击寻找狼人之后
下面是相关代码部分
let cardList = [
{
id: 1,
category: "werewolf",
name: "小狼人",
},
{
id: 2,
category: "werewolf",
name: "小狼人",
},
.....
{
id: 8,
category: "werewolf",
name: "黑狼王",
},
{
id: 9,
category: "poor",
name: "平民",
},
];
let newcardList = cardList.myarray(
(item) => item.category == "werewolf"
);
// 返回条件为真的新数组
Array.prototype.myarray = function (cb) {
};
看这些代码逻辑我们知道,myarray函数中传入了一个函数参数: (item) => item.category == "werewolf",这个是回调
我们怎们利用这个参数,进行筛选这个cardList数组,返回一个新的数组只包含狼人列表,并且看这个参数可知他就是用来筛选狼人列表的,并且方法的使用对象是cardList,也就是this
Array.prototype.myarray = function (cb) {
// TODO:待补充代码
let arr = [] //狼人数组
this.forEach(item =>{
//cb是一个回调,传入的参数是列表某项
if(cb(item)) arr.push(item)
})
return arr
};
43.传送门
$(window).scroll(function () {
if($(window).scrollTop()<960){
//排他思想
$('.default-color').removeClass('active-color').eq(0).addClass('active-color')
}else if($(window).scrollTop()<1920){
$('.default-color').removeClass('active-color').eq(1).addClass('active-color')
}else{
$('.default-color').removeClass('active-color').eq(2).addClass('active-color')
}
});
/**
* @param {Object} scrollTopVal:到达指定位置需要滚动的高度
* 点击按钮,滚动到指定位置
*/
function toFunction(scrollTopVal) {
// TODO:请补充代码实现功能
//要善于观察题目已给代码中的方法-参照上面的滚动函数
$(window).scrollTop(scrollTopVal)
}
44.拖拽小应用
介绍
HTML 5 为我们提供了拖放 API,这个 API 可以让页面上几乎任何元素都具备可拖拽的功能,只需要为该 HTML 元素添加上
draggable=true
的标记,并进行适当编码即可。这一功能也为前端开发提供了更多有趣的交互效果和无限可能。
目标
- 为了实现绿色方块的拖放效果,需要在
index.html
文件中为该元素添加属性,使其具备可拖拽性。- 然后再根据
index.js
文件中的提示和要求添加所需的 JavaScript 代码,功能实现之后效果如下:
根据提示,我们给选择的可拖拽元素添加属性
<!-- 为下方 div 添加属性,让其具备可拖拽的功能 -->
<!-- 设置可拖拽 -->
<div class="item" id="item" draggable=true></div>
45.猜硬币
- 页面加载后,系统会在 9 个杯子中随机挑选 3 个杯子生成硬币。
- 用户在文本框中输入任意字符串,点击确定按钮后,系统会找到字符串中含有
1-9
的数字,并根据数字打开对应的杯子。
// 将输入的值中 1-9 组成一个数组
function findNum(input_values) {
// TODO:待补充代码
let result = input_values.match(/[1-9]/g);
//因为得到的是输入的字符串数组,所以要进行转化成数字
result = [...new Set(result)].map(item => parseInt(item));
//这个字符串是猜测的硬币位置
return result;
}
// 将 1-9 中三个不重复的随机数放入数组中,并返回这个数组
let randomCoin = () => {
//这个方法是随机选择三个位置放硬币
let randomNumArr = [];
// TODO:待补充代码
while(randomNumArr.length < 3) {//生成3个
let num = parseInt(Math.random() * 9 + 1);
//生成不一样的
if (!randomNumArr.includes(num)) randomNumArr.push(num);
}
return randomNumArr;
};
46.URL 参数解析并高亮文本内容
挑战需求
- 当点击搜索按钮时,请为页面内容中与搜索框中
wd=
后对应的值相同的字符串添加<em>
标签,达到高亮的效果。- 当搜索框中参数
wd
的值为空的时候,点击搜索按钮,需要清除已有的高亮。- 只能通过 JS 的方式处理,其他方式无效。
<body>
<div class="search">
<div class="input-box">
<input type="text" width="546px" name="search-input" height="45px" value="https://lanqiao.cn/s?wd=蓝桥云课&d=20220712&from=wx" />
</div>
<div class="search-box">
<input type="button" width="110px" height="45px" value="搜索" />
</div>
</div>
<main class="main-container">
<div class="item">
<a href="#"><h3 class="c-title">蓝桥云课楼+课程_实验楼</h3></a>
<div>
<div class="c-gap-top-small">
<span class="content-right">蓝桥云课是国内领先的IT在线编程及在线实训学习平台,专业导师提供精选的实践项目,创新的技术使得学习者无需配置繁琐的本地环境,随时在线流畅使用。实验楼,以就业为导向,提供编程</span>
<div class="c-row">
<span class="c-color-gray" aria-hidden="true">www.shiyanlou.com/louplus/</span>
</div>
</div>
</div>
</div>
......
</main>
</body>
// 请你在 script 标签中编写代码,实现根据 URL 中的关键字为内容中包含关键字的文本添加 em 标签,以表示高亮。
//搜索按钮
var search = document.querySelector('.search-box')
//文本内容
var html = document.querySelector('.main-container').innerHTML
search.addEventListener('click',function(){
let url = document.querySelector('.input-box').children[0].value
//请求地址获取对应参数
let wd =(new URL(url)).searchParams.get('wd')
box.innerHTML = !wd ? html : html.replaceAll(`${wd}`, '<em>$&</em>')
})
47.小兔子找胡萝卜
具体说明如下:
- 点击开始游戏的按钮后,移动按钮显示,开始游戏按钮隐藏,在右侧输入框中输入步数后,点击移动按钮,小兔子可以在草坪上向前移动。
- 输入框中只能输入 1 或者 2,输入其他数字,点击移动按钮后,小兔子不会移动,并且在按钮下方(**.result** 元素中)会显示一句话:“输入的步数不正确,请重新输入。”。
- 点击移动按钮后,输入框中的值不会被清空。
- 如果小兔子踩到第 13 块草坪上的炸弹,移动按钮隐藏,重置按钮显示,并且在重置按钮的下方(**.result** 元素中)会显示一句话:“哎呀!兔子踩到炸弹了,游戏结束!”。
- 如果小兔子踩到第 24 块草坪上的胡萝卜,移动按钮隐藏,重置按钮显示,并且在重置按钮的下方(**.result** 元素中)会显示一句话:“小兔子吃到胡萝卜啦,游戏获胜!”。
- 点击重置按钮小兔子回到游戏的初始化状态,并且输入框中的值和按钮下方的提示文字都会被清空。
// TODO:游戏开始
function start() {
//移动按钮显示,开始游戏按钮隐藏
$('#start').hide()
$('#move').show()
}
// TODO:重置游戏
function reset() {
time = 0
$('.lawn').eq(time).addClass('active').siblings().removeClass('active')
$('.result').text('')
$('input')[0].value = ''
$('#start').show()
$('#reset').hide()
}
var time = 0 //移动的方格数
// TODO:移动 active在哪里,兔子就在哪里
function move() {
//选择的步数--这里拿到的值是字符串,要隐式转换
let step = +$('input').val()
//所有方格
let fangge = $('.lawn')
time += step //从点击开始增加
if(step == 1 || step == 2){
fangge.eq(time).addClass('active').siblings().removeClass('active')
if (time == 12) {
$('#move').hide()
$('#reset').show()
$('.result').text('哎呀!兔子踩到炸弹了,游戏结束!')
}else if(time == 23){
$('#move').hide()
$('#reset').show()
$('.result').text('小兔子吃到胡萝卜啦,游戏获胜!')
}
}else{
$('.result').text('输入的步数不正确,请重新输入。')
}
}
48.分一分
const splitArray = (oldArr, num) => {
// TODO:请补充代码实现功能
let newArr = [];
oldArr = oldArr.sort((a, b) => {
return a - b;
});
for (let i = 0; i < oldArr.length; i += num) {
newArr.push(oldArr.slice(i, i + num));
}
return newArr
};
49.权限管理
这是网页的初始状态,当我们点击这些按钮时,将会改变选中用户的权限,对应下面的表格就会改变
$(function () {
// 使用 ajax 获取 userList.json 数据并渲染到页面
getData();
// 为按钮添加事件
$("#add").click(function () {
// TODO:补充代码,实现功能
});
$("#addAll").click(function () {
// TODO:补充代码,实现功能
});
$("#remove").click(function () {
// TODO:补充代码,实现功能
});
$("#removeAll").click(function () {
// TODO:补充代码,实现功能
});
});
/**
* 修改权限
* @param {Object} right 要修改的权限
* @param {Object} changeList 要修改权限的用户列表
*/
function changeAccess(right, changeList) {
// TODO:补充代码,实现功能
}
// 异步获取数据
function getData() {
// TODO:补充代码,实现功能
}
数据格式
1.我们先请求数据,完成初始渲染
// 异步获取数据
function getData() {
// TODO:补充代码,实现功能
$.get('./js/userList.json',data=>{
data.forEach( user => {
//遍历每一项,追加到列表框,初始时,每项都是普通用户
$('.user-list').append("<tr><td>" + user.name + "</td><td>" + (user.right ? '管理员' : '普通用户') + "</td></tr>")
});
})
}
2.完整编码
$(function () {
// 使用 ajax 获取 userList.json 数据并渲染到页面
getData();
// 为按钮添加事件
$("#add").click(function () {
// TODO:补充代码,实现功能
// 获取选中的option
let option = $("#leftSelect option:selected");
// jQ方法:each() 遍历jQ获取的节点
option.each((index, item) => {
// 删除左侧对应的option
$(`#leftSelect option[value=${item.value}]`).remove();
// 向右侧添加option
$("#rightSelect")[0].add(new Option(item.value, item.value));
});
changeAccess("管理员", option);
});
$("#addAll").click(function () {
// TODO:补充代码,实现功能
let option = $("#leftSelect option");
option.each((index, item) => {
$(`#leftSelect option[value=${item.value}]`).remove();
$("#rightSelect")[0].add(new Option(item.value, item.value));
});
changeAccess("管理员", option);
});
$("#remove").click(function () {
// TODO:补充代码,实现功能
let option = $("#rightSelect option:selected");
option.each((index, item) => {
$(`#rightSelect option[value=${item.value}]`).remove();
$("#leftSelect")[0].add(new Option(item.value, item.value));
});
changeAccess("普通用户", option);
});
$("#removeAll").click(function () {
// TODO:补充代码,实现功能
let option = $("#rightSelect option");
option.each((index, item) => {
$(`#rightSelect option[value=${item.value}]`).remove();
$("#leftSelect")[0].add(new Option(item.value, item.value));
});
changeAccess("普通用户", option);
});
});
/**
* 修改权限
* @param {Object} right 要修改的权限
* @param {Object} changeList 要修改权限的用户列表
*/
function changeAccess(right, changeList) {
// TODO:补充代码,实现功能
changeList.each((index, item) => {
// 将option.value与tr.name对应,找到对应的td并修改其内容
// jQ方法::last 获取最后个元素
$(`#userList tr[name=${item.value}] td:last`).html(right);
});
}
// 异步获取数据
function getData() {
// TODO:补充代码,实现功能
$.ajax("./js/userList.json").then((res) => {
res.forEach((item) => {
// jQ方法:html() 设置html内容
$("#userList tbody").html(
$("#userList tbody").html() +
` <tr name=${item.name}>
<td>${item.name}</td>
<td>${item.right ? "管理员" : "普通用户"}</td>
</tr>`
);
});
});
}
一些方法
过滤
const goods = this.goods.filter((element) => {
return goodsName === element.name;
});
数组累加
totalPrice() {
return this.bought.reduce((pre, item, index) => {
pre += parseInt(item.price);
return pre;
}, 0);
},
jquery
元素显示与隐藏
$('.card-body-option-favorite img').each(function(i,item){
$(item).click(function(){
//1.设置点击的图片地址
this.src = './images/solid.svg'
//2.显示元素
$('#toast__container').show()
$('.toast__close').click(function(){
//3.隐藏元素
$('#toast__container').hide()
})
})
分页器
//将请求的数据进行分割显示
data = res.data.splice((currentPage-1)*pageSize,pageSize)
网格布局
js控制文本溢出
// 一个块元素显示的文本的行数
p.style["-webkit-line-clamp"] = 2
p.style.overflow = "hidden"
css文本溢出省略号
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
本地存储
//请求的数据存到本地
localStorage.setItem("historyData",JSON.stringify(data))
//拿到请求的数据
const data =JSON.parse(localStorage.getItem("historyData"))
将数字变成千分位格式
let num=12345678;
console.log(num.toLocaleString()); // 12,345,678
js控制模糊清晰
let img1 = document.querySelector('.img1')
img1.style.filter = 'blur(0px)'
let img2 = document.querySelector('.img2')
img2.style.filter = 'blur(0px)'
时间戳与时间转换
时间戳转换成date时间与格式时间转换
Mon Jan 26 1970 03:25:43 GMT+0800 (中国标准时间) -> 2022-04-10 15:37:17
使用Number()将时间戳字符串转换成数字,之后使用 new Date()
时间转换成时间戳
使用getTime()函数即可
时间转换
20220501 -> 2022-05-01
let date ="20220501"
date = `${date.slice(0,4)}-${date.slice(4,6)}-${date.slice(6,8)}`
表示大于并小于
错误:4<x<6
正确:x>4 && x< 6
箭头函数加不加{}
如果加了{},需要加return
<script>
let arr = ["你是一个好人", "哈哈哈", "你说什么?"]
let newArr = arr.filter(item =>
item.search('') !== -1
)
let newArr1 = arr.filter(item =>
{ item.search('') !== -1}
)
console.log(newArr);
// ["你是一个好人", "哈哈哈", "你说什么?"]
console.log(newArr);
//[]
</script>
jquery中同级元素点击事件
$(function(){
$('.option').click(function(){
$(this).addClass('active').siblings().removeClass('active')
})
})