没错,我用Vue写了一个H5项目,来看下我踩坑记录吧。
1、按需引入
在开发过程中,会遇到很多五花八门的库。其实这些库中有很多功能/模块是用不到的,所以,这里推荐按需引入:
import { Slider } from 'element-ui';
Vue.use(Slider);
- 1
- 2
- 3
像这样,如果只用到滑条,只需引入Slider,并挂载到Vue实例。
2、全局样式抽离
Css样式在前端开发中是绕不开的话题,以Vue开发为例,每个.vue文件都有自己的局部样式scoped,但是全局性的样式可以抽离到一个统一的文件(main.css),大概有以下四种情况:
- 项目中的特有颜色(其他类比),它会在不同的地方出现
- 全局的组件样式,比如对滚动条颜色的控制
- 对一些引用的公共组件的定制化样式
- 单个维度的样式,比如
.fl{ float: left }
然后样式文件在项目入口引入:
import 'assets/css/main.css';
- 1
3、统一的页面入口
用Vue开发的话,如果配置好路由,其实页面之间大可以独立运行。但是项目越来越复杂,交互越多,就更需要一个统一的入口,这样可以统一控制事件监听、处理公共组件(比如Toast)等等。所以,咱们需要一个App.vue,代码如下:
<template>
<div class="page">
<router-view class="page-content"></router-view>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
// TODO
};
},
};
</script>
<style lang="scss" scoped>
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
然后,在Vue实例化的时候把它作为选项传入:
import App from 'modules/App.vue';
new Vue({
router,
...App
}).$mount(`#app-wrapper`);
- 1
- 2
- 3
- 4
- 5
最后,页面的跳转都会在App.vue内,一切尽在掌握。
4、缓存
听到业务需求说要做持久化我是懵逼的,不过后来理解他们的意思就是做个缓存,那就简单了,哈哈。Vue有提供keep-alive组件:
<template>
<div class="page">
<keep-alive>
<router-view class="page-content"></router-view>
</keep-alive>
</div>
</template>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在上一节的基础上,加上这个组件包裹它就行了。原理就是它会缓存不活动的组件,而不是销毁它。详情可以参见 keep-alive api,官方有详细的解释。
5、监听移动设备的横屏事件
如果是用RN开发,可以调用接口来监听横屏事件,H5的话,Js有没有接口可以给你调用,但是可以监听事件,通过监听orientationchange事件,可以监听横屏动作,然后通过Orientation来获取当前角度:
window.addEventListener( "orientationchange", () => {
let angle = window.orientation;
if(angle % 180 != 0){
// TODO
} else {
// TODO
}
// TODO
}, false);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
根据上一节说的App.vue,这个监听事件就可以放在其中,然后向其他组件广播。
6、不同组件间通信
那么,如何向其他组件广播?如果是父子,子父这种的,都好说。但是,如果是多层级的组件间通信就不好处理了,这里推荐一种网上广为流传的方法,借用Vue实例,把它作为中间方,在各组件中注册或者监听事件。直接看代码:
// inner.js
import Vue from 'vue';
const bus = new Vue();
export {bus};
- 1
- 2
- 3
- 4
- 5
- 6
在inner.js中,new 一个Vue实例,然后,可以这样监听事件:
import {bus} from 'common/utils/inner';
bus.$on('my_event', (bool) => {
// TODO
});
- 1
- 2
- 3
- 4
- 5
广播事件:
import {bus} from 'common/utils/inner';
bus.$emit('my_event', {});
- 1
- 2
- 3
这样一来,就不用管什么层级关系了,都是广播的对象。
7、简单实现Dom拖动
如果不想引用其他库的话,可以自己实现一个移动的Dom,原理就是监听touchmove事件,然后改变它的top/left值:
document.getElementById("toolbar").addEventListener('touchmove', (e) => {
e.stopPropagation();
e.preventDefault();
let y = e.touches[0].clientY;
let height = window.screen.height;
if(y > height) {
y = height;
} else if (y < 0) {
y = 0;
}
document.getElementById("toolbar").style.top = y + "px";
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
不依赖任何插件,达到手指拖动toolbar的效果(这里只是让toolbar在Y轴上拖动,所以只改了它的top值)。注意要把冒泡和默认事件禁止掉,不然会影响其他模块。
8、禁止页面被拖动
H5开发会有很多问题,有些时候客户想拖动的只是某个区域,但是整个页面都会随之拖动,那就把它禁了吧,很简单:
document.getElementById("page").addEventListener('touchmove', function(e) {
e.preventDefault();
}, {passive: false});
- 1
- 2
- 3
对于Vue页面来说,把它的顶部Dom禁掉就可以了,这样页面就不会有拖动的效果。
9、Ios设备下的特定样式
通常,H5开发都会遇到适配问题,特别是Iphone下,同一套样式Iphone和安卓下效果的就是会有区别。所以,我们需要判断Iphone,并给它配置特定样式,代码如下:
const isIos = () => {
var ua = navigator.userAgent.toLowerCase();
if (/iphone|ipad|ipod/g.test(ua)) {
return true;
} else {
return false;
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
其实原理就是通过UserAgent去判断这个设备是否是Ios设备,如果是,就把相应的样式引用进来,如下:
if(isIos()) { //是ios系统
require('assets/css/ios.scss');
}
- 1
- 2
- 3
这样就能达到根据设备配置指定样式。
10、调用引用组件的内部方法
在Vue项目已经组件化之后,经常会面临一个很常见的问题,调用组件的内部方法。其实很简单,通过Ref就可以实现:
<my-comp ref="myRef"> </my-comp>
- 1
在给引用的组件加上ref之后,在代码中去调用就行了。
this.$refs.myRef.fun();
- 1
这样就不用去传Props触发了。
11、下载文件
这个功能其实涉及到前后端的配合,如果你想下载一个文件,首先需要这个文件存在,或者是先生成,然后再获取路径下载。这是比较常规的方式了。以Excel文件为例,后台要根据业务生成Excel文件:
static async createDownloadFile(data) {
try {
let xls = json2xls(data);
let fileName = `file.xlsx`;
await fs.writeFileSync(`./dist/${fileName}`, xls, 'binary');
return fileName;
} catch (err) {
logger.error(`createDownloadFile error is : ${err && err.message || ''}`);
return;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
nodejs实现一个Excel文件下载就是这样,把文件放到服务器指定目录,将文件名称返回到前端,前端去下载。
<a :href="downloadUri" download >保存到本地</a>
- 1
downloadUri就是拼接好的文件路径,然后别忘记加上download属性,这个属性在移动端大部分浏览器内核是支持的,但是,IE浏览器不支持(Safari浏览器也不支持,但是实测是可以下载的),没关系,它是移动端,哈哈。
12、动画效果
有些时候,整个项目交互没有点动画过渡会显的很沉重,所以,还是加点动画吧。手写吗?我知道要定义keyframes,然后设置animation之类的,但是这个东西我还是推荐使用一个库: animation. 非常轻量,就是一个css文件。使用的时候也很简单:
<div class="animated fadeOutDown" > </div>
- 1
像这样写样式就可以了。
13、表格
什么,要加表格?还是可以固定列,自定义的那种?我反手就是Element-ui表格,哈哈,完成。
巨坑啊,
Element-ui并不适合在移动端用,前期适配完之后,发现非常卡顿,最后发现是它的数据结构的问题,可折叠表格的数据结构就是子母嵌套的,数据量一上来,渲染过程就会页面卡死。不推荐。
这里推荐一个小众的组件: vue-easytable,功能都有主要是不卡,然后,把数据结构换成平级的,层级用样式实现。大概就是这个意思:
[
{
id: -1,
children: [
{
id: -1.1,
}
]
},
{
id: 2,
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
换成这样:
[
{
id: -1,
},
{
id: -1.1,
},
{
id: 2,
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
通过自定义属性来设置样式,达到不同层级缩进效果。
最后
今天我看到鱿鱼须在VueConf的演讲了,Vue3.0用的是Typescript写的,想想微软还是强大,这种类Java的语言也能被他搞的这么火,吓得我赶紧去看下Typescript。前端变化真快~