写着写着发现会写很多内容... 所有写在一篇文章里感受太多了不方便看,因此分为上下篇吧...下篇写完啦,感兴趣的朋友能够继续关注 => Vue开发仿旅游站webapp项目总结 (下)css
此文章,仅是作完项目后的我的以为能够总结下来的操做/思路,接触vue不久的朋友应该会有收获。此项目也才是萌新作的第二个Vue项目,使用了脚手架工具( vue-cli 2.x 非 3 ),前辈老手们有时间看的话,有写得很差的地方还请多多指导!~html
仅实现项目首页、项目详情页、城市列表页组件的页面/逻辑。vue
千万别点我webpack
先用脚手架生成项目框架。ios
由于作的是一个移动端网页,因此咱们能够有一些配置:git
index.html里加个 meta
标签:github
<meta name="viewport"content="width=device-width,initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
在网页的<head>
标签中增长以上代码,可让网页的宽度自动适应手机屏幕的宽度。web
其中:ajax
width=device-width : 表示宽度是设备屏幕的宽度vuex
initial-scale=1.0 : 表示初始的缩放比例
minimum-scale=1.0 : 表示最小的缩放比例
maximum-scale=1.0 : 表示最大的缩放比例
user-scalable=no : 表示用户是否能够调整缩放比例
以上我设置的参数的目的是:想要一打开网页,就自动以原始比例显示,而且不容许用户修改,不容许用户缩放。
在不一样的手机浏览器上,默认的一些样式是不一样统一的。咱们须要把这些不一样手机的初始化样式作一个统一。
因此能够引入个 reset.css
这是一个初始化的代码,其中一些初始化配置能够自行根据需求修改。
想看/拿代码的能够到我Github上拿:src/assets/styles/reset.css
在移动端页面开发,经常有个 1像素边框 的问题。
也就是有的手机屏幕分辨率比较高,若是咱们在页面上写border-bottom啥的样式,会致使这些手机屏幕分辨率高的当中,1px边框显示成2px边框或3px边框等显示成多像素。
为了解决这个1像素边框问题,咱们就引入了 border.css(貌似这是哪一个团队提出的解决方案?忘记啦,只知道怎么用...但仍然要表示感谢。还有其余解决方案,这个就自行搜索了。)
两百多行不贴出来了,想看/拿完整代码的能够到我Github上:src/assets/styles/border.css
具体这个解决方案的用法,看过border.css代码的同志就会发现很简单:在元素上根据想要的需求加如下这些类名。
按照字面意思理解就行。
好比要给一个元素加上一像素的下边框,就直接加个类名:<div class="border-bottom>"
就好了。
要给一个元素加上一像素的上边框和下边框,就直接加类名:<div class="border-topbottom">
就好了。
边框也能够改颜色的,举个项目中的例子,按照这种格式去改颜色(本文例子有css代码的话基本都是stylus的写法):
对应页面:
在移动端开发中,某些机型、某些浏览器上,click点击事件要延迟300ms执行。
要解决这个问题,咱们引入个fastclick库
npm install fastclick --save
--save的意思是:无论在开发环境测试,仍是线上跑代码,安装了的库均可以使用。而且下载好后,自动存到package.json的dependencies属性中,好比这里install的fastclick:
而后在入口函数main.js中引入和使用:
import fastClick from 'fastclick'
、fastClick.attach(document.body)
先在阿里巴巴矢量图标库建立一个项目
而后在iconfont上选购,添加到购物车,选好后添加到本身的项目,而后下载到本地。
下载的东西中只要用到这几个:
而后把iconfont.css放到一个文件夹中而且在入口函数main.js处引入后就能够全局使用了。
举个使用的例子:
注意类名要加iconfont,而后这里在span里输入的代码就是你选中的图标的代码:
这步其实应该穿插在作项目过程当中进行的,这里先列出来。
在build文件夹下的webpack.base.conf.js中配置,以下图,圈起来的是我在项目中配置的。
这样有配置后就可使用自定义目录了。好比按照我上面的配置的话
import src/assets/styles/border.css
就能够写成
import styles/border.css
了。
这里使用的是 vue-awesome-swiper。
先安装: npm install vue-awesome-swiper --save
而后用法一些的其实均可以在其文档中查阅到:
鉴于在各个页面均可能会用到轮播功能,因此直接在全局也就是入口文件 main.js 处引入。
而后使用:
好比要使用按钮区的话,就须要配置参数。根据我的在项目中的需求,能够查阅其github文档按需使用。
好比这个test。在网速慢慢加载的时候,可能test会先在上面显示,而后等图片撑开区域的时候再跑回下面。
为了防止这种抖动,最好这样子作:
给轮播swiper外面套一层类为wrapper的div,而后给div固定大小。好比在项目中这里的轮播图片的宽高比是 364:97 约等于 3.75,高度是宽度的百分之 26.6。
因此响应式开发能够这样给div框样式:
如今vw单位的兼容性其实能够了。
有种兼容性很好的方案:
overflow: hidden width: 100% height: 0 padding-bottom: 26.6%
这种方式也是高度是宽度的 26.6%。
其实吧。。这个vue-aowsome-swiper组件目前为止已经不存在这种抖动问题了。。
好比插件按钮区配置后,默认按钮颜色是蓝色小圆点。
审查元素能够看出:
那咱们以下这样子加样式去改变行吗?
通常这样子问都是不行滴...
由于有scoped做用域的缘由,这个类的属性的设置是在本来的 swiper组件下,而不是在咱们这里设置的swiper组件下。
应该这样设置:
意思是在.wrapper下的全部类中,找.swiper-pagination-bullet-active类。
>>>
是具备穿透做用域的意思,穿透其余组件的做用域。
好比,这里是个p标签。
P标签里的数据太多的话 但愿显示一个 ... 省略号。
能够这样利用text-overflow属性:
要实现溢出时产生省略号的效果,应该在定义两个样式:强制文本在一行内显示(white-space:nowrap)和溢出内容为隐藏(overflow:hidden),只有这样才能实现溢出文本显示为省略号效果。
通常状况下在mounted钩子里发送ajax请求数据。想详细了解生命周期 => 我有写过一篇文章
请求方式,看本身,这个项目中axios、fetch两个方式我都写过。
首先,用vue脚手架工具生成的工程里面,只有static目录(静态文件目录)下,才能被外界访问到。
咱们就把本地的一些模拟数据放在这个static目录下,本身建个文件夹存储数据。这个项目中是static/mock/index.json:
这数据是本地的模拟数据,咱们不但愿到时候一块儿把它push到线上,能够在.gitignore里这样配置:
如今这个文件夹下的全部东西都不会被传到线上了。
固然,也不会提交到本地的git仓库里面。
这样配置还不够,目前在局部根组件中写的请求的路径是这样的,拿项目中举例:
当咱们上线这代码的时候,咱们请求的网址,最好前面加上个‘api’,以下面的红框中:/api/index.json 这样子最好了。
很好的是,刚好Vue脚手架里面有这样一个转发的代理功能。经过这个功能,就能够实现以上构想。
config配置文件下,有个 index.js 脚本,官方给咱们提供了一个 proxyTable{} 的配置项,咱们能够这样配置:
这意思是:当咱们请求api的时候,依然映射到本地8080端口,而后访问任何以api为开头的url的时候,作一个路径替换,代理访问到 /static/mock 处。
实际这功能 是webpack-dev-sever提供的。
改过配置文件,须要重启下服务器,重启后就能够以下请求数据了:
这里实际上访问的就是static/mock/index.json里的内容了。
若是能够的话,最好能在局部根组件里请求一次ajax数据,而后从局部根组件里把接收到的数据分别传给各个局部的子组件,而不是每一个局部的子组件都发送一次ajax请求。
这里是这样写的css
如今在输入框里面输入文字字符超过输入框大小时:
这两部会贴着,不那么好看。想要给这个输入框加个padding,留点间隙会更好。
但直接在input下面加行吗?
页面:
由于包裹input框的div没设置width,也就是width是auto。input框的width设置的是100%。
若是直接给input加padding左右一点的话是会撑开input框的宽度的。因此会溢出。
那怎样解决这个问题呢?
咱们只是想设置一个左右padding值,没想让input框长宽变化。因此,咱们在 Input 下面加个:box-sizing: border-box
这样的话,咱们直接给input设置的宽高就包括了padding、border在内的宽高了。
此时咱们要修改padding的值的话,就只会在这个框内变化 不会撑开框宽高了。
初始开发页面时,到这步,由于加了比较多字母对应的区域,页面出现了滚动条的时候:
为了使用better-scroll库,咱们仅让列表区域显示到刚进页面时能显示到的区域就好了,不须要出现滚动条。因此能够给最外层的包裹整个列表区域的框div.list 加个overflow: hidden
就好了。(整个列表页指下图中的从当前城市开始到最后,城市选择和输入框是其余子组件写的了)
接下来具体better-scroll的用法,github上其文档有说明,各人可根据具体状况查阅使用。
点击事件中,咱们须要查看点击的内容时,能够利用点击事件的事件对象
在Vue的一个点击事件里,在methods定义点击方法时这个方法能够接收一个参数e,e就是咱们点击到的那个事件对象。
要拿到咱们点击到的事件对象的内容 能够这样来:e.target.innerText
举个项目中的例子验证一下:
好比此时页面上点击了 D F J
当点击到相应的字母的时候显示list组件的对应城市的区域。
better-scroll这个第三方插件有个方法能够实现这个需求,思路是:
监听所点击的字母表里字母的值letter的变化,一旦letter变了,就利用better-scroll的提供的一个接口,以下图划线的部分
它会让better-scroll的滚动区域,自动滚动到某一个元素上。须要给这个方法传递咱们滚动到该元素的该元素DOM。
利用这个思路就能够实现需求1了。
手指拖动字母表,字母对应的列表跟着联动展现。
思路:
利用touchstart、touchmove、touchend事件,并给个限制(touchStatus) 只当手指在屏幕移动的时候才执行一些操做。而后用个数组letters来存放字母表的全部字母,这里的letters大概是['A','B','C'...],并让页面v-for这个letters来显示相应的内容。用数组存放这些字母的缘由也是为了实现这需求的主要思想:根据下标,找到对应的字母。
接下来,先用offsetTop找到字母表中字母A距离包裹它的顶部的高度。下图红框。
这里的74 表明的是红色方框的高度。
而后获取移动时手指所在的高度,此高度时针对于客户端的高度,用clientY。
touchmove事件有个事件对象,事件对象里有个touches数组,touches[0]里面就有当前手指的信息,包括clientY属性。
实时获取咱们手指的位置。
咱们要获取距离包裹块的高度 => 也就是clientY的高度要减去headers区和serach区的高度,这两个区高度是 79px。
而后算咱们手指移到的字母在数组中的下标 逻辑是 <font color="#dd0000">(touchY - startY)/每一个字母的高度,再把结果向下取个整。</font>
最后,把这个下标在letters数组中对应的字母传给需求1所在的组件利用需求1的思路就好了。(这里的传值涉及到了兄弟组件之间的传值,此时该页面比较简单不建议用vuex,能够用event bus/找同一父组件作媒介传值,具体方法百度。)
在我项目中最终逻辑代码是这样写的:
最后作个最佳实践,用个if,确保 index的值。
第一处
handleTouchMove是手指滑动的时候就会执行,而咱们框起来的也就是A字母距离包裹框的高度是固定的,不用每次滑动的都执行这段代码。
因此此处须要优化,这样子来:
在data里初始化startY为0
而后用生命周期钩子 updated 去执行给startY赋值的语句
这里为何用updated这个钩子呢?在项目中初次渲染字母表组件alphabet.vue的时候,从它父组件City.vue传过来的值是一个空对象。当City.vue里ajax动态获取数据后,从City再传到alphabet的值让数据从初次的空对象发生改变。在数据更新完毕后,就触发了updated钩子,此时给startY赋值就是值都有,并且只会赋一次。
第二处:函数节流
经过函数节流 减小handleTouchMove()的执行频率 (由于咱们手指在滑动的时候 该函数执行频率很高的)。
怎样使得函数节流呢?
经过定时器和清除定时器来实现。
先在data中初始化timer为 null,而后这样来用
这样子用定时器进行函数节流的话 :
若是已经正在作这件事情的时候,我呢,让它延迟16ms以后再去执行。假设在这16ms之间你又去作了手指的滚动,那么它会把上一次你要作的操做给清除掉(clearTimeout),而后从新执行你此次要作的事情 (等于以最终的手指滑动的位置为准 )。
经过这种函数节流方式,会大大减小该函数的执行次数,从而提升网页性能。
函数节流的方式,当一个函数执行次数不少想要减小并且减小也没影响的时候,是颇有必要采用的一种方式。
可能用户会有不小的几率关闭了本地自动存储的功能,通常咱们使用localStorage的时候 都要使用 try catch 代码块,这样就算用户关闭本地自动存储功能,也不会让整个代码都不能运行,只是没了这个localStorage的功能而已。
举个项目中的例子: