这段时间在作的东西,是北邮人论坛APP的注册页。这个注册页是内嵌的网页,由于打算安卓和IOS平台同时使用。所以实际上就是在作移动端的web开发了。
在这过程当中遇到了很多有意思的东西。php
DEMO的github地址在这里css
内容提要:
html
这点与在PC端写前端有着很大的区别,移动端的meta标签简直多。我就说说我所用到的标签。前端
<!-- 一、若是支持Google Chrome Frame:GCF,则使用GCF渲染;二、若是系统安装ie8或以上版本,则使用最高版本ie渲染;三、不然,这个设定能够忽略。 --> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- 对视窗缩放等级进行限制,使其适应移动端屏幕大小 --> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 当把这个网页添加到主屏幕时的标题(仅限IOS) --> <meta name="apple-mobile-web-app-title" content="北邮人论坛注册"> <!-- 添加到主屏幕后全屏显示 --> <meta name="apple-touch-fullscreen" content="yes" />
尤为是第二个meta标签,是移动端适配很是重要的一句话。vue
总体的布局大体是4-5页横向布局。第一页是用来填写注册信息的。后面的几页是用来选择关注的版面的。
jquery
前端采用的架构大体是这样:
css3
后端支撑的框架来自php的laravel,固然,这不是本文的重点,仅说起一下。laravel
是的此次的开发中,已经看不到jquery的身影了——这也是前端之后发展后的结果——慢慢地脱离jquery的依赖。不过jquery给前端带来的改变和发展是无人能替代的。git
引入swiper.js来进行页面的切换效果纯粹是由于此次开发的周期要求比较短,要考虑效果和兼容性兼备的状况下,我就偷懒找了一个动画库。github
不过这个动画库的效果我仍是算比较满意的。而总体来讲使用也至关方便。尤为是,swiper.js是能够不依赖jquery的。
使用起来也比较方便。我简要说说用法。
首先须要在页面顶部的head标签里加入swiperjs的css文件:
<link rel="stylesheet" href="css/swiper.min.css')">
而后在页面底部能够引入和写下相应的js:
<script src="{{ asset('js/swiper.min.js') }}"></script> <!-- Initialize Swiper --> <script> var swiper = new Swiper('.swiper-container', { pagination: '.swiper-pagination', paginationType: 'progress', noSwipingClass: 'swiper-no-swiping', allowSwipeToNext: true, allowSwipeToPrev: true, }); </script>
解释一下,建立一个swiper的对象,而后这对象的容器是class叫作swiper-container的一个html元素。对其的配置是:
相应的HTML代码能够以下:
<!-- swiper生效的容器 --> <div class="swiper-contanier"> <div class="swiper-wrapper"> <!-- 具体滑动的页面 --> <div class="swiper-slide"></div> <div class="swiper-slide"></div> <div class="swiper-slide"></div> <div class="swiper-slide"></div> </div> </div> <!-- 进度条 --> <div class="swiper-pagination"></div>
有些页面是不能直接让用户经过触摸来先后滑动的,而必须经过点击按钮触发。好比第一页注册页,这个页面就是必须填写完信息而后点击下一步进行验证后而后才能够滑动到后面的内容。因此只要将这个页面所在的class里加上swiper-no-swiping这个class就能够实现没法触摸滑动切换页面了。
而后咱们能够经过swiper.slideNext(bool,time)这个方法来进行手动控制向后翻页的动做以及控制动画的时长。这个内容会在vue里说到。
因为本次的开发只是在原有的北邮人开放平台的项目的基础上加入一个快速注册的功能,因此Vue.js的引入并非为了将整个项目重构,而只是为了尝试一下脱离jquery的状况下对于开发来讲不一样的体验是什么,能学到什么。
关于Vue.js的用法、特性什么的不是本文的重点,题外话就不说了。说说本次实现思路。由于个人Vuejs实际上也只是算入门级别,只能说会用可是还没到能驾驭的程度。
首先整个页面包在class叫作swiper-contanier的元素中。由于这个元素包括了滑动所需的全部东西,咱们实际上能够简单的把它当作是一个SPA(Single Page Application),用一个Vue的实例就能够接管整个页面了(这么说是不负责的,由于实际上Vue是组件化的思想)。
先建立一个基本的Vue的示例,并将其和swiper-container绑定起来:
var vm = new Vue({ el: ".swiper-contanier", // 将这个实例与html元素绑定起来 data: {}, // 所须要变更、关注的数据,也是vue的核心 ready: function(){}, // vue提供的钩子,用于在vue渲染视图完成后当即触发 methods: {} // 方法,用于操做、更新、改变数据而改变视图 })
上面所说,咱们的页面是构建在一个Vue的实例上的。所以不一样类型的两种页面如何用一个实例来接管呢?在这里个人实现方式是用两类数据来分别表示。
咱们分析一下注册页:
实际上注册页的中间部分是重复的元素,他们都是input标签+显示文字标签(对,尤为注意这里并非用placeholder实现的)。效果:
因此这中间的部分实际上能够当作是一个列表,能够用Vue的v-for来渲染。列表里所不一样的只是显示的文字不一样以及input框的类型不一样(有text类型的,有password类型的),因此用数据绑定的方式咱们能够将这个页面的数据格式安排以下:
data: { main: [ {"name":"username","info":"用户名(以英文开头+英文数字)","type":"text"}, {"name":"passwd","info":"设置密码","type":"password"}, {"name":"passwd_confirm","info":"在输入一遍密码","type":"password"}, {"name":"gwno","info":"校园网帐户(默认是学号)","type":"text"}, {"name":"gwpwd","info":"校园网密码(默认是身份证后六位)","type":"password"}, ], }
同时咱们建立一个便于和前端视图进行双向绑定的数据对象userInfo:
data: { main: [...], userInfo: { username: "", passwd: "", passwd_confirm: "", gwno: "", gwpwd: "" } }
而在前端的话咱们就能够用这个数据来进行视图渲染:
<ul class="user-info"> <li v-for="item in main" style="position: relative;"> <!-- input输入框 --> <!-- 此处用了v-model将数据和视图进行了双向绑定 --> <input class="effect" type="{{item.type}}" v-model="userInfo[item.name]"> <!-- 提示信息 --> <label> <span>{{item.info}}</span> </label> <!-- input框的底下的线条 --> <span class="focus-border cube"></span> </li> </ul> <a href="#"><button>下一步</button></a>
因而一个输入的列表就很容易作出来了。而后既然是表单,就须要验证。而此处作的验证明际上有这么几点:
其中只有第二点两次密码输入是否相同能够用前端直接判断,而第1、三点都是须要经过ajax的方式向后台发送验证请求的。为了可以体现和辨别错误与否,咱们在main下的每一个条例里加入了一个error属性,并规定以下三种状态:
因而咱们能够在method下写一些方法来进行判断。
checkUserId: function(msg){ if (msg !== ""){ this.$http.post('url'+msg,function(data){ if (data.success){ this.main[0].error = false; } else{ this.main[0].error = true; } }) } else{ this.main[0].error = "normal"; } }, checkUserPwd: function(){ if (this.userInfo.passwd_confirm !== ""){ this.userInfo.passwd == this.userInfo.passwd_confirm && this.userInfo.passwd_confirm != "" ? this.main[2].error = false : this.main[2].error = true; } },
固然这个只是一个引入的功能,咱们再聚合一下:
check: function(msg,i){ var index = i; this.userInfo[msg] != "" ? this.main[index].effect = true : this.main[index].effect = false; switch (msg){ case "username": this.checkUserId(this.userInfo[msg]); break; case "passwd": this.userInfo.passwd !== "" ? this.main[1].error = false : this.main[1].error = "normal"; this.checkUserPwd(); break; case "passwd_confirm": this.checkUserPwd(); break; case "gwno": this.userInfo.gwno !== "" ? this.main[3].error = false : this.main[3].error = "normal"; break; case "gwpwd": this.userInfo.gwno !== "" ? this.main[4].error = false : this.main[4].error = "normal"; break; } }
这样经过一个check的method咱们就能够将整个表单的验证的方法容纳进来了。(此处对于校园网帐号的验证会放到提交表单的函数中)。为了能在视图中体现正确、错误、正常的不一样形态,咱们须要对前端的一些结构进行一些修改。咱们须要给main下的每一个条例加入错误信息,也即errorInfo。
因此至此整个main的结构是这样:
main: [ {"name":"","info":"","type":"","error":"","errorInfo":""}, ... ]
而后咱们须要加入提交验证的部分:
submitReg: function(){ var flag = 0; // 用于判断表单是否都是正确的 this.main.map(function(obj){ obj.error == false ? flag += 1 : flag +=0; }) if (flag == 5){ this.$http.post('url',this.userInfo) .then(function(res){ if (res.success){ swiper.slideNext(false,300); // 验证正确就能够进入下一页 } else{ this.main[4].error = true; } }) } },
将视图部分修改以下:
<ul class="user-info"> <li v-for="item in main" style="position: relative;"> <!-- 绑定blur事件 --> <input @blur="check(item.name,$index)" class="effect" type="{{item.type}}" v-model="userInfo[item.name]"> <!-- 根据error类型切换不一样的标签显示 --> <label> <!-- 此处用到了v-show的方法 --> <span v-show="item.error == 'normal'">{{item.info}}</span> <span style="color: red;" v-show="item.error == true">{{item.errorInfo}}</span> <span v-show="item.error == false">{{item.info}}√</span> </label> <span class="focus-border cube"></span> </li> </ul> <!-- 点击下一步的同时提交表单信息 --> <a href="#"><button @click="submitReg">下一步</button></a>
至此,整个注册页的布局和功能性的部分都已经作完了。不过这只是一块比较简单的部分,咱们用到了vuejs的的v-for进行列表渲染,用到了v-model进行数据的双向绑定,用到了method进行一些数据的处理,用到了v-show进行条件显示,一个基本的页面下咱们已经能尝试这么多vue的特性了。而相比于jquery的dom操做,我以为vue在此处最好的地方在于,表单的提交很方便。因为双向绑定了数据,只须要后台把数据格式规定好给我,我按照后端的数据结构整理一下我前端的数据结构而后就能够直接提交给后端了。并且省去了不少dom操做的地方。
不过除了vue的部分,我还想来讲说两个东西,跟css有关:
全屏背景
不只仅是简单的background-size: cover那么简单了,还须要进行小小的处理。先说说我但愿实现的效果吧。我但愿的效果是整个背景可以填充整个页面,而且在页面元素上下滚动的状况下,背景固定而不随着元素滚动。
放到往常我可能会这么写:
body,html{ height: 100%; } body{ background: url(bg.png) center 0 no-repeat; background-size: cover; }
可是这样的话在移动端会出现比较严重的后果,那就是一旦页面元素的高度大于整个页面后,滚动页面元素的时候,背景也会随之而动。并且背景会被撑开。这不是我所但愿的。
这里用到一个小技巧,用上:before的方法。
body:before { content: ""; position: fixed; z-index: -1; top: 0; right: 0; bottom: 0; left: 0; background: url(bg.png) center 0 no-repeat; background-size: cover; }
这个用上before的伪元素的方法是一个颇有奇效的小技巧。你们不妨能够试试。这样的话在移动端也能完美实现背景固定并且显示全屏。
移动端动画简单初探
在作PC端的web的动画效果的时候,因为PC端的性能足够,因此在写一些效果的时候每每没有考虑到性能的问题。此次在开发的时候就遇到了动画效果实现上不小的问题。你们先来看看这两个动画的比较:上面一个动画和下面一个动画:
第一个:
https://codepen.io/molunerfinn/pen/zBGrxx
第二个:
https://codepen.io/molunerfinn/pen/oLXjKz
会发现这两个东西的效果相差甚大。实际上,两者实现的最终效果是一致的,都是让小球按一条口型路线运动。可是为什么显示上来讲,第一个这么流畅,而第二个有明显卡顿呢?
这里涉及到不少东西,不光光是重绘(repaint),还有软硬件性能上面的问题。感兴趣的话能够参考这些文章:
在移动端上的效果若是没有优化的话,实际上大体就是第二种的效果——让人看起来有所卡顿。简单来讲,在移动端,有些效果是由浏览器来渲染的——那么这些效果若是比较复杂,而移动端的浏览器性能又不太足够的状况下,效果就比较卡顿。有些效果能够由GPU来渲染,那么这些效果渲染起来就相对来讲比较流畅。而咱们还能够人为触发GPU硬件渲染,经过 transform的translate3d属性就能实现硬件渲染从而俗称硬件加速。
举个简单例子。若是让一个元素从(0,0)->(100px,0),正常思路是left: 0->left: 100px,而后再用transition属性进行过渡。不过这样的话在移动端上效果就很感人,由于涉及到性能问题。可是若是咱们用另一种方式: transform: translate3d(100px,0,0)的话,就可让这个动画效果由GPU去渲染,那么这样的话,在移动端的效果也是彻底能够接受的流畅。
实际上,可以触发GPU渲染的动做有opacity,transform,transition,animation等等。可是像top,left,color,size等属性的变化则不会触发GPU渲染。
本文中描述的实例,是当焦点集中到input框的时候,文本上移而且有颜色变化。原本想实现的是文本大小还有变化。可是因为上面说的状况,涉及到size变化的时候,效果就会大打折扣。无奈之下我只能砍掉这个效果了。而实现文本上移实际上就是采用了transform的translate3d的方式,将其往上移动,并配合transition进行了一下过渡处理罢了。
具体的CSS实现大体以下:
input:focus ~ label,.trans { color: #fff; transition: 0.3s; -webkit-transform: translate3d(0, -20px, 0); -moz-transform: translate3d(0, -20px, 0); -ms-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); }
实际上也不难不是么?
实际上从注册页的实现中已经能够瞅见关注版面页实现的方法了。实际上关注版面页不过也是列表的渲染,在数据里定义好相应的属性就好了。而后用一个picked的属性来看看是否被选中便可。最后完成注册的时候,将全部选中的列表组装成相应的数组提交到后台就好了。由于注册页里这些方法已经说过了,因此就再也不赘述了。
实际上,兼容性方面还有很多的东西须要诉说,不过限制于篇幅以及本文的主要内容并非在纠结移动端的兼容性的因此并无在兼容性方面进行记录。
在排版上我仍是没有用上比较流行的flex,对于Vue尚未使用组件化开发的思路。这些都是须要改进的部分。不过此次的开发过程当中通过美工的指点,将我以前写页面的时候注意不到的不少细节部分,好比线条尺寸,元素间隔,颜色搭配等东西给指了出来,这些东西都不是简简单单就实现的。总之,有时间的话,我想我能够将设计方面的知识融入到个人前端开发中,想必能让个人做品更加地符合审美和用户的体验吧~
DEMO的github地址在这里
文章做者: Molunerfinn
文章连接: https://molunerfinn.com/vuejs-1/
版权声明: 本博客全部文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 MARKSZのBlog!