赞
踩
.seat-area {
margin-top: 50px;
display: grid;
grid-template-columns: repeat(2, 45px 65px 45px 45px);
gap: 10px;
}
function createWatermark(text, color, deg, opacity, count) { // 创建水印容器 const container = document.createElement('div') container.className = 'watermark' // TODO: 根据输入参数创建文字水印 for (let i = 0; i < count; i++) { const span = document.createElement('span') span.innerText = text span.style.color = color span.style.transform = `rotate(${deg}deg)` span.style.opacity = opacity container.appendChild(span) } return container }
function collectPuzzle(...puzzles) {
// TODO: 在这里写入具体的实现逻辑
return Array.from(new Set(puzzles.flat()))
}
@media (max-width: 800px) { .menu { height: 54px; line-height: 54px; margin-bottom: 25px; } .icon-menu { color: #a0a0a0; margin-left: 20px; display: inline-block !important; } .icon-menu:hover { color: white; cursor: pointer; } .collapse { display: none; } input[type='checkbox']:checked ~ .collapse { display: flex; flex-direction: column; background-color: #252525; } .dropdown:hover ul { display: flex; flex-direction: column; } .row { margin-top: 20px; display: flex; flex-wrap: wrap; } .box { margin-bottom: 15px; } #tutorials img { margin: 0; } }
<template> <div class="block"> <span class="demonstration">请为外卖评分:</span> <ul class="rate-list"> <li> <!-- TODO: 补全 el-rate 属性 --> 送餐速度: <el-rate @change="changeScore" show-score="true" v-model="speed"></el-rate> </li> <li> <!-- TODO: 补全 el-rate 属性 --> 外卖口味: <el-rate @change="changeScore" show-score="true" v-model="flavour"></el-rate> </li> <li> <!-- TODO: 补全 el-rate 属性 --> 外卖包装: <el-rate @change="changeScore" show-score="true" v-model="pack"></el-rate> </li> </ul> </div> </template> <script> module.exports = { data() { return { speed: 0, // 送餐速度 flavour: 0, // 外卖口味 pack: 0, // 外卖包装 } }, /* TODO:待补充代码 */ methods: { changeScore() { if (this.speed && this.flavour && this.pack) { this.$emit('change', { speed: this.speed, flavour: this.flavour, pack: this.pack, }) } }, }, } </script>
document.querySelector('#sendBulletBtn').addEventListener('click', () => {
// TODO:点击发送按钮,输入框中的文字出现在弹幕中
bulletConfig.value = document.querySelector('#bulletContent').value
renderBullet(bulletConfig, videoEle, true)
})
/** * @description 根据 bulletConfig 配置在 videoEle 元素最右边生成弹幕,并移动到最左边,弹幕最后消失 * @param {Object} bulletConfig 弹幕配置 * @param {Element} videoEle 视频元素 * @param {boolean} isCreate 是否为新增发送的弹幕,为 true 表示为新增的弹幕 * */ function renderBullet(bulletConfig, videoEle, isCreate = false) { const spanEle = document.createElement('SPAN') spanEle.classList.add(`bullet${index}`) if (isCreate) { spanEle.classList.add('create-bullet') } // TODO:控制弹幕的显示颜色和移动,每隔 bulletConfig.time 时间,弹幕移动的距离 bulletConfig.speed // 解构配置对象 const { isHide, speed, time, value } = bulletConfig // 获取视频容器的宽度和高度 const { width, height } = getEleStyle(videoEle) // 给元素添加样式 spanEle.innerText = value spanEle.style.color = `#${getRandomNum(999999)}` spanEle.style.position = 'absolute' spanEle.style.top = `${getRandomNum(height)}px` spanEle.style.left = `${width}px` spanEle.style.display = isHide ? 'none' : 'block' // 将配置好的SPAN标签追加到视频容器中 videoEle.appendChild(spanEle) // 控制弹幕移动 let left = width const timer = setInterval(() => { left -= speed spanEle.style.left = `${left}px` if (left <= -spanEle.clientWidth) { videoEle.removeChild(spanEle) clearInterval(timer) } }, time) }
// 将用户输入的带分隔符的 isbn 字符串转换只有纯数字和大写 X 字母的字符串 // 入参 str 为转换为包含任意字符的字符串 function getNumbers(str) { // TODO: 待补充代码 return str == '' ? '' : str.match(/\d|X/g).join('') } // 验证当前 ISBN10 字符串是否有效 // 入参 str 为待判断的只有纯数字和大写 X 字母的字符串 function validISBN10(str) { // TODO: 待补充代码 const reg = new RegExp(/\d{10}|(\d{9}X{1})/) if (!reg.test(str)) return false const num = str.split('') if (num.length != 10) return false // 上面那个正则有问题,这里加个判断 const sum = num.slice(0, 9).reduce((prev, cur, index) => prev + Number(cur) * ++index, 0) const remainder = sum % 11 const contrast = num[9] == 'X' ? 10 : num[9] return contrast == remainder } // 将用户输入的 ISBN-10 字符串转化为 ISBN-13 字符串 // 入参 isbn 为有效的 ISBN-10 字符串 function ISBN10To13(isbn) { // TODO: 待补充代码 const str = '978' + isbn.substring(0, 9) const sum = str.split('').reduce((prev, cur) => { cur = Number(cur) // 转数字格式 return (prev += cur % 2 == 0 ? cur * 3 : cur) }, 0) const remainder = sum % 10 const verify = remainder == 0 ? 0 : 10 - remainder return str + verify }
<div id="app"> <header> <div>全球新冠疫情数据统计</div> </header> <main> <!-- TODO: 请修改以下代码实现不同国家的数据展示功能 --> <div class="title"> <h2>{{curCountry}}</h2> </div> <div class="boxes"> <div class="box1"> <h3>确诊</h3> <div class="number"> <span class="font-bold">新增:{{newConfirmed}}</span> </div> <div class="number"> <span class="font-bold">总计:{{totalConfirmed}}</span> </div> </div> <div class="box2"> <h3>死亡</h3> <div class="number"> <span class="font-bold">新增:{{newDeaths}}</span> </div> <div class="number"> <span class="font-bold">总计:{{totalDeaths}}</span> </div> </div> </div> <select v-model="selectCountry"> <option :value="0">Select Country</option> <option v-for="item in data" :value="item">{{item.Country}}</option> <!-- 请在此渲染所有国家选项 --> </select> <div id="chart" style="width: 100%; height: 50vh"></div> </main> </div> <script> var vm = new Vue({ el: "#app", methods: { // TODO: 请修改该函数代码实现题目要求 initChart () { // 初始化图表 this.chart = echarts.init(document.getElementById("chart")); this.chartOptions = { title: { text: "全球感染人数前30国家累计确诊人数统计", x: "center", }, tooltip: { trigger: "axis", axisPointer: { type: "shadow", label: { show: true }, }, }, // 设置x轴数据 xAxis: { // TODO:这里需要显示国家名称缩写,因为有些国家的全称太长,会导致界面不美观 data: this.countryCodeList, axisLabel: { show: true, interval: 0, }, }, yAxis: { type: "value", name: "确诊数量", }, // 设置y轴数据 series: [ { // TODO:设置图表中的总确证数 data: this.totalConfirmedList, type: "bar", itemStyle: { normal: { color: "#a90000" }, }, }, ], }; // 调用此方法设置 echarts 数据 this.chart.setOption(this.chartOptions); }, }, // TODO: 请在此添加代码实现组件加载时数据请求的功能 async mounted () { this.data = (await axios.get('./js/covid-data.json')).data this.initChart(); }, computed: { countryCodeList () { return this.data.map(e => e.CountryCode) }, totalConfirmedList () { return this.data.map(e => e.TotalConfirmed) } }, data () { return { data: [], selectCountry: 0, newConfirmed: 0, totalConfirmed: 0, newDeaths: 0, totalDeaths: 0, curCountry: '请选择国家' } }, watch: { // 监听下拉列表值,动态切换数据 selectCountry (val) { this.curCountry = val.CountryCode || this.curC this.newConfirmed = val.NewConfirmed || 0 this.totalConfirmed = val.TotalConfirmed || 0 this.newDeaths = val.NewDeaths || 0 this.totalDeaths = val.TotalDeaths || 0 } } }); </script>
实现思路: 此题主要难点在于 style 和 class 的处理,将当前渲染对象传入对应方法,判断返回对象具有的属性
/* * 骨架屏渲染组件 */ let ItemTemplate = `` // TODO: 请补充完整Template,完成组件代码编写 ItemTemplate += ` <div :class="'ske-'+paragraph.type+'-container'"> <div v-for="item in arrIs(paragraph)" :class="classIs(item)" :style="styleIs(item)" > <item :paragraph="item" :active="active"></item> </div> </div> ` Vue.component('item', { name: 'item', template: ItemTemplate, props: ['paragraph', 'active'], data() { return { typeList: ['rect', 'circle'], classPrefix: 'ske ske-', activeClass: ' ske-ani' } }, watch: {}, methods: { // 判断是 rows or cols arrIs(obj) { if (obj?.rows) return obj.rows else if (obj?.cols) return obj.cols else return [] }, // 判断class类 classIs(obj) { if (this.typeList.includes(obj.type)) { return this.classPrefix + obj.type + (this.active ? this.activeClass : '') } else { return this.classPrefix + obj.type } }, // 判断样式 styleIs(obj) { if (obj?.style && obj?.rowStyle) return { ...obj.style, ...obj.rowStyle } else if (obj?.style) return obj.style else if (obj?.rowStyle) return obj.rowStyle else if (obj?.colStyle) return obj.colStyle else return {} }, }, })
async function ajax({ url, method = 'get', data }) { let result // TODO:根据请求方式 method 不同,拿到树型组件的数据 // 当method === "get" 时,localStorage 存在数据从 localStorage 中获取,不存在则从 /js/data.json 中获取 // 当method === "post" 时,将数据保存到localStorage 中,key 命名为 data if (method === 'get') { const dataList = localStorage.getItem('data') result = dataList ? JSON.parse(dataList) : (await axios({ url, method })).data.data } if (method === 'post') { // result = (await axios({ url, method, data })).data localStorage.setItem('data', JSON.stringify(data)) } return result }
实现思路: 递归生成DOM树
function treeMenusRender(data, grade = 0) { let treeTemplate = '' // TODO:根据传入的 treeData 的数据生成树型组件的模板字符串 grade++ for (obj of data) { treeTemplate += grade === 3 ? `<div class="tree-node" data-index="${obj.id}" data-grade="${grade}"> <div class="tree-node-content" style="margin-left: 30px"> <div class="tree-node-content-left"> <img src="./images/dragger.svg" alt="" class="point-svg" /> <span class="tree-node-tag">${obj.tag}</span> <span class="tree-node-label">${obj.label}</span> </div> <div class="tree-node-content-right"> <div class="students-count"> <span class="number"> 0人完成</span> <span class="line">|</span> <span class="number">0人提交报告</span> </div> <div class="config"> <img class="config-svg" src="./images/config.svg" alt="" /> <button class="doc-link">编辑文档</button> </div> </div> </div>` : `<div class="tree-node" data-index="${obj.id}" data-grade="${grade}"> <div class="tree-node-content" style="margin-left: ${grade === 2 && 15}px"> <div class="tree-node-content-left"> <img src="./images/dragger.svg" alt="" class="point-svg" /> <span class="tree-node-label">${obj.label}</span> <img class="config-svg" src="./images/config.svg" alt="" /> </div> </div>` if (obj?.children) treeTemplate += `<div class="tree-node-children">${treeMenusRender(obj.children, grade)}</div>` treeTemplate += `</div>` } return treeTemplate }
实现思路: 利用字符串替换的方式,将拖动的元素插入到对应节点,最后将替换完成的字符串转JSON对象重新赋值给 treeData
function treeDataRefresh({ dragGrade, dragElementId }, { dropGrade, dropElementId }) { if (dragElementId === dropElementId) return // TODO:根据 `dragElementId, dropElementId` 重新生成拖拽完成后的树型组件的数据 `treeData` let dragStr = JSON.stringify(getDragElement(treeData, dragElementId)) let dropStr = JSON.stringify(getDragElement(treeData, dropElementId)) let treeDataStr = JSON.stringify(treeData) if (dragGrade === dropGrade) { treeDataStr = treeDataStr.replace(dragStr, '') treeDataStr = treeDataStr.replace(dropStr, dropStr + ',' + dragStr) } if (dragGrade - dropGrade == 1) { if (dropStr.includes(dragStr)) dropStr = dropStr.replace(dragStr, '') const newDragStr = `${dragStr},` const newDropStr = dropStr.replace('[', '[' + newDragStr) treeDataStr = treeDataStr.replace(dragStr, '') treeDataStr = treeDataStr.replace(dropStr, newDropStr) } // 处理多余字符 treeDataStr = treeDataStr.replace(',,', ',').replace('[,', '[').replace(',]', ']') treeData = JSON.parse(treeDataStr) }
通过传入的 id 获取被拖拽的节点对象
function getDragElement(data, id) {
for (const obj of flatObj(data)) {
if (obj.id == id) return obj
}
}
此方法将 treeData 扁平化
function flatObj(obj) {
return obj.reduce((prev, cur) => {
prev = [...prev, cur]
if (cur?.children) prev = [...prev, ...flatObj(cur.children)]
return prev
}, [])
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。