蓝桥杯Web开发【大学组:国赛】2022年真题

1.分一分

如果给你一个数组,你能很快将它分割成指定长度的若干份吗?

1.1 题目问题

请在 js/index.js 文件中补全函数 splitArray 中的代码,最终返回按指定长度分割的数组。

具体要求如下:

  1. 将待分割的(一维)数组升序排序。
  2. 将排序后的数组从下标为 0 的元素开始,按照从 id=sliceNum 的输入框中获取到的数值去分割,并将分割好的数据存入一个新数组中。如:输入框中值为 n,将原数组按每 n 个一组分割,不足 n 个的数据为一组。
  3. 将得到的新数组返回(即 return 一个二维数组)。

例如:

var arr = [3, 1, 4, 2, 5, 6, 7];
// 分割成每 1 个一组
var newA = splitArray(arr, 1);
console.log(newA); // => [[1],[2],[3],[4],[5],[6],[7]]

// 分割成每 2 个一组
newA = splitArray(arr, 2);
console.log(newA); // => [[1,2],[3,4],[5,6],[7]]

// 分割成每 4 个一组
newA = splitArray(arr, 4);
console.log(newA); // => [[1,2,3,4],[5,6,7]]

// 分割成每 7 个一组
newA = splitArray(arr, 7);
console.log(newA); // => [[1,2,3,4,5,6,7]]

上述仅为示例代码,判题时会随机提供数组对该函数功能进行检测。

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

在这里插入图片描述

1.2 题目分析

排序可以使用数组的sort方法

完成分割可以使用数组的slice方法做成切片然后push到需要返回的数组中去

1.3 题目解答

const splitArray = (oldArr, num) => {
  // TODO:请补充代码实现功能
  let newArr = []
  oldArr.sort((a, b) => a - b)
  for(let i = 0 ; i < oldArr.length; i += num){
    const a = oldArr.slice(i, num+i)
    newArr.push(a)
  }
  return newArr
    
}

2.新鲜的蔬菜

厨房里新到一批蔬菜,被凌乱地堆放在一起,现在我们给蔬菜分下类,把相同的蔬菜放到同一个菜板上,拿给厨师烹饪美味佳肴吧。

2.1 题目问题

完成 css/style.css 中的 TODO 部分。所有元素的大小都已给出,无需修改,

初始效果

完成后效果如下(图中灰色线条为布局参考线无需实现):

布局位置示意图

2.2 题目分析

本题主要是考察了对flex布局的应用,以及结构伪类选择器的使用

2.3 题目解答

/* TODO:待补充代码 */
#box1{
  display: flex;
  justify-content: center;
  align-content: center;
  flex-wrap: wrap;
}

#box2{
  display: flex;
  justify-content: space-between;
}

#box2 .item:nth-child(2){
  align-self: flex-end;
}

#box3 {
  display: flex;
  justify-content: space-evenly;
}

#box3 .item:nth-child(2){
  align-self: center;
}

#box3 .item:nth-child(3){
  align-self: flex-end;
}

3.水果消消乐

消消乐是一款益智类休闲游戏,在排队等待做核酸的时候可以打开手机玩一会,陪你度过这漫长且无聊的等待期。

3.1 题目问题

请完善 js/index.js 文件。

具体说明如下:

  • 点击开始按钮后,该按钮被隐藏,方格上的图片显示后又隐藏。
  • 点击方格,方格中的图片显示,页面显示两张图片后,比较图片是否相同。
  • 如果图片上的水果相同,方格即可消除,并得 2 分;如果图片上的水果不相同,图片隐藏,并扣 2 分(分数可以为负数)。
  • 在文本 “当前分数为:” 的冒号后面会实时统计当前的得分情况。

在这里插入图片描述

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

在这里插入图片描述

3.2 题目分析

本题主要是利用事件监听,来控制元素的显示和隐藏

要注意的点是事件监听的事件对象e和如何获取子节点父节点等

以及两个水果相同的时候控制隐藏和消失的不是display而是visibility或者是opacity。因为display是直接相当于消除了该元素,会影响布局的结构,而visibility和opacity只是让这个元素单单的隐藏

3.3 题目解答

// TODO:请补充代码
function startGame() {
  document.querySelector("#start").style.display = "none";
  const img = document.querySelectorAll("img")
  for(let i = 0; i < img.length; i++ ){
    img[i].style.display= 'inline-block'
  }
  setTimeout(() => {
    for(let i = 0; i < img.length; i++ ){
        img[i].style.display= 'none'
      }
  }, 1000);
  let count = 0
  let alt = ''
  let prevObj = null
  let score = 0
  const scoreobj = document.querySelector('#score')
  const arr = document.querySelectorAll('.img-box')
  for(let i = 0; i < arr.length; i++){
    arr[i].addEventListener('click', (e) => {
        if(count  === 0 ){
            prevObj = e.target
            e.target.children[0].style.display= 'inline-block'
            alt = e.target.children[0].alt
            count = 1
        }else{
            e.target.children[0].style.display= 'inline-block'
            setTimeout(() => {
                if(e.target.children[0].alt === alt){
                    e.target.style.visibility = 'hidden'
                    prevObj.style.opacity = 0
                    count = 0
                    score += 2
                    scoreobj.innerHTML = `${score}`
                }else{
                    prevObj.children[0].style.display = 'none'
                    e.target.children[0].style.display= 'none'
                    count = 0
                    score -= 2
                    scoreobj.innerHTML = `${score}`
                }
            }, 500)
        }


    })
  }
}

