题目链接:
1.日历格绘
思路:
**本题主要考察CSS中的grid布局,题目中有提示
**总结:水题
题解:
/* TODO_1: 请补充代码 */
display: grid;
grid-template-columns: repeat(7, 1fr);
/* TODO_1: END */
/* TODO_2: 请补充代码 */
#days p:first-of-type{
grid-column: 3;
}
/* TODO_2: END */
2.记词小能手
思路:
**待复习函数没什么好说的,就是循环展示,如果展示到了最后一个的话需要回到第一个
****完成复习函数, 首先使用删除函数splice删除当前展示的单词,然后展示
****但是需要注意的是,当删除到最后一个的时候当前index会大于words的长度,所以需要回到第一个,而正常删除时则会正常往下推一个,不用++,
****然后再是展示的问题,如果已经全部复习完,也就是words的长度是0,就展示题目给出的p标签,否则展示下一个单词
**总结:思维题,js的splice函数使用
题解:
/**
* @description 待完成单词复习,跳到下一个单词
*/
function waitReview() {
// TODO: 请补充代码
if (index >= words.length)
index = 1;
else
index ++;
renderData(index);
}
/**
* @description 完成单词复习,删除当前单词,跳到下一个单词
*/
function completeReview() {
// TODO: 请补充代码
words.splice(index-1, 1);
if (index >= words.length)
index = 1;
if (words.length == 0)
document.querySelector('#word').innerHTML = '<p class="success">今日复习已完成</p>'
else{
renderData(index);
}
// TODO: END
waitTaskBox.innerText = `还需复习:${words.length}`;
}
3.小蓝餐厅
思路:
怎么说呢,写题目不能想当然,题目中提供了方法的话就用它给的,最好不要用自己的方法,如果题目中没提供的话就用自己的方法
****首先是比较简单的axios网络请求,没啥好说的,再者就是需要设置拦截器,axios官网上的拦截器的写法不适合这个题目(链接在最后),需要使用题目中提供的方法(http://www.axios-js.com/zh-cn/docs/#%E6%8B%A6%E6%88%AA%E5%99%A8**)
****首先是config参数中的对象以及对象里函数的判断,因为题目中说这些都不是必须的,所以说在使用前要先判断,再是拦截器的使用,题目中已经提供了use的使用方法,但是拦截其中的use是有两个函数的如:
****use(成功函数,失败函数)
****然后题目中也展示了成功函数的使用,在模仿写出失败函数就行了,拦截器的写法在题目最后也提供了
**总结:审题,注意题目要求的写法,axios的基本使用
题解:
function useAxios(url, config) {
const { ref } = Vue;
// 网络请求返回的数据
const data = ref(null);
// 本次网络请求是否出错
const error = ref(null);
// TODO:待补充代码
const instance = axios.create();
if (config){
if (config.interceptors && config.interceptors.request){
instance.interceptors.request.use(
config.interceptors.request.bind(undefined ,false),
config.interceptors.request.bind(undefined, true));// 请求拦截器
}
if (config.interceptors && config.interceptors.response){
instance.interceptors.response.use(
config.interceptors.response.bind(undefined, false),
config.interceptors.response.bind(undefined, true)); //响应拦截器
}
}
instance.get(url).then(res => {
data.value = res.data;
error.value = null;
}).catch(err => {
data.value = null;
error.value = err;
})
return {
data,
error
}
};
4.世纪危机(人口增长推算)
思路:
**感觉像是在做阅读理解
****主要是Echarts图表内容的考查,API的使用,不过题目有问题,题目中说的是”万“,但是实际上是”百万“,还有就是JS中Math的使用,如果用普通数学方法做也是不能通过的
**总结:Echarts和JS函数
题解:
// 初始化 ECharts 实例
const chart = echarts.init(document.getElementById('main'));
/**人口数据增长推算函数
* @param {number} initialPopulation 基础人口数,假设有 10 亿
* @param {number} growthRate 年增长率,假设为 3%
* @param {number} startYear 起始年份,假设为 200000
*/
function calculatePopulation(initialPopulation, growthRate, startYear){
const years = [];
const population = [];
// TODO:待补充代码 目标 1
for(let i = 0; i <= 30; i++){
years.push(startYear + i);
population.push(initialPopulation*Math.pow(1+growthRate,i));
}
return {years,population};
}
const pData = calculatePopulation(1000000000, 0.03, 200000);
// 配置 ECharts 选项
const option = {
title: {
text: '未来30年人口增长趋势图',
subtext: '假设年增长率为3%',
left: 'center'
},
tooltip: {
trigger: 'axis',
// TODO:待补充代码 目标 3
formatter: (params) => {
let res = ''
res += `<p>${params[0].name}<br/>人口:${Math.round(params[0].value / 1000000)}M</p>`
// console.log(params.length,res);
return res;
}
},
xAxis: {
type: 'category',
// TODO:待修改代码 目标 2
// 年份
data: pData.years,
name: '年份',
boundaryGap: false
},
yAxis: {
type: 'value',
name: '人口数',
axisLabel: {
// TODO:待补充代码 目标 4
formatter: (value, index) => {
return Math.round(value/1000000) + 'M';
}
}
},
series: [
{
name: '人口',
type: 'line',
// TODO:待修改代码 目标 2
// 人口数量
data: pData.population,
smooth: true,
lineStyle: {
color: '#3398DB'
},
itemStyle: {
color: '#3398DB'
}
}
]
};
// 使用刚指定的配置项和数据显示图表
chart.setOption(option);
5.回忆画廊
思路:
**主要是vue3的v-for指令的使用,JS中Date()函数的使用,还有vue3与element-plus插槽的使用,这个不会的话没办法
**总结:vue3基础+element-plus插槽
题解:
const List = {
template: `
<div class="photo-list">
<el-row :gutter="20">
<!--TODO:待修改代码 每一个 el-col 存放一个单张照片 -->
<el-col :span="6" v-for='item in photos' :key='item'>
<el-card>
<!-- TODO:待修改代码 目标 1 -->
<el-image
style="width: 100%; height: 200px"
:src="item.url"
>
<!-- TODO:待补充代码 目标 2 -->
<template #error>
<photo-error/>
<template>
</el-image>
<div style="padding: 14px;">
<!--TODO:待修改代码 目标 1 -->
<span class="title">{{item.title}}</span>
<div class="bottom clearfix">
<!--TODO:待修改代码 目标 1 -->
<time class="time">{{getDate(item.date)}}</time>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
`,
props:['photos'],
setup(props) {
let photos = props.photos
const getDate = (date) => {
const nowDate = new Date(date);
const year = nowDate.getFullYear();
let month = nowDate.getMonth()+1;
let day = nowDate.getDate();
if (month < 10)
month = '0' + month;
if (day < 10)
day = '0' + day;
return `${year}-${month}-${day}`;
}
return {
photos,
getDate
};
},
};
6.文件切片上传
思路:
**node.js的考点,一点不会
****这题解抄的同学的
**总结:node.js
题解
/**
* @description: 将图片文件切片列表通过文件流的方式合并成一个文件,文件合并完成后删除所有的切片。
* @param {*} imgNameList 图片文件列表
* @param {*} writeStream 写入流
* @param {*} deleFileList 需要删除的图片文件列表
* @return {*}
*/
function streamMergeRecursive(imgNameList, writeStream, deleFileList = []) {
// TODO:待补充代码
if (imgNameList.length === 0) {
writeStream.end();
deleFile(deleFileList);
return;
}
// 获取并移除图片文件列表中的第一个文件名
const imgName = imgNameList.shift();
// 创建读取流
const readStream = fs.createReadStream(path.resolve(baseDir, imgName));
// 将读取流的数据写入写入流,但不结束写入流
readStream.pipe(writeStream, { end: false });
// 当读取流结束时,将当前文件名添加到删除列表,并递归处理下一个文件
readStream.on('end', () => {
deleFileList.push(imgName);
streamMergeRecursive(imgNameList, writeStream, deleFileList);
});
}
7.员工管理
思路:
这个题的目标一考察vue的基本语法的
[**emit**](https://cn.vuejs.org/guide/components/events.html)**的使用,还有JS的函数使用,看知识点会不会不会就完蛋
**总结:vue + JS
题解:
const handleSubmit = () => {
// TODO 目标1 待补充代码
emit('submit-add')
};
const handleCancel = () => {
// TODO 目标1 待补充代码
emit('close-add')
};
// TODO:待补代码目标 2
worker.value[editIndex.value].name = form.name;
worker.value[editIndex.value].phone = form.phone
/**
* 批量删除
*/
const deleteItems = () => {
// TODO:待补充代码 目标 3
worker.value = worker.value.filter(item => {
if (item.checked === false)
return item
})
}
/**
* 删除单个员工
* @param item 员工信息
*/
const deleteItem = item => {
// TODO:待补充代码 目标 3
worker.value.splice(worker.value.indexOf(item),1);
}
8. 收藏书签栏
思路:
这个题目算是比较复杂的题目了,要转化数据对象的结构,然后还要改变数组对象内部的值->这个地方用到了引用赋值,这个算一个浅拷贝的特例,然后再是对象结构转化的地方用到了map()**函数
**总结:JS函数+数据拷贝
题解:
const addBookmark = () => {
const newBookmark = {
name: bookmarkTitle.value,
url: bookmarkUrl.value,
};
// TODO: 实现添加书签功能
const pathList = selectedFolderPath.value.split('/');
let nowNode = bookmarks.value;
pathList.forEach(e => {
let node = nowNode.find(item => e == item.tag);
if (node){
nowNode = node.children;
}
});
nowNode.push(newBookmark);
closeDialog();
treeData.value = convertBookmarksToTreeData(bookmarks.value);
};
const convertBookmarksToTreeData = (bookmarks) => {
// TODO: 实现书签数组转换为树形数据结构的逻辑
return bookmarks.map(i => {
return {
'label': i.tag||i.name,
'children': i.children?convertBookmarksToTreeData(i.children):[],
'url': i.url,
}
})
};
const handleNodeDrop = (draggingNode, dropNode, dropType) => {
console.log(draggingNode.data);
// TODO: 实现拖放功能
function convertTreeDataToBookmarks(treeData) {
return treeData.map((node) => {
if (node.url) {
return {
name: node.label,
url: node.url,
}
}
return {
tag: node.label,
children: convertTreeDataToBookmarks(node.children || []),
}
})
};
bookmarks.value = convertTreeDataToBookmarks(treeData.value);
};
9.订单状态更新
思路:
思维题,题目要求返回Promise对象先判断传入的数组是不是空的,然后返回空数组,如果不是空的,则需要将数组内的
**Promise**对象解构,否则不变,如果**Promise**对象有**reject**的直接返回**reject **我一直在用算法的思维写,然后查资料发现**forEach****是同步执行,一直不显示结果
**总结:Promise对象和JS
题解:
/**
* @param {Array} promises 传入的数组,可以包含 Promise 对象或普通值
* @return {Promise} 返回一个 Promise,解析为结果数组
*/
function myPromiseAll(promises) {
// TODO:待补充代码
return new Promise((resolve,reject) => {
if (promises.length == 0)
resolve([]);
else{
let res = [],cnt = 0;
promises.forEach((item,index) => {
if(Object.prototype.toString.call(item) != '[object Promise]'){
res[index] = item;
cnt ++;
if (cnt == promises.length)
return resolve(res);
}
else{
item.then(p => {
res[index] = p;
cnt ++;
if (cnt == promises.length)
return resolve(res);
}).catch(err => {
return reject(err);
})
}
})
}
})
}
10.需求管理
思路:
**有bug,目标四只需要取消单选框然后相应的数据消失,选择单选框后数据不回显也可以通过
****这个题
****这个题考的挺综合,反正我不会,看官方题解的,学到了挺多
****首先是子父组件之间的传值、监听事件(props,emits),计算属性computed,监听器watch,响应式数据,JS函数的使用
**总结:vue的综合使用
题解:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="./lib/vue.global.js"></script>
<link rel="stylesheet" href="./css/style.css" />
<title>需求管理</title>
</head>
<body>
<div id="app" v-cloak>
<header>
<stats
:items-data="itemsList"
></stats>
<filter-group
@update="updateGroup"
></filter-group>
</header>
<!-- TODO:待修改代码 目标 1 -->
<demand-list
:items-data="itemsList"
@update-child="updateChild"
@update-parent="updateParent"
@toggle-item="toggleItem"
></demand-list>
</div>
<script src="./components/DemandList.js"></script>
<script src="./components/FilterGroup.js"></script>
<script src="./components/Stats.js"></script>
<script>
const { createApp, ref, computed, onMounted, watch } = Vue;
let app = createApp({
setup() {
const MockUrl = `./mock/data.json`
const items = ref([]);
onMounted(async () => {
// TODO:待修改代码目标 1
let res = await fetch(MockUrl)
items.value = await res.json()
console.log(items.value)
});
// TODO:待补充代码 目标 4
const obj1 = ref({
demand: true,
bug: true,
task: true
})
const itemsList = computed(() => {
return items.value.filter(i => obj1.value[i.type]);
})
const updateGroup = (obj) => {
obj1.value = obj
console.log(obj1.value)
}
// TODO:END
const toggleItem = (item) => {
item.expanded = !item.expanded;
};
// 目标 2 点击完成的逻辑
// 点击子项目
const updateChild = (parent) => {
// TODO:待补充代码 目标 2
parent.completed = !parent.children.find(i => !i.completed)
};
// 点击父项目
const updateParent = (item) => {
// TODO:待补充代码 目标 2
if (item.children){
item.children.map(i => i.completed = item.completed);
}
};
// 目标 2 END
return {
items,
itemsList,
updateGroup,
toggleItem,
updateChild,
updateParent,
};
},
});
app.component("demand-list", DemandList);
app.component("filter-group", FilterGroup);
app.component("stats", Stats);
let vm = app.mount("#app");
</script>
</body>
</html>
let DemandList = {
// TODO:待补充代码 目标 1
props: ['itemsData'],
emits: ['update-child', 'update-parent', 'toggle-item'],
setup(props, { emit }) {
const toggleItem = (item) => {
emit('toggle-item', item);
};
const updateChild = (parent) => {
emit('update-child', parent);
};
const updateParent = (item) => {
emit('update-parent', item);
};
return {
toggleItem,
updateChild,
updateParent,
};
},
template: `
<ul>
<!-- TODO:待修改代码,目标 1 此处的空数组需要修改正确数据 -->
<li
v-for="item in itemsData"
:key="item.id"
:class="{ demand: item.type === 'demand', bug: item.type === 'bug', task: item.type === 'task' }"
>
// TODO:待补充代码
const Stats = {
props: ['itemsData'],
setup(props) {
const getCount = (type) => {
return props.itemsData.filter(i => i.type == type).length
}
const getSelectedCount = (type) => {
return props.itemsData.filter(i => i.type == type && i.completed).length
}
const getDemandCount = computed(() => getCount('demand'))
const getDemandSelectedCount = computed(() => getSelectedCount('demand'))
const getBugCount = computed(() => getCount('bug'))
const getBugSelectedCount = computed(() => getSelectedCount('bug'))
const getTaskCount = computed(() => getCount('task'))
const getTaskSelectedCount = computed(() => getSelectedCount('task'))
return {
getDemandCount,
getDemandSelectedCount,
getBugCount,
getBugSelectedCount,
getTaskCount,
getTaskSelectedCount
}
},
template: `
<div class="stats">
<div>
需求:{{getDemandSelectedCount}}/{{getDemandCount}}
</div>
<div>
缺陷:{{getBugSelectedCount}}/{{getBugCount}}
</div>
<div>
任务:{{getTaskSelectedCount}}/{{getTaskCount}}
</div>
</div>
`,
};
// TODO:待补充代码
const FilterGroup = {
emits: ['update'],
setup(props, { emit }) {
const obj = ref({
demand: true,
bug: true,
task: true
})
watch(obj, (newData) => {
emit('update',newData)
// console.log(newData)
},{deep: true})
return {
obj,
}
},
template: `
<div class="filter-group">
过滤:
<label>
<input type="checkbox" v-model='obj.demand'> 需求
</label>
<label>
<input type="checkbox" v-model='obj.bug'> 缺陷
</label>
<label>
<input type="checkbox" v-model='obj.task'> 任务
</label>
</div>
`,
};