PC端和移动端需要同时上线图表功能(没有多余工时)
之后的版本迭代(功能、样式、配置等)默认双端同步,开发人员只希望维护一套代码
Echarts在移动端有部分功能不兼容不支持
① 移动端页面使用echarts4 中的地图组件,并添加省份的点击事件,响应click无效,eharts也不支持tap事件。
解决方法:自己代理echarts组件实例的click事件。或更新到echarts5版本
②地图组件有数据的省份高亮状态点击后消失。
解决方法:劫持点击事件做判断
③dataZoom失效
- dataZoom:{
- type: 'inside',
- start: 0,
- end: 50,
- },
解决方法:把传入的对象参数改成数组
- dataZoom:[
- {
- type: 'inside',
- start: 0,
- end: 50,
- }
- ],
④ 图表组件的datazoom会阻碍页面的原生滑动事件,导致页面没办法正确上下滑。
解决方法:添加preventDefaultMouseMove属性为false
⑤datazoom为inside时,多个图表在移动端上滑动失效
解决方法:更新到最新版本echarts,但是还是会有部分机型存在这个问题
我们可以看到Echarts在移动端上还是存在很多不兼容的地方。而且Echarts官网时挂着的example都是PC端上的。为了避免各种坑爹问题,我在项目中还是选择了多端为一端的开发方案。
核心思想就是通过Iframe让移动端的页面直接渲染PC的网页,同时微调一些样式以适配移动端的小屏。
这部分不是重点,因为页面用的还是PC端的页面。只需要调整部分样式大小就好。主要解决一个留存问题就是Iframe里面图表的内部滑动会影响移动端的页面滑动。
- <mobileTouchView @touchInfo="updateTouchInfo" :touchRecord="true">
- <...>
- <m-dashboard-runtime-item
- v-for="item in layout"
- :key="item.pkId"
- :layout="item"
- :field="fieldMap[item.pkId]"
- />
-
- mobileTouchView>
解决方法是套了个自定义的滑动层,并监听会出问题的几个操作
- <template>
- <div
- :class="$style.mobileTouchView"
- @touchstart="proxyStart"
- @touchmove="proxyMove"
- @touchend="proxyEnd"
- @touchcancel="proxyCancel"
- >
- <slot>slot>
- div>
- template>
核心思想是计算touch起点和终点的screenY/screenX的偏离来确定用户手势。具体可以看我的另外一篇推文。
代码分为两部分
-
class="dashboard-page"> - ....
-
- <view class="content" :class="{ showFilter: filterFields.length > 0 }">
- <iframe
- v-if="iframeUrl"
- ref="iframe"
- class="webview"
- :src="iframeUrl"
- >iframe>
-
- <x-abnormal v-else :text="tips" class="tips" />
- view>
很简单的一个移动端页面中间嵌套了一个iframe页面
- async getFormData() {
- ....
- await this.$nextTick();
- this.$refs.iframe &&
- this.$refs.iframe.addEventListener('load', e => this.handleIframeLoad(e));
- }
同时监听PC端发过来的讯息
- // iframe加载完成
- handleIframeLoad(e) {
- // 先打开对PC讯息的监听器
- window.addEventListener('message', this.messageGateway);
- // 对PC建立握手
- this.handShake(5);
- }
这里为什么要握手五次?其实这里可以填大一点。因为单方无法知道连接是否成功。 所以每500毫秒重新握手一次,直到收到回复。
- handShake(t = 0) {
- if (this.connected || t < 1) {
- return;
- }
- // console.log('mobile: 开始建立握手');
- this.$refs.iframe.contentWindow.postMessage({
- type: 'ping',
- data: {timeStamp:this.currentTime},
- }, '*');
- setTimeout(() => {
- this.handShake((t -= 1));
- }, 500);
- }
收到回复后把this.connected改成true就好了
PC上通过监听message来捕抓移动端发送过来的讯息
- created() {
- window.addEventListener('message', e => this.messageGateway(e));
- }
这里可以过滤一下域名:
- get allowOrigin() {
- return ['localhost:8080', 'm.xxx.com', 'mobile.xxx.com'];
- }
-
- messageGateway(e) {
- const findIndex = this.allowOrigin.findIndex(item =>
- e.origin.includes(item),
- );
- if (findIndex > -1) {
- ...
- }
- }
在移动端打开PC端的Iframe页面,需要传入token来验证登录状态和身份权限。
- get iframeUrl() {
- return `${createModuleUrl('app')}/m-dashboard/${this.formId}?token=${
- this.token
- }`;
- }
iframe页面验证token后通过路由跳转到页面
- const routes = [
- ...,
- {
- path: '/m-dashboard/:formId',
- component: () => import('@/views/dashboard/mobile')
- },
- ]