4.用什么来做计算A

古以算盘作为计算工具。算盘常为木制矩框,内嵌珠子数串,定位拨珠,可做加减乘除等运算。站在前人的肩膀上,后人研究出计算器,便利了大家的生活,我们不用带着笨重的计算工具出门,打开手机上的计算器就可以了。

4.1 题目问题

请完善 js/index.js 文件,当鼠标点击计算器上的按钮时,能够正常进行计算。

具体说明如下:

  • 点击按钮会在计算式子区域显示当前输入的计算式子,当点击等号(=) 后,在结果显示区域应该显示出正确的结果。
  • 计算器需要具有加(+)减(-)乘(x)除(÷)开二次方(√)重置(AC)小数点(.)括号运算这八个功能。
  • 计算器的计算遵循四则混合运算的法则,括号的优先级最高,其次是乘除,加减的优先级最低。

效果说明如下:

  • 能够正确进行加、减、乘、除的混合运算,样例如下所示:

在这里插入图片描述

  • 能够正确进行开二次方,输入一个可以平方的数,点击开方(√)按钮即可在结果显示区域显示结果。如果输入的值是不能平方,结果显示 NaN,样例如下所示:

在这里插入图片描述

在这里插入图片描述

  • 点击重置按钮(AC),可以清空计算式子显示区域和结果显示区域的值。

  • 能够进行小数的加减乘除运算,样例如下所示:

在这里插入图片描述

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

在这里插入图片描述

4.2 题目分析

本题最关键的核心就是eval函数。eval函数可以将传入的字符串变成代码去执行

其次就是判断字符串相等和一些字符串常用的方法

而解决开二次方,则需要用到JS内置的Math构造函数的sqrt()

4.3 题目解答

解法1

// TODO:请补充代码
const show1 = document.querySelector('#formula')
const show2 = document.querySelector('#result')

let process = ''

const button = document.querySelectorAll('.calc-button')
for ( let i = 0; i < button.length; i++ ) {
    button[i].addEventListener('click', function (e) {
        if(e.target.innerHTML === 'AC'){
            show1.value = ''
            process = ''
            show2.value = ''
        }else if(e.target.innerHTML === '='){
            console.log(process);
            show2.value = eval(process)
        }else if(e.target.innerHTML === '÷'){
            process += '/'
            show1.value += e.target.innerHTML
        }else if(e.target.innerHTML === 'x'){
            process += '*'
            show1.value += e.target.innerHTML
        }else if(e.target.innerHTML === '√'){
            console.log(eval(process));
            if(eval(process) < 0 ){
                show2.value = NaN
            }
            show2.value = Math.sqrt(eval(process))
        }else{
            show1.value += e.target.innerHTML
            process += e.target.innerHTML
        }   
    })
}

解法2

// TODO:请补充代码
const calculator = document.querySelector('.calculator');

// 事件委托(无需遍历所有按钮)
calculator.addEventListener('click', (event) => {
    if (event.target.className == 'calc-button') {

        // 当点击的是以下 3 种按钮时 需要做特殊处理。
        switch(event.target.textContent) {
            case '=' :
                const resultStr1 = formula.value.replaceAll('x', '*').replaceAll('÷', '/');
                result.value = eval(resultStr1);
                return;
            case 'AC' :
                formula.value = '';
                result.value = '';
                return;
            case '√' :
                result.value = Math.sqrt(formula.value);
                return;
        }

        formula.value += event.target.textContent;
    }
});

5.开学礼物大放送

又是一年开学季,蓝桥为大家准备了开学礼物,想制作一个页面来宣传一下该活动。

5.1 题目问题

请完善 css/style.cssindex.html 文件。

请根据 mark/preview 最终效果图和 mark/index.html 上的参数标注来完成页面布局。

效果图如下:

在这里插入图片描述

5.2 题目分析

看结构就知道考察了定位、flex方面的一些知识

5.3 题目解答

考察的只是简答的页面实现,每个人的实现方式不同,代码差异也很大,这里就不放代码了

6.权限管理

你有没有想过,在我们日常浏览的网页中,那些新闻或者商品内容是如何被输入到数据库中的呢?大家虽然没有用过,但是肯定听过“后台管理系统”,运营人员就是通过它将批量的商品上传到数据库并呈现在网页中的。那么随便一个人就可以通过该管理系统操作这些商品数据吗?当然不行,这就涉及到了权限管理问题。

6.1 题目问题

请在 js/index.js 文件中补全代码,最终实现管理用户权限的功能。

具体需求如下:

  1. 实现异步数据读取和渲染功能。

    • 使用 ajax 异步获取 ./js/userList.json 中的用户数据,并以正确的方式显示在页面下的用户权限表格中(注意:调试完成后请将请求地址写死为 ./js/userList.json)。

    • 页面初始化时,左边用户列表显示 7 个用户(页面数据和结构不能随意篡改),右边的管理员列表无选项。效果如下:

在这里插入图片描述

  1. 实现左/右单个、多个或全部互移功能。

    • 选中任意一个或多个(按 Ctrl 键可多选)左/右边用户/管理员列表中的用户,并点击选中移动到右/左边按钮,即可将选中的用户/管理员移动至另一边的管理员/用户列表中。效果如下:

在这里插入图片描述

  • 点击全部移动到右/左边按钮,则将左/右边用户/管理员列表中的用户全部移动到右/左边的管理员/用户列表中(即:左/右边列表被清空)。效果如下:

在这里插入图片描述

在这里插入图片描述

  1. 实现用户权限表格中的权限,随用户移动发生变化功能。

    • 页面下的用户权限表格中所有用户的权限,会根据页面上方所处列表不同发生相应改变,即管理员列表中的用户权限为管理员,用户列表中的用户权限为普通用户

完成后效果如下:

在这里插入图片描述

6.2 题目分析

本题主要考察了ajax进行请求数据的知识,我们可以用ajax中的xhr技术来完成

还考察了对文档对象模型的考察,以及操作节点

还有就是css的伪类选择器:checked

6.3 题目解答

$(function () {
  // 使用 ajax 获取 userList.json 数据并渲染到页面
  getData();

  // 为按钮添加事件
  $("#add").click(function () {
    // TODO:补充代码,实现功能
    changeAccess(true,document.querySelectorAll('#leftSelect>option:checked'))
  });
  $("#addAll").click(function () {
    // TODO:补充代码,实现功能
    changeAccess(true,document.querySelectorAll('#leftSelect>option'))
  });
  $("#remove").click(function () {
    // TODO:补充代码,实现功能
    changeAccess(false,document.querySelectorAll('#rightSelect>option:checked'))
  });
  $("#removeAll").click(function () {
    // TODO:补充代码,实现功能
    changeAccess(false,document.querySelectorAll('#rightSelect>option'))
  });
});

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

  function fn(who){
    for(let i = 0;i<changeList.length;i++){
      document.querySelector(who).appendChild(changeList[i])
      const tr = document.querySelectorAll('#userList>tr')
      tr.forEach(e=>{
        if(e.firstChild.innerText==changeList[i].value){
          e.lastChild.innerText = right?'管理员':'普通用户'
        }
      })
    }
  }
}

// 异步获取数据
function getData() {
  // TODO:补充代码,实现功能
  const xhr = new XMLHttpRequest();
  xhr.open("GET", "./js/userList.json");
  xhr.addEventListener("loadend", () => {
      const res = JSON.parse(xhr.response)
      // 一定要注意不能篡改页面数据结构,意思就是不能自己加表格的表头
      // 因此就不要用map了
      res.forEach(item => {
        const tr = document.createElement('tr')
        const power = item.right ? '管理员' : '普通用户'
        tr.innerHTML = `<td>${item.name}</td><td>${power}</td>`
        document.querySelector(".user-list").appendChild(tr)
      })
  });
  xhr.send()
}

7.一起会议吧

网络会议已经成为当下最流行的会议模式,为网络会议提供支持的当然是一些优秀的会议软件。

1.1 题目问题

请在 index.html 文件中补全代码,最终实现网络会议中参会人员列表的几个展示效果

具体需求如下:

  1. 实现异步数据读取和渲染功能。

    • 使用 axios 异步获取 ./js/userList.json 中的用户数据(注意:调试完成后请将请求地址写死为 ./js/userList.json),并显示在登录窗口参会人员窗口中。效果如下:

  2. 实现登录、注销切换功能。

    • 在登录窗口选取用户登录后,登录窗口切换为注销窗口,具体变化为:登录标题变为注销字样;选择用户下拉框变为显示当前登录用户名登录按钮变为注销按钮。参会人员窗口显示,并默认只显示当前登录用户信息。效果如下:

1.2 题目分析

computed中计算当前用户列表有哪些,返回一个数组,根据图标点击的状态筛选出相应的用户对象,状态改变了,就会重新计算。

1.3 题目解答

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>一起会议吧</title>
    <link rel="stylesheet" type="text/css" href="./css/index.css" />
    <link rel="stylesheet" href="./css/iconfont/iconfont.css" />
  </head>
  <body>
    <div id="app">
      <!-- TODO:请在下面实现需求 -->
      <!-- 登录/注销窗口 -->
      <div class="login">
        <div class="left-tools">
          <a class="close-btn"></a>
          <a class="shrink-btn"></a>
        </div>
        <h3>{{ !isLogin ? '登录' : '注销' }}</h3>
        <p v-if="!isLogin">
          选择用户:<select id="selectUser" v-model="currentUser">
            <option v-for="user in userList" :key="user.id" :value="user">{{ user.name }}</option>
          </select>
        </p>
        <p v-if="isLogin">当前用户为:{{ currentUser.name }}</p>

        <a class="login-btn" @click="handleLogin">{{ !isLogin ? '登录' : '注销' }}</a>
      </div>

      <!-- 右侧显示用户列表窗口按钮 -->
      <button id="show" class="right-btn" v-if="isLogin" v-show="!isShow" @click="isShow = true">
        <span class="iconfont icon-left-arrow"></span>
      </button>

      <!-- 用户列表窗口 -->
      <div class="user-dialog" v-if="isLogin" v-show="isShow">
        <!-- 用户列表窗口上侧工具栏 -->
        <ul class="tools">
          <li class="tools-left">
            <button :class="{ active: currentState == 1 }" @click="currentState = 1">
              <span class="iconfont icon-close"></span>
            </button>
            <button :class="{ active: currentState == 2 }" @click="currentState = 2">
              <span class="iconfont icon-dialog"></span>
            </button>
            <button :class="{ active: currentState == 3 }" @click="currentState = 3">
              <span class="iconfont icon-list"></span>
            </button>
          </li>
          <li class="tools-right">
            <button class="show-list" @click="isShow = false">
              <span class="iconfont icon-retract"></span>
            </button>
          </li>
        </ul>

        <!-- 用户列表 -->
        <ul class="say-list">
          <li>
            <span class="iconfont icon-microphone"></span>
          </li>
          <li class="line"></li>
          <li>正在讲话:{{ currentSay }};</li>
        </ul>
        <ul class="user-list">
          <li v-for="user in filterUserList" :key="user.id">
            <img class="header" :src="user.imgPath" />
            <div class="user-name">
              <span v-if="user.isHost" class="iconfont icon-user header-icon"></span>
              <span class="iconfont icon-microphone"></span>
              {{ user.name }}
            </div>
          </li>
        </ul>
      </div>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript" src="./js/axios.min.js"></script>
    <script type="text/javascript">
      // TODO:请在下面实现需求
      new Vue({
        el: "#app",
        data: {
          userList: [],  // axios获取的用户列表
          isLogin: false,  // 登录标志
          isShow: true,   // 展示用户列表标志
          currentUser: {},  // 当前登录用户对象
          currentState: 2  // 当前选择页面呈现的方式
        },
        async mounted() {
          let { data } = await axios.get('./js/userList.json')
          this.userList = data
          this.currentUser = this.userList[0]
        },
        methods: {
          handleLogin() {
            if(this.isLogin) {
              // 注销重置
              this.currentState = 2
              this.isShow = true
            }
            this.isLogin = !this.isLogin
          }
        },
        computed: {
          filterUserList() {
            if(this.currentState == 2) {
              return this.userList.filter(u => u.id == this.currentUser.id)
            } else if(this.currentState == 3) {
              return this.userList.filter(u => u.id == this.currentUser.id).concat(this.userList.filter(u => u.id != this.currentUser.id))
            } else {
              return []
            }
          },
          currentSay() {
            return this.userList.find(u => u.isHost).name
          }
        }
      });
    </script>
  </body>
</html>

8.天气趋势A

日常生活中,气象数据对于人们的生活具有非常重要的意义,数据的表现形式多种多样,使用图表进行展示使数据在呈现上更加直观。

1.1 题目问题

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

  1. 完成数据请求(数据来源 ./js/weather.json),weather.json 中存放的数据为 12 个月对应的温度数据。在项目目录下已经提供了 axios,考生可自行选择是否使用。注意:调试完成后请将请求地址写死为 ./js/weather.json

  2. data 中的月份数据 monthList, 在 class=month 标签下面的 li 上完成渲染,点击月份则切换对应月份的温度数据同时被点击的月份会变成激活状态( .active 类),x 轴为日期,y 轴为温度,默认显示 1 月份数据。

  3. 如果点击的月份是当天(通过时间函数动态获取的时间)所在月份,本月和未来七天切换的 tab (即 id=currentMonth 元素)显示,其他月份 currentMonth 元素不显示。

    • 默认显示本月数据。
    • 点击本月显示当月数据,点击未来七天显示从当天(包含当天)开始未来七天的数据,当显示未来七天数据时 x 轴需要显示为月/日格式。
    • 点击 tab本月未来七天会切换激活状态(.active)。

    以当天为 5 月 29 号为例,未来七天 x 轴显示示例(即 x 轴显示成:5/29,5/30,5/31,6/1,6/2,6/3,6/4):

本月未来七天 切换效果见文件夹下 effect-1.gif

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

在这里插入图片描述

1.2 题目分析

本题主要是考查如何异步更新图标数据的问题

以及内置的Date构造函数的使用

