前言
由于各种原因,最后学校的体育系统的前端由我来写。这算是自己第一次做交互性这么强的项目,也是自己第一次使用Vue书写。整个项目过程中学到了很多新东西,也把很多自己从书本上看到的东西使用上了。总体来讲收获满满。下面来总结一下自己的项目经验,以及指出自己通过这个项目发现的不足之处。
业务需求简述
系统使用者为体育负责人和运动员,体育负责人登录成功后,选择需要报名的比赛,报名成功,系统返回一个序列号。运动员通过这个序列号报名并且填写个人信息上传。负责人对于上传的运动员信息确认领队以及运动员具体参加比赛的那个类别(例如单打,双打等)
备注:本系统主要在移动端使用
前端布局
对于前端布局,自己一向是很有信心,毕竟自己还是写过不少的前端界面,想想不就那么回事吗?但是总还是会遇到一些问题。
表格布局
因为自己在布局方面使用了bootstrap框架,对于表格,当然第一时间是想到设定class为table。如果想要更多样式,当然也还可以设置更多的class。但是对于表格中列比较多,并且比较长的时候,就比较尴尬了。对于外部是bootstrap中的container,pc端一般不会出现溢出的情况,但是对于移动端,溢出那是秒秒钟的事情。这个怎么办呢?首先第一个想法就是看看能不能强制横屏查看,最后基本实现了,具体实现过程后面再说。但是即使使用横屏,信息还是显示不完全,不过每个td可以左右滑动查看,觉得也还过得去。本来以为这里就告一段落了,但是有人在用iPhone7测试的时候,发现td中的内容不能够滑动查看。这个就尴尬了,本来想着修改table的样式,但是因为使用了bootstrap框架中的table样式,修改一直没有成功。后来索性想着自己写table样式,但是对于table中的布局其实有很多坑的,不过好在自己之前把这个坑都填好了,并且准备了一个小demo(嘻嘻)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
table,tr,td{
margin:0;
padding: 0;
border-spacing: 0;
font-size: 12px;
color:orange;
}
table{
border:gray solid;
width: 400px;
border-width: 1px 0px 0px 1px;
}
td{
border:gray solid;
width: 100px;
padding: 10px 3px;
border-width: 0px 1px 1px 0px;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<td>Name</td>
<td>Age</td>
<td>Sex</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
<tr>
<td>xiaoD</td>
<td>30</td>
<td>男</td>
<td><input type="button" value="Delete" class="btn" /></td>
</tr>
</tbody>
</table>
</body>
</html>
对于代码就不多做解释,最后放几张自己项目中实现的效果图
其中对于手机竖屏的哪一张可以左右滑动,这里只需要对于外层div设置overflow:auto即可
模态框
对于模态框的制作原理还是挺简单的,就是设置一个div,将position设置为absolute,然后宽高(根据内容大小的例外),设置top值,以及left值,让其居中。恩,一切都很好,实现了。但是当有下拉条的时候,就出问题了,弹出的模态框一直在最开始页面的中间,并不是当前屏幕的中间。不过这里应该可以用JavaScript获取当前的scrolltop值,然后……不过还是觉得太麻烦,最后找到一个方法,设置position为fixed,这样弹出的模态框始终处于当前页面的居中位置。
css样式
说其css,这次真得是赚大了,前不久接触过less(不过讲道理现在sass应该用的更加多一点),在里面把主题颜色通过变量的方式定义了一下。在整个项目过程中,主题颜色修改了两次,要是没有通过变量的方式定义,估计还得忙一阵。
存在问题:因为一个人写,命名以及书写顺序相对比较随意,所以是时候应该总结一下css书写规范以及命名规则
JavaScript
判断屏幕是横屏还是竖屏
function orientationChange() {
var oDirection = document.getElementById("direction");
if(window.orientation == 90 || window.orientation == -90){
oDirection.className = 'true_direction'
}else{
oDirection.className = 'false_direction'
}
};
// 添加监听函数
addEventListener('load', function(){
orientationChange();
window.onorientationchange = orientationChange;
});
其中direction的宽度和高度都是100%,设置一个背景色,透明度为1,并且z-index为最高,如果是横屏,我们将其display设置为none,否则设置为block。这样就可以达到一种覆盖的效果
判断设备是否是移动端
setInterval(function(){
if (!((/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i).test(navigator.userAgent))) {
document.documentElement.innerHTML = "<h3 style=\"text-align:center\">请使用手机或者pad打开此页面</h3>";
}
},1000)
上面代码加了一个定时器,隔一秒钟判断一次,当然这里也可以设置为覆盖的方式
上传图片并显示
这里主要是通过FormData的方式实现
下面是图片上传代码:
// 检测是否支持FormData
if(window.FormData){
var formData = new FormData()
//这里的file是<input type="file" id="file">控件
formData.append('avatar', document.getElementById('file').files[0]);
formData.append('password', this.password);
formData.append('name', this.name);
formData.append('fullname', this.fullname);
formData.append('contact_person', this.contact_person);
formData.append('contact_phone', this.contact_phone);
formData.append('type', "account");
formData.append('action', "modify");
}
下面是获取上传的图片代码:
var reader = new FileReader()
reader.onload = function(event){
var image = new Image()
image.src = event.target.result
//这里的container是new Vue({})获取到的
container.avater_new = image.src
}
reader.readAsDataURL(document.getElementById("file").files[0]);
上面的代码写在type为file控件中的onchange事件中
document.referrer
对于移动端的使用,肯定需要history.back()操作,这时候我们需要获取前一个页面的地址,这时候就可以使用document.referrer来获取,但是如果在别人直接发一个不是首页的链接给你的时候,你点击返回按钮,会没有反应。借鉴前端大神张鑫旭的做法就是,如果不存在,那么我们就跳转到首页,代码如下:
if(document.referrer === '' ){
window.location.href='index.php'
}else{
window.location.href=document.referrer
}
-
在下面几种情况下document.referrer无效(引用张鑫旭)
-
1、直接在浏览器地址栏中输入地址;
2、使用location.reload()刷新(location.href或者location.replace()刷新有信息);
3、在微信对话框中,点击链接进入微信自身的浏览器;
4、扫码进入QQ或者微信的浏览器;
5、从https的网站直接进入一个http协议的网站(Chrome下亲测);
6、a标签设置rel=”noreferrer”(兼容IE7+);
7、meta标签来控制不让浏览器发送referer;
例如:
<meta content="never" name="referrer">
上面的方法虽然很好,但是这样通过跳转的方式,导致每个页面都刷新,重新加载也不是一种很划算的事情(如果对于页面进行了离线缓存另当别论),所以我们可以指定只跳转到某个页面(例如index.php)进行刷新,所以我们还可以通过下面的方式实现:
if(document.referrer === '' || document.referrer === 'index.php'){
window.location.href='index.php'
}else{
history.back()
}
Vue
之前说过这是自己第一次使用Vue框架,来总结一下心得。因为自己对其他框架,例如React,Angular了解偏少,无法评价他们自己的优劣。
vue渲染过程出现{{xxx}}
解决方法主要有两种
第一种就是通过v-text绑定
<span v-text="name"><span>
第二种就是通过v-cloak,第二中主要可以解决下面这种情况,如果通过第一种又需要添加一个标签
<span v-cloak>姓名:{{name}}<span>
css中需要添加下面代码
[v-cloak]{
display:none;
}
对于Vue的生命周期有了一些理解
当我们点击下面的比赛信息以后,再点击主页,这时候系统会执行beforeUpdate和Updated。如果我们需要进行相关的操作,那么我们可以将代码写在Updated中。
当我们点击返回按钮,执行history.back()的时候,会执行mounted前的所有操作,但是我们并看不到页面有重新加载的情况,所以不要被表面现象所迷惑。