688
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2023年福大-软件工程实践-W班 |
|---|---|
| 这个作业要求在哪里 | 结对第二次作业--编程实现 |
| 结对学号 | 222000433猫猫&222000434鹦鹉 |
| 这个作业的目标 | fork仓库、编程实现、撰写博客 |
| 其他参考文献 | 相关链接置于文末 |
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 20 | 20 |
| • Estimate | • 估计这个任务需要多少时间 | 20 | 20 |
| Development | 开发 | 2135 | 2610 |
| • Analysis | • 需求分析 (包括学习新技术) | 400 | 600 |
| • Design Spec | • 生成设计文档 | 30 | 45 |
| • Design Review | • 设计复审 | 10 | 10 |
| • Coding Standard | • 代码规范(为目前的开发制定合适的规范) | 45 | 60 |
| • Design | • 具体设计 | 30 | 45 |
| • Coding | • 具体编码 | 1500 | 1750 |
| • Code Review | • 代码复审 | 30 | 40 |
| • Test | • 测试 | 90 | 60 |
| Reporting | 报告 | 30 | 40 |
| • Size Measurement | • 计算工作量 | 10 | 15 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 25 |
| 合计 | 2185 | 2670 |
猫猫&鹦鹉的项目地址~(有效期至2023年4月22日)
对于云服务器,我们选择的是阿里云,因为它能免费使用一个月,并且部署的教程较为简单。
我们采用顶部导航栏+网页内容+页脚的布局,使用下拉菜单提供导航功能。图片失效请戳我~
使用轮播图展示选手图片,并显示两场决赛情况。图片失效请戳我~
使用内容中的导航栏可跳转至相应页面和位置。图片失效请戳我~
了解更多部分,介绍澳网历史。图片失效请戳我~
点击按钮切换不同日期赛程,因为时间关系,我们只实现了Day13和Day14日期的切换。图片失效请戳我~
鼠标悬停边框显示。图片失效请戳我~
点击跳转详情页面,由于时间关系详情页面只实现了Day13中的最后一场即A.Hewett VS T.Oda,所以只有该场能够跳转。图片失效请戳我~
使用ElementUI组件快速实现斑马纹表格,这里的页面布局和原型一致。可查看Men's Singles Aces Leaders和Women's Singles Aces Leaders。图片失效请戳我~
展示从第四轮开始的选手晋级图,晋级选手通过加粗高亮显示,鼠标悬停边框显示。
(鹦鹉牌纯手工制作线条,画疯了......)图片失效请戳我~
显示比赛双方国旗和比赛整体情况、显示该场比赛小场得失分情况。图片失效请戳我~
通过下拉选择不同小场。图片失效请戳我~
提供澳网最新相关消息,使用户更加了解澳网。图片失效请戳我~
点击按钮在页内打开视频播放窗口,查看比赛精彩时刻。由于时间原因,只实现了Day13中的第一场比赛即M.Andreeva VS A.Korneeva。图片失效请戳我~
我们一开始选择前后端分离,但由于搭建环境以及学习新技术较为费时
(同时助教老师对作业要求进行了修改),于是我们改变策略决定使用纯前端进行实现,采用vue框架进行编码(此时的鹦鹉同学要从后端转前端再学新技术十分痛苦...一度想放弃了)
因为web基础不是很好而且对于vue框架是一点都不了解。所以在开发过程中遇到过很多奇奇怪怪的问题,但我们都通过交流讨论一起解决了这些问题,真的是人多力量大!