1.3 题目解答

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>天气趋势</title>
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
    />
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <script src="./js/axios.js"></script>
    <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script
      src="js/echarts.min.js"
      type="text/javascript"
      charset="utf-8"
    ></script>
  </head>

  <body>
    <div id="app">
      <div class="top-bar">2022年 Y 城全年温度统计图</div>
      <!-- 主体 -->
      <div class="container">
        <!-- 月份 -->
        <div class="month">
          <ul>
            <!-- TODO:待补充代码 在下面的 li 标签中完成 12个月份 (即 monthList) 的渲染  -->
            <li
              :class="{active:active == i}"
              v-for="(m,k,i) in monthList"
              @click="changeMonth(i)"
            >
              {{m}}
            </li>
          </ul>
        </div>
        <div class="chart">
          <!-- TODO:待补充代码  -->
          <!-- currentMonth  未来七天和本月 tab 切换,只有当前月才显示 -->
          <div id="currentMonth" v-if="currentMonth == active">
            <div class="title">
              <h3>{{isfuture ? '未来七天天气' : typeTitle}}</h3>
              <div class="type">
                <span id="seven" :class="{active:isfuture}" @click="future"
                  >未来7天</span
                >
                <span
                  id="current"
                  :class="{active:!isfuture}"
                  @click="changeMonth(active)"
                  >本月</span
                >
              </div>
            </div>
          </div>
          <div id="chart"></div>
        </div>
      </div>
    </div>
  </body>
</html>
<script>
  // TODO:待补充代码
  var vm = new Vue({
    el: "#app",
    data: {
      chart: null, // 图表
      chartOptions: null, // 图表配置项
      typeTitle: "本月天气",
      active: 0,
      isfuture: false,
      currentMonth: new Date().getMonth(),
      weatherData: [],
      monthList: {
        January: "1月",
        February: "2月",
        March: "3月",
        April: "4月",
        May: "5月",
        June: "6月",
        July: "7月",
        August: "8月",
        September: "9月",
        October: "10月",
        November: "11月",
        December: "12月",
      },
    },
    mounted: async function () {
      let { data } = await axios.get("./js/weather.json");
      this.weatherData = data.map((v) => Object.values(v).flat(1));
      // 初始化 echarts
      this.$nextTick(() => {
        this.initChart();
      });
    },
    methods: {
      async initChart() {
        // 初始化图表
        this.chart = echarts.init(document.getElementById("chart"));
        // 配置项
        this.chartOptions = {
          grid: {
            top: 35,
            bottom: 5,
            left: 10,
            right: 10,
            containLabel: true,
          },
          tooltip: {
            trigger: "axis",
            axisPointer: {
              lineStyle: {
                color: {
                  type: "linear",
                  x: 0,
                  y: 0,
                  x2: 0,
                  y2: 1,
                  colorStops: [
                    {
                      offset: 0,
                      color: "rgba(255,255,255,0)",
                    },
                    {
                      offset: 0.5,
                      color: "rgba(255,255,255,1)",
                    },
                    {
                      offset: 1,
                      color: "rgba(255,255,255,0)",
                    },
                  ],
                  global: false,
                },
              },
            },
          },
          xAxis: [
            {
              type: "category",
              boundaryGap: false,
              axisLabel: {
                formatter: "{value}",
                fontSize: 12,
                margin: 20,
                textStyle: {
                  color: "#bfbfbf",
                },
              },
              axisLine: {
                lineStyle: {
                  color: "#e9e9e9",
                },
              },
              splitLine: {
                show: true,
                lineStyle: {
                  color: "#f7f7f7",
                },
              },
              axisTick: {
                show: false,
              },
              // x 轴显示的数据,日期
              data: [
                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,
              ],
            },
          ],
          yAxis: [
            {
              boundaryGap: false,
              type: "value",
              axisLabel: {
                textStyle: {
                  color: "#bfbfbf",
                },
                formatter: `{value}\u2103`,
              },
              nameTextStyle: {
                color: "#fff",
                fontSize: 12,
                lineHeight: 40,
              },
              splitLine: {
                lineStyle: {
                  color: "#f7f7f7",
                },
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: "#e9e9e9",
                },
              },
              axisTick: {
                show: false,
              },
            },
          ],
          series: [
            {
              name: "天气",
              type: "line",
              smooth: false,
              showSymbol: false,
              symbolSize: 0,
              zlevel: 3,
              itemStyle: {
                color: "#ff6600",
                borderColor: "#a3c8d8",
              },
              lineStyle: {
                normal: {
                  width: 3,
                  color: "#ff6600",
                },
              },
              areaStyle: {
                normal: {
                  color: new echarts.graphic.LinearGradient(
                    0,
                    0,
                    0,
                    1,
                    [
                      {
                        offset: 0,
                        color: "#ff6600",
                      },
                      {
                        offset: 0.8,
                        color: "#ff9900",
                      },
                    ],
                    false
                  ),
                },
              },
              //  Y 轴显示的数据,即温度数据
              data: [
                23, 19, 30, 31, 18, 20, 16, 15, 23, 27, 29, 30, 32, 23, 25, 20,
                22, 24, 34, 24, 21, 26, 23, 24, 25, 23, 25, 28, 32, 20,
              ],
            },
          ],
        };
        // 调用此方法设置 echarts 数据
        this.chart.setOption(this.chartOptions);
        this.changeMonth(0);
      },
      changeMonth(m) {
        this.active = m;
        this.isfuture = false;
        let x = [...new Array(this.weatherData[m].length).keys()].map(
          (v) => v + 1
        );
        let y = this.weatherData[m];
        this.chartOptions.xAxis[0].data = x;
        this.chartOptions.series[0].data = y;
        this.chart.setOption(this.chartOptions);
      },
      future() {
        this.isfuture = true;
        let date = new Date();
        let d = date.getDate();
        let x = [];
        let y = this.weatherData[date.getMonth()].slice(d - 1, d + 6);
        if (y.length != 7) {
          y = y.concat(this.weatherData.slice(0, 7 - y.length));
        }
        for (
          let i = +date;
          i < +date + 7 * 1000 * 60 * 60 * 24;
          i += 1000 * 60 * 60 * 24
        ) {
          x.push(new Date(i).getMonth() + 1 + "/" + new Date(i).getDate());
        }
        console.log(x, y);
        this.chartOptions.xAxis[0].data = x;
        this.chartOptions.series[0].data = y;
        this.chart.setOption(this.chartOptions);
      },
    },
  });
</script>

9.JSON生成器

JSON 已经是大家必须掌握的知识点,JSON 数据格式为前后端通信带来了很大的便利。在开发中,前端开发工程师可以借助于 JSON 生成器快速构建一个 JSON 用来模拟数据。

1.1 题目问题

请在 index.js 文件中补全 generateData 函数代码,并最终返回一个 js 对象(说明 : generateData 生成的数据会由插件自动转化成 JSON)。

在左侧的输入框中输入指定格式的数据模板,点击生成 JSON 按钮,右侧会自动生成对应格式的 JSON 数据。

  1. 数据模板中对象的 key 对应的 value 如果是 {{}} 并且符合下述规则,则根据下述规则解析,否则一律返回原始 value 值。具体规则如下:

    • {{bool()}} 表示随机生成布尔值。
    • {{integer(n, m)}} 表示生成 n-m 之间(包含 n、m )的随机整数(注意:n<m)。

    目标1测试用例

    附目标 1 测试用例:

    {
      isPass: '{{bool()}}',
      age: '{{integer(3, 5)}}',
      goodsNumber:2,
      isShow:false,
      tag:'phone',
      fn:'{{integer}}'
    }
    
  2. 数据模板中 {{repeat()}}(此项只会出现在数组首位)表示重复生成数组中的数据,如:"repeat(5, 7)" 则表示随机生成 5-7 条数组数据,repeat 中值只包含一个数字,如"repeat(5)" 表示生成 5 条数组数据。

    目标2测试用例

    附目标 2 测试用例(3 组):

    // (1)随机生成 `2-5` 条数组数据
    [
      "{{repeat(2, 5)}}",
      {
        isActive: "{{bool()}}",
        age: "{{integer(20, 40)}}",
        num: 2,
        boolean: true,
        str: "str",
        isTel: "{{bool}}",
        fn: "{{fn()}}",
      },
    ]
    // (2)固定生成 `7` 条数组数据
    [
      ("{{repeat(7)}}",
      {
        isTrue: "{{bool()}}",
        score: "{{integer(3, 7)}}",
        tag: "android",
        isSamll: true,
        fn: "{{fn()}}",
      })
    ]
    // (3)无 repeat 的情况
    [
      { maxNum: 10 }
    ];
    

注意:本题不考虑用户输入和传参不合法的情况,只处理合法的数据格式即可,实际测试中 keyvalue 为非固定值。提供的测试用例仅为方便测试代码使用,实际使用中需要对所有符合要求的数组/对象结构的模板生效。

1.2 题目分析

主要是考察了对正则的理解和使用

以及eval和Math的相关使用

注意:eval执行字符串里面的代码的时候如果出现{{ 代码 }}包裹的字符串,{{}}不会被执行和返回-----类似于vue的插值表达式

1.3 题目解答

/*
 * @param {*}  左侧输入框输入的值转化成的 js 数据
 * @return {*} 根据传入的数据生成对应的 js 格式数据
 */
let generateData = (data) => {
  // TODO:待补充代码
  //正则表达式用于匹配字符
  //匹配形如 {{repeat(n1, n2, ..., nk)}} 的字符串模式
  let reg1 = /^\{\{(repeat\([\d,\s]+\))\}\}$/
  let reg2 = /^\{\{bool\(\)\}\}$/
  let reg3 = /^\{\{integer\([\d,\s]+\)}\}$/
  //不是数组进入
  if(!Array.isArray(data)){
    for(let k in data){
      //将bool和integer进行转换并运行
      if(reg2.test(data[k])||reg3.test(data[k])){
        data[k]=eval(data[k]);
      }
    }
    return data;
  }
  //记录重复生成的次数
  let len = reg1.test(data[0]) ? eval(data[0]) : 1
  let result = []//记录结果

  while (result.length !== len) {
    let obj = {...data[1]}//扩展成一个对象
    for (let k in obj) {
      if(reg2.test(obj[k]) || reg3.test(obj[k])) {
        obj[k] = eval(obj[k])
      }
   }
    result.push(obj)
  }

  function repeat(a,b){
    //如果b是空值,则返回啊,否则返回随机值
    return  b ? Math.random() * (b-a+1) + a | 0 : a
  }
  function integer(a, b) {
    return Math.random() * (b - a + 1) + a | 0
  }
  function bool() {
    return Math.random() > 0.5
  }
  return result
};

