项目总结
下面说一些我在写移动端项目时总结的经验:
- 我们知道移动端click点击事件有300ms延迟,为了正常使用click,需引入
fastClick这个库
在main.js编写如下代码:
300ms延迟由来
07年,苹果公司发布首款Iphone前夕,遇到一个问题:当时的网站都是为大屏设计,手机屏幕太小无法正常浏览,于是苹果工程师做了一些约定解决此类问题。
这些约定当中,最为有名的是双击缩放(double tap to zoom),这是产生300ms延迟的根源。
用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。如果用户在 iOS Safari
里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS
Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone
Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。 由此产生了300ms延迟问题。
解决方案:
方案一 禁用缩放
在html文档头部的meta标签中加入如下语句:
<!-- 1.禁用缩放 user-scalable=no -->
<meta name="viewport"
content="width=device-width, initial-scale=1.0,user-scalable=no">
user-scalable=no表明这个页面不可缩放,也就是浏览器禁用的双击缩放事件并且同时会去掉300ms点击延迟。
但这个方案也有缺点,就是完全禁用了双击缩放,当我们需要放大文字或者图片时无法满足我们的需求。
方案二 封装一个处理函数
//封装tap解决click 300ms 延时
function tap (obj,callback) {
var isMove = false;//记录手指是否移动
var startTime = 0;//记录手指触摸的时间
obj.addEventListener('touchstart',function(e){
startTime = Date.now();//记录触摸时间
})
obj.addEventListener('touchmove',function(e){
isMove = true;//查看手指是否滑动
})
obj.addEventListener('touchend',function(e){
if(!isMove && (Date.now()-statrTime) < 150){
callback && callback();
}
isMove = false;//取反 重置
startTime = 0;
})
};
tap(div,function(){ //执行代码 });
方案三 fastclick插件解决问题
FastClick 是 FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉。
import fastClick from 'fastclick'
fastClick.attach(document.body)
低版本安卓浏览器打开一片白
import 'babel-polyfill'
在移动端使用 100vh 导致页面出现滚动条的解决方法
但是如果在移动端使用某些浏览器,比如 iOS 的 Safari,就会出现纵向滚动条:
这是因为某些移动端浏览器在计算 vh 时,会将工具栏高度也计算进去,因此会出现滚动条,我们可以通过如下三种方案去尝试修复这个行为。
方案一:使用 -webkit-fill-available
-webkit-fill-available 是 webkit 浏览器独有的一个属性值,表示填充剩余可用空间,因此我们可以将 body 的 min-height 设置为该值,就可让 body 填充整个视口了:
方案二:使用 dvh
dvh 表示动态视口,是一个比较新的 CSS 单位。其可以动态的表示移动端浏览器的视口高度,比如当浏览器存在工具栏、地址栏时,其表示中间的小视口的高度;而当用户向下滑动,或者手动隐藏掉工具栏时,其表示的是隐藏掉栏框后的大视口高度:
作者:Esun_R
链接:juejin.cn/post/737350…
轮播图、横向滑动
- tab、图片放大滑动等这些使用
vue-awesome-swiper插件
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
Vue.use(VueAwesomeSwiper)
具体使用场景需参照文档配置option选项,这里不再赘述。
下面只阐述一点就是我们在使用插件时常常需要更改样式,比如改变轮播图下面小圆点的颜色。这里我们推荐使用样式穿透:
/deep/是sass和less的样式穿透
>>>是stylus的样式穿透
.wrapper >>> .swiper-pagination-bullet-active
background: #fff
.wrapper /deep/ .swiper-pagination-bullet-active {
background: #fff
}
css文件引入
- 当我们要引入不是其本文件跟目录下的 css 文件时,记得使用
'~@文件名'来简化'./../../....'这些相对路径。或者使用'~路径别名'
@import './../../../assets/css/mixin.scss';
//简化成功
@import '~@/assets/css/mixin.scss';
@import '~styles/varibles.scss'
- css常用相同模块内容可以提mixin提供多处使用,如:
@mixin omit {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
然后通过@include来调用具有相同名称的mixin模块
div {
@include omit;
}
容器占位
- 在css里面,
padding-top,padding-bottom,margin-top,margin-bottom取值为百分比的时候,参照的是父元素的宽度.这个小技巧好处有很多:
- 可以进行提前占位,避免资源加载时候的闪烁
- 还可以让高度自适应
在移动端或者在响应式开发情况下,我们可以利用这个特性来实现图片等比例缩放自适应。
解决核心思想为:提供一个容器,设置容器的高度为0,再设置padding-bottom为56.25%(需要自适应的元素高度除以宽度*100%)(因为padding的百分比是按照容器宽度计算的,所以由padding来撑开容器高度,而不是height,保证了容器的宽高比例)
<div class="wrapper">
<img class="swiper-img" />
</div>
.wrapper {
overflow: hidden
width: 100%
height: 0
padding-bottom: 31.25%
}
.swiper-img {
width: 100%
}
fixed 布局的元素可能会被键盘顶起
Vue 在移动端中使用,当弹出键盘时,fixed 布局的元素可能会被键盘顶起。
例子图示及解决方法参考:blog.csdn.net/qq_31929931…
- 移动端页面当滑动到底部时,路由跳转后发现页面还是保持在底部,这里可以在router中配置
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 }
}
-
项目打包后,manifest.js可以理解为webpack打包生成的配置文件, vendor.js各个页面各个组件公用的一些代码,app.js放的是项目各个页面的业务逻辑代码。app.js至少超过1M的时候才使用异步组件
-
使用keep-alive时有两个钩子函数:
mounted () {
this.lastCity = this.city
this.getHomeInfo() //ajax请求
},
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
}
- 有一个移动端很常见的效果,当滑动右边部分的时候,左边会联动显示与当前内容相符合的标题高亮,当点击左边某一个标题的时候,右边会自动滑动到相应的内容。左右联动效果,可以通过
better-scroll这个插件实现。另外,横向滚动的导航栏、竖向滚动的列表都可以通过这个插件来实现。
<template>
<!--定义外层-->
<div class="wrapper" ref="wrapper">
<!--定义需要滚动的内容区域-->
<ul class="content">
<li v-for="item in items">{{item.text}}</li>
</ul>
</div>
</template>
<script>
import BScroll from 'better-scroll'
export default {
mounted() {
this.$nextTick(() => {
this.scroll = new Bscroll(this.$refs.wrapper, {})
})
},
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
this.scroll.scrollToElement(element)
}
}
},
}
</script>
样式这里需要注意的是,要滚动的这一部分给了固定的高度,且超出部分overflow:hidden;
.wrapper {
overflow: hidden
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
}
另外附上better-scroll原作者的文章:www.imooc.com/article/182…
- 我们做好的项目,如何在移动端进行调试呢?
我们发现,vue项目是用webpack-dev-server这个服务器跑起来的,这个服务器默认外部是无法访问的,需在package.json中加入--host 0.0.0.0才行:
更改后的配置如下:
"scripts": {
"dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js",
},
vuecli3.0
对于vuecli3.0的项目,可以采用如下配置:
devServer: {
host: '0.0.0.0',
proxy: {
"/api": {
target: "https://xxxxx",
secure: false,
changeOrigin: true
}
}
},
这样的话,在命令行运行ipconfig,手机和电脑连接同一局域网,用手机访问电脑的ip地址就可以用真机打开啦