一开始打算做成前后端分离,猫猫同学(222000433)负责前端,鹦鹉同学(222000434)负责后端;于是我们就开始找教程,定技术,搭建环境,学习相关用法。但是事情的进展并不是那么容易,搭建环境真的很让人抓狂,我们在学习技术上差不多花了两天时间,最终还是决定使用纯前端,使用vue框架进行编写。
对比原型,因为时间不多了,所以我们决定放弃左侧弹出的菜单栏,改用下拉菜单降低工作难度,同时还放弃了日期滚动条,改为直接显示;剩余部分则是对照原型,编写css来进行排版布局修改样式等,使用表格来展示数据。
- 对于导航栏、日期条、赛程显示、选手排名等都是使用ElementUI来实现。
- 晋级图使用css进行布局
- 详细赛况使用table实现
- 页面交互使用监听器和事件函数来实现
1. 页面的组件偏移偏移问题
- 问题描述: 当我们写好一部分页面开始测试时发现,切换某些页面后,这些页面的ui会发生特定的偏移现象,而刷新后却又能恢复正常。
- 解决方案: 经过排查,我们发现,由于VUE单页面开发的特性,写在不同vue文件中的同名样式会产生冲突,因此直接用某一标签名作为选择器来写CSS是比较危险的做法。解决的一种比较麻烦的方式是给标签都加上可以区分的id和class名,使用类选择器;另一种简单粗暴的方式是在所有<style>标签后都加上属性scoped,表示只在当前文件中生效。
2. 高光时刻相关问题
- 问题描述: 完成高光时刻组件后,需要一个关闭按钮来关闭窗口。我们使用v-show绑定data数据来控制播放器组件的显示和隐藏,但是点击按钮后,窗口虽然消失了,可是视频却没有停止播放。
- 解决方案: 经过查询我们发现,v-show隐藏元素的原理是更改该元素的display属性为none,而没有从dom树上删除这个元素。而v-if的作用原理是后者。虽然v-if的开销比v-show大,但是结合实际需求,此处只能替换为v-if。
3. 子组件向父组件发送事件
- 问题描述: 我们将日期条单独做成了组件,嵌入在Results页面内容组件中,但是点击事件需要传递给Results页面内容组件来切换展示比赛结果。
- 解决方案: 通过在子组件注册监听函数,使用this.$root.$emit('自定义事件名',发送参数)来从根元素发送一个自定义事件,而在父组件中使用this.$root.$on('自定义事件名',function(接收参数){//自定义事件的处理函数体})来监听这个自定义事件,代码见下:
//子组件
handlechange(){
this.$root.$emit('date-change',this.selectdate);
},
//父组件
created(){
this.$root.$on('date-change',function(date){
//处理函数...
});
},
- 问题描述: 新闻页面侧边栏只需要展示前若干条新闻,而新闻json数量很庞大。
- 解决方案: v-show的值可以是表达式,将需要展示的数据的index用表达式筛选出来既可,具体见下方代码:
<div class="side-news-content" v-for="(item,index) in newsList" :key="item.index" v-show="index < 4">
一开始想通过伪类选择器给赛程和晋级图加上鼠标悬停特效,设置好了边框颜色和粗细后却并不生效,于是想通过JavaScript来解决,给相应div加上onmouseover和onmouseout事件,但是依旧没能实现,最后是在网上找到了解决方法,原来是单独设置border-width和border-color时要先设置border-style,最后成功实现了悬停特效,但是因为是先写好布局再考虑特效,所以一开始没有考虑边框的粗细来设置div的宽高等,显示出来的效果就是鼠标移上去的时候会位移,变得很奇怪,最后是舍友也刚好遇到这个问题!真的太巧了,然后分享给我了一个CSDN上的解决方法,就是先给div加个透明边框站位,再通过伪类选择器将颜色改变。
一开始在网上看到个前端实现世界杯对战图的博客,想参考来实现晋级图,但是实在是太难理解了,于是决定自己手动实现。每轮比赛是一个div,每场比赛也是一个div,将每轮比赛的div设置为inline-block,以实现后四轮比赛在同一水平上,将div的高度设为1px就是横线,宽度设为1px就是竖线,设置好第四轮比赛的样式后先画了一组连接线想预览一下,结果什么都没有显示,于是将每个div都设置背景色,以便于发现问题产生的原因,其实是因为连线的父容器没有设置宽度,将连线都画好以后,预览时发现位置全乱了,于是给每类div加上一个背景颜色继续来调整位置(不得不说加背景色真的好用!手写css真的太累了QAQ...)。
一开始想通过点击事件修改路由来达到每日赛程到详细赛况的跳转,但是不管使用什么方法都没能成功跳转,再咨询了猫猫同学后,使用router-link成功实现跳转,但是却显示了链接,第二天仔细一看发现可以将div放在router-link里面,但是此时又出现了一个问题,div里的所有文字都变成了链接形式,仔细查阅资料后才明白,原来router-link在实现跳转的时候是转化为a标签实现的,所以只要修改a标签的样式,将下划线和字体颜色修改了就可以了。
主页轮播图实现:
<!-- 轮播图 -->
<el-carousel trigger="click" height="600px" style="width:850px">
<el-carousel-item v-for="item in imgList" :key="item.name">
<img :src="item.src" style="width:100%;height:100%">
</el-carousel-item>
</el-carousel>
data() {
return {
//轮播图片资源json:
imgList: [
{
name:'p1',
src:require('@/assets/home/u46.png'),
},
//其他图片.....
]
};
},
主页点击侧边导航栏滚动到Learn More实现:
对侧边导航栏的LearnMore按钮添加@click="handleClick"事件监听函数:
handleClick(key,keyPath){
console.log(key,keyPath);
document.getElementById('lmt').scrollIntoView({
behavior: "smooth", // 平滑过渡
block: "start" // 上边框与视窗顶部平齐。默认值
});
}
新闻页面实现:
<!-- 侧边新闻栏 -->
<table class="side-news"
background-color="#ffffff"
text-color="#555555">
<div class="side-news-content"
v-for="(item,index) in newsList" :key="item.index" v-show="index < 4"><!-- 侧边只展示前四条新闻 -->
<tr>
<td class="news-title" @mouseover="handleMouseOver"><ul><li>{{ item.title }}</li></ul></td>
</tr>
<tr>
<td class="news-time">{{ item.time }}</td>
</tr>
</div>
</table>
handleClick(key,keyPath){
data(){
return{
//新闻资源json
newsList: [
{
title:'标题...',
content:"内容...",
time:'时间..'
},
{
//其他新闻...
},//.....
]
}
}
}
<!-- 视频内联框架 -->
<iframe ref="player" :src="videolink"
scrolling="no"
border="0"
frameborder="yes"
framespacing="0"
allowfullscreen="true"
v-if="Show">
对不起,您的浏览器版本过低,无法播放视频。
</iframe>
<!-- 关闭内联框架窗口按钮 -->
<el-button class="close-button" icon="el-icon-close" @click="closeClick" v-if="Show"></el-button><!-- 设置相同的v-if条件确保按钮和内联框架同时出现、消失 -->
data(){
return{
Show:false,
ResultsList:{
[
videolink:'//player.bilibili.com/player.html?aid=477807073&bvid=BV12K411C79m&cid=965405712&page=1',//...
],
},
}
},
methods: {
handleClick(key,keyPath){
console.log('1:'+key);
if(this.Show==false)
this.Show=!this.Show;
console.log(this.Show);
},
closeClick(key,keyPath){
if(this.Show==true)
this.Show=!this.Show;
}
}
赛程显示部分
设定好每场比赛的样式,将数据显示出来。
<style>
.el-row {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.court .el-col {
margin-top: 20px;;
border-radius: 4px;
width: 475px;
height: 208px;
}
.bg-purple-dark {
background: #f2f2f2;
}
.bg-purple {
background: #ffffff;
}
.bg-purple-light {
background: #ffffff;
}
.grid-content {
border: 1px solid transparent;
border-radius: 4px;
min-height: 208px;
min-width: 450px;
}
.grid-content:hover {
border-style: inset;
border-width: 1px;
border-color: #1693d2;
}
.row-bg {
padding: 10px 0;
background-color: #f9fafc;
}
.winner {
color: #1693d2;
}
a {
text-decoration: none;
color: black;
}
</style>
晋级图部分
在网上没有找到十分合适的组件能很好地表示晋级图,所以使用css纯手工制作盒子和连线。
<style scoped>
.match1:hover, .match2:hover, .match3:hover, .match4:hover {
border-style: inset;
border-color: #1693d2;
border-width: 1px;
}
.promotion {
border-width: 0px;
margin-top: 50px;
width: 100%;
height: 100%;
background-color: #f2f2f2;
}
.match1, .match2, .match3, .match4 {
border: 1px solid transparent;
width: 320px;
height: 85px;
background-color: white;
}
.fourth, .third, .second, .first, .line_1, .line_2, .line_3 {
display: inline-block;
}
.line_1 {
width: 20px;
position: relative;
top: 35px;
}
.first {
position: relative;
bottom: 395px;
}
.line1 {
display: flex;
width: 20px;
height: 198px;
margin-bottom: 27px;
position: relative;
}
.horizontalline {
border-width:0px;
width:8px;
height:1px;
display:flex;
background-color: black;
}
.vertical {
border-width:0px;
width:1px;
height:113px;
display:flex;
background-color: black;
}
.horizontal, .vertial {
display: inline-block;
}
td {
width: 160px;
height: 28px;
}
</style>
选手排名部分
使用ElementUI的斑马纹table,数据放在js部分。
<div class="ranking">
<div class="men">
<h1 class="title">Men's Singles Aces<br><h1 class="title">Leaders</h1></h1>
<el-table
:data="tableData1"
stripe
style="width: 100%">
<el-table-column
prop="name"
label=""
width="180">
</el-table-column>
<el-table-column
prop="rank"
label="Rank"
width="150">
</el-table-column>
<el-table-column
prop="matches"
label="Matches"
width="150">
</el-table-column>
<el-table-column
prop="aces"
label="Aces"
width="150">
</el-table-column>
</el-table>
</div>
...
详细赛况部分
通过更改标签的类名更换样式来达到set之间的切换。
<script>
export default {
name: 'DetailsContent',
data() {
return {
options: [{
value: 'set2',
label: 'set 2'
}, {
value: 'set1',
label: 'set 1'
}, ],
value: 'set2',
}
},
methods: {
handlechange() {
var cur;
var cur2;
if(this.value=='set2'){
cur=document.getElementById('set2');
cur2=document.getElementById('set1');
cur.className= 'show';
cur2.className='hide';
}
else if(this.value=='set1'){
cur=document.getElementById('set1');
cur2=document.getElementById('set2');
cur.className= 'show';
cur2.className='hide';
}
}
}
}
</script>
猫猫(222000433):
在不到一周时间里把一个完全陌生的框架运用自如还是很困难的(首先配置环境花了一天=。=),这次的作业对我来说十分有难度orz,因此没能实现和原型图完全相同的UI,有点不甘心。看来当前主流的框架技术等还是需要自己积极去累积,所以首先感谢这次作业push我学习了新的技术。
另外,与上次不同的是,原型设计工具的图形界面设计的很好,很容易就能上手,所以必需的学习时间也就少很多,可当我们这次也决定继续上次那种先看个大概就直接上手的方式后,发现开发起来遇到的问题一环扣一环,搜索起来比直接系统性学习某个章节要慢上许多……这让我认识到,技术学习不能好高骛远,系统性的学习必不可少,如何平衡学习与探索时间需要认真思考。
鹦鹉(222000434):
因为一开始规划的不好,没有考虑过自己是否真的能学会那些从来没接触过的技术,花了两天时间学习技术,最后还是转到了前端来帮助猫猫同学,我个人觉得再花时间学习vue可能会导致最后来不及,只能在询问猫猫同学vue大概是怎么使用的就开始上手做页面写布局了。本次编程实现还是和上次原型设计一样,由猫猫同学负责技术上的难点,我负责页面内容布局这些琐碎的部分。经过这次作业,更加深刻地了解到了自己的web基础真的很差,很多很显而易见的原因却研究了半天,非常耽误时间,想要成为一名合格的前端工程师也太难了(各种布局、属性,给我用晕了555...)。
经过这次结对作业,我感觉我的抗压能力还有待提高,总是容易焦虑,在前期就很担心我们会实现不了、做不完等,并且在转到前端但是什么都不会什么都做不了的时候,抵触情绪达到了顶峰(想放弃、想离开这个灰暗的世界、想......),但是在这个时候,我的伙伴站了出来,一直安慰我,稳定我的情绪,努力让我重拾信心,真的很感激猫猫同学;而且因为我的基础不好,不会什么稍微复杂一点的技术,所以猫猫同学很多很好的点子都因为我而没能实现,真的很愧疚555......
总之,不管是技术上还是个人的心理上以及和伙伴的交流上都有了更进一步的提高,也算是不枉花了好几个夜晚来实现这次作业,希望下一次能更有准备地去进行实践、完成作业,更好地实现预期的效果。
猫猫(222000433):
你永远可以相信鹦鹉同学!她实在太可靠了,在开发时又有主见速度又快,复杂的页面编码总是很迅速完成,能很好的把课程内所学知识发挥出来,让我佩服得不得了(星星眼)!!她也很耐心指导我一些代码上的问题,真的很感谢!
这次果不其然我又在没完成全部主要内容的情况下抠一些不很重要的细节,鹦鹉同学也常常有在提醒我不要钻牛角尖,鹦鹉同学真的是很能吸取经验教训的人!
在结对的过程中相互帮助、共同进步的感觉真是比一个人钻研到头秃好多了,谢谢你鹦鹉同学!
鹦鹉(222000434):
猫猫同学真的很厉害!大心脏选手,学习技术也很快,每次我出现情绪上的问题都会来开导我,还提供了本次作业的技术支持!和猫猫同学合作真的太愉快了!和猫猫同学亲密度
猫猫同学在编程实现的过程中总是不紧不慢,很淡定,给人一种一切尽在掌控之中的感觉,让我这个急性子有点着急(dbq),而且猫猫同学很热衷于学习新技术,新方法等,在快要截止的时候又觉得这个地方可以改改,那个地方可以修修,给猫猫同学和我一个小小的建议,在下一次可以先规划好使用的技术和方法,尽量保证方法是好的能够实现的,这样一步到位能免去很多重新修改或者出bug的麻烦。
总之,又是一次愉快的合作!每个人都有很大的进步!完结撒花~(这次是真的完结啦)
Web项目(Vue)部署到阿里云服务器【超详细】
ElementUI
v-for只显示前两条数据
vue/跳转页面后样式错乱/刷新就好了/布局错乱/恢复
前端html中div设置边框border属性无效的解决方案
解决鼠标悬停添加border导致图片抖动的问题
声明式导航<router-link>:解决a标签自带的默认样式
时间很紧迫的情况下能做到这样,很棒