module.exports = { generateData };

10.商城管理系统

在商城管理系统中,超级管理员和普通管理员因为权限不同,登录进入后看到的菜单也会是不同的。

1.1 题目问题

请在 js/auth.js 文件中补全 getMenuListAndAuth 函数代码。

在登录页 login.html 点击管理员登录超级管理员登录时会根据管理员的权限不同,在商城首页 index.html 的左侧显示不同的菜单列表。但是后端同学给的数据是不符合前端展示要求的,所以我们需要做些处理,假如后端提供的数据是这样的:

[
  { parentId: -1, name: "商品管理", id: 1, auth: "cart" },
  { parentId: 1, name: "商品列表", id: 4, auth: "cart-list" },
  { parentId: -1, name: "添加管理员", id: 10, auth: "admin" },
];

其中数据中对象字段的含义说明:

  • id 表示当前节点
  • parentId 表示父级节点,如果为 -1 则表示顶级数据
  • auth 表示权限

具体需求如下:

  1. 将待处理数据(一维数组)根据 parentId 字段值处理成树形结构存入 menus 变量中。

把数据处理成如下格式(每一项都必须有 children 字段,没有子级时,children 为空数组):

[
  {
    parentId: -1,
    name: "商品管理",
    id: 1,
    auth: "cart",
    children: [
      {
        parentId: 1,
        name: "商品列表",
        id: 4,
        auth: "cart-list",
        children: [],
      },
    ],
  },
  {
    parentId: -1,
    name: "添加管理员",
    id: 10,
    auth: "admin",
    children: [],
  },
];

注意js/auth.js 中的 menuList 仅为后端返回的数据结构示例,非固定数据。实际使用中,后端返回的数据转化成树形结构时层级可能更多,封装方法时务必考虑通用性。

  1. 将待处理数据中的 auth 字段提取出来并存入 auths 变量中,左侧菜单会根据传入的权限列表数组和 auths 对比后进行菜单渲染。

经过 getMenuListAndAuth 处理后 auths 的结果为:

["cart", "cart-list", "admin"];

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

在这里插入图片描述

1.2 题目分析

考察了递归算法和数组的去重

1.3 题目解答

const getMenuListAndAuth = (menuList) => {
  // TODO:待补充代码
  const arr = menuList.map(item => item.auth)
  const auths = arr.filter((item, index) => arr.indexOf(item) === index)
  
  const menus = getMenuList(menuList, -1)
  function getMenuList(menuList, parentId) {
    let arr = []
    menuList.forEach(item => {
      if (item.parentId == parentId) {
        arr.push(item)
        item.children = getMenuList(menuList, item.id)
      }
    })
    return arr
  }
  return { menus, auths }; // menus 转化后的树形结构数据,auths 转化后的权限列表数组
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/654805.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

web前端之vue动态访问静态资源、静态资源的动态访问、打包、public、import、URL、Vite

MENU 静态资源与打包规则动态访问静态资源直接导入将静态资存放在public目录中动态导入URL构造函数结束语实践与坑附文 静态资源与打包规则 介绍 Vite脚手架在打包代码的时候&#xff0c;会把源代码里对于静态资源的访问路径转换为打包后静态资源文件的路径。主要的区别是文件指…

Vue中使用Vue-scroll做表格使得在x轴滑动

页面效果 首先 npm i vuescroll 在main.js中挂载到全局 页面代码 <template><div class"app-container"><Header :titletitle gobackgoBack><template v-slot:icon><van-icon clickgoHome classicon namewap-home-o /></templat…

深度解析Java 11核心新特性

码到三十五 &#xff1a; 个人主页 < 免责声明 > 避免对文章进行过度解读&#xff0c;因为每个人的知识结构和认知背景都不同&#xff0c;没有一种通用的解决方案。对于文章观点&#xff0c;不必急于评判。融入其中&#xff0c;审视自我&#xff0c;尝试从旁观者角度认清…

爬虫实战教程:深入解析配乐网站爬取1000首MP3

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、实战前准备 1. 选择目标网站 2. 分析网页结构 三、爬虫工作流程详解 1. 发…

内网穿透入门使用(frp和natapp)

内网穿透入门使用 简单介绍穿透工具推荐FrpFrp下载安装服务端配置启动服务端配置客户端启动客户端效果查看 NATAppNATApp下载安装NATApp配置启动NATApp 使用途径 我的博客&#xff1a;Lichg&#xff0c;欢迎大家访问留言。 简单介绍 什么是内网穿透&#xff1a; 首先我们对内网…

lvm概述和配额

lvm概述和配额 文章目录 lvm概述和配额LVM概述1、逻辑卷的作用&#xff1a;2、lvm主要命令和实操磁盘配额创建data目录&#xff0c;进入data目录限制创建文件数 LVM概述 逻辑卷管理liunx系统下对硬盘分区的一种管理机制 lvm机制特别适合管理大储存设备&#xff0c;可以动态的…

Echarts x轴坐标二级分组

在使用echarts 封装组件的时候&#xff0c;偶尔会遇到需要x轴坐标进行二层分组的需求。那么如何对echarts 进行二层分组呢&#xff0c;有以下几个步骤&#xff1a; 仅介绍二层分组的逻辑。有兴趣的可以进行三层延伸。 1&#xff0c;修改echarts Options 中xAxis 的配置。 此…

win11中文文件名称乱码解决方案

解压后出现以下的乱码 解决方案 步骤1.winR 输入intl.cpl 或 windows 自带的搜索搜“intl.cpl”&#xff0c;打开这个面板控制项 步骤2.在新打开的区域面板中&#xff0c;选择“管理”标签页&#xff0c;点击下方的“更改系统区域设置”按钮 步骤3.取消"Beta版…"选…

如何将RK R75键盘的右Alt键改为Ctrl键

打开注册表地址栏中输出 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout右键新建二进制值&#xff0c;名称设为ScanCode Map按下图输入数值

【NumPy】全面解析NumPy的bitwise_and函数:高效按位与操作指南

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

鸿蒙4.2小版本推出,鸿蒙5.0已经不远了

上个月&#xff0c;市场上迎来了华为鸿蒙系统4字开头的小升级&#xff0c;版本来到了4.2版本。 我们先来看看4.2版本都给用户带来哪些特色&#xff1a; 界面切换更流畅&#xff1a;无论是响应速度还是操作手感&#xff0c;用户都将感受到更加迅速和顺滑的体验 搜星速度的显著…

磁盘管理以及文件系统08

1、为什么要对磁盘进行分区&#xff1f; 业务层面&#xff1a;为满足一定的需求所是做的特定操作。 2、硬盘是什么&#xff0c;以及硬盘的作用 硬盘&#xff1a;计算机的存储设备&#xff0c;一个或者多个带磁性的盘组成的&#xff0c;可以在盘片上进行数据的读写。硬盘的最…

深入解析Python中的两种导入方法:from...import与import

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、from...import与import的基本区别 1. 导入方式的不同 2. 命名空间的差异 三…

开源与闭源:AI大模型发展路径的博弈

一、引言 在人工智能&#xff08;AI&#xff09;领域&#xff0c;大模型以其卓越的性能和广泛的应用前景&#xff0c;成为了近年来技术发展的热点。然而&#xff0c;在大模型的发展路径上&#xff0c;开源与闭源两种模式一直存在着激烈的博弈。本文将深入探讨这两种模式在大模…

ZooKeeper安装

安装Zookeeper 1、下载Zookeeper安装包 打开链接选择一个版本进行下载 https://zookeeper.apache.org/releases.html2、上传Zookeeper安装包到集群 输入命令 scp apache-zookeeper-3.8.4-bin.tar.gz hadoop192.168.88.100:/tmp也可以使用xftp等上传&#xff0c;物理机用u盘…

DINO结构中的exponential moving average (ema)和stop-gradient (sg)

DINO思路介绍 在 DINO 中&#xff0c;教师和学生网络分别预测一个一维的嵌入。为了训练学生模型&#xff0c;我们需要选取一个损失函数&#xff0c;不断地让学生的输出向教师的输出靠近。softmax 结合交叉熵损失函数是一种常用的做法&#xff0c;来让学生模型的输出与教师模型的…

C++学习笔记(19)——模板

目录 模板参数与非类型模板参数 模板参数 类型模板参数——传递类型 非类型模板参数——传递数量 C11希望array替代静态数组&#xff0c;但实际上vector包揽了一切 模板总结 优点&#xff1a; 缺点&#xff1a; 模板特化&#xff1a;针对某些类型进行特殊化处理 特化…

代码随想录算法训练营第五十三天||1143.最长公共子序列、1035.不相交的线、53. 最大子序和

文章目录 一、1143.最长公共子序列 思路 二、1035.不相交的线 思路 三.53. 最大子序和 思路 一、1143.最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长公共子序列的长度。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原…

mysql中text,longtext,mediumtext区别

文章目录 一.概览二、字节限制不同三、I/O 不同四、行迁移不同 一.概览 在 MySQL 中&#xff0c;text、mediumtext 和 longtext 都是用来存储大量文本数据的数据类型。 TEXT&#xff1a;TEXT 数据类型可以用来存储最大长度为 65,535(2^16-1)个字符的文本数据。如果存储的数据…

stream-实践应用-统计分析

背景 业务部门提供了一个数据&#xff0c;数据甚至不是excel类型的&#xff0c;是data.txt&#xff0c;每一行都是一个数据&#xff0c;需要对此数据进行统计分析 统计各个月份的销量 因为直接获取resources下的data.txt&#xff0c;所以要借助输入流进行获取数据&#xff0c;再…