新浦京娱乐场官网-301net-新浦京娱乐www.301net
做最好的网站

但是由于代码都是通过原生的 js

pwa重构北京大巴线路图

2018/03/28 · JavaScript · PWA

原版的书文出处: Neal   

事先一向有在维护贰个新加坡地铁线路图的 pwa,最入眼的特点正是 “offline first”。不过出于代码都以经过原生的 js 去达成,以前自个儿都不是很欢腾去用框架,不想有所任何框架的偏爱。不过到末代随着代码量的加多,代码的确变得混乱不堪,扩充新功效也变得更其困难。由此,花了相近七个礼拜的时候对于使用举办了贰回完整的重构。网址访谈地址:

准备

防患于未然干活先做好,在 vue 和 react 之间,笔者大概接纳了前面一个。基于 create-react-app 来搭建境况,crp 为你绸缪了三个开箱即用的开拓条件,因此你不供给和睦亲手配置 webpack,由此你也不需求产生一名 webpack 配置程序员了。

其他一边,大家还亟需一些数据,包罗站点音信,线路门路,文字表明等等。基于从前的应用,能够经过一小段的代码获取音讯。就此如要我们获得大家在此之前的站点在 svg 图中的相关属性,普通的站点使用 circle 成分,为了获取其性质:

const circles = document.querySelectorAll('circle'); let result = []; circles.forEach(circle => { let ele = { cx: circle.cx, cy: circle.cy, sroke: circle.stroke, id: circle.id }; result.push(ele); }) const str = JSON.stringify(result);

1
2
3
4
5
6
7
8
9
10
11
12
13
const circles = document.querySelectorAll('circle');
let result = [];
circles.forEach(circle => {
  let ele = {
    cx: circle.cx,
    cy: circle.cy,
    sroke: circle.stroke,
    id: circle.id
  };
  result.push(ele);
})
const str = JSON.stringify(result);
 

透过那样的代码大家就能够获得 svg 普通站点新闻,同理还可收获中间转播站新闻,线路渠道音信以及站点以及线路 label 音讯。还会有,我们还索要获得各个站点的时刻表消息,卫生间地点新闻,无障碍电梯音信以及出入口音讯。这里是写了一部分爬虫去官方网站爬取并做了一些多少管理,再度就不一一赘述。

设计

数量希图好之后,正是应用的谋算了。首先,对组件进行一次拆分:

零件结构

将全方位地图知道成贰个 Map 组件,再将其分为 4 个小零件:

图片 1

  • Label: 地图上的公文音信,包含地铁站名,线路名称
  • Station: 地铁站点,包括平日站点和转化站点
  • Line: 大巴线路
  • InfoCard: 状态最复杂的贰个零件,重要含一时刻表新闻、卫生间地方新闻、出入口新闻、无障碍电梯音讯

那是四个概况的零件划分,里面可能带有越多的别的成分,例如 InfoCard 就有 InfoCard => TimeSheet => TimesheetTable 那样的嵌套。

零件通讯和状态管理

地点开垦的最大的难关应该正是这一块的剧情了。本来出于组件的层级并不算极度复杂,所以本身并不图谋上 Redux 那体系型的大局状态管理库。首要组件之间的通讯正是老爹和儿子通讯和兄弟组件通讯。父子组件通讯比较轻巧,父组件的 state 即为子组件的 props,能够透过那一个达成父亲和儿子组件通讯。兄弟组件略为复杂性,兄弟组件通过分享父组件的状态来开展通讯。假诺那样的处境,小编点击站点,希望能够弹出新闻提示窗,那就是Station 组件和 InfoCard 组件之间的通讯,通过 Map 组件来进行分享。点击 Station 组件触发事件,通过回调更新 Map 组件状态的翻新,同临时间也落实了 InfoCard组件的立异。相同的时间为了落到实处,点击任何区域就足以关闭音讯提示窗,我们对 Map 组件进行监听,监听事件的冒泡来达成快速的关闭,当然为了幸免有个别不须求的冒泡,还索要在某事件管理中梗阻事件冒泡。

图片 2

Info卡德 是最最复杂的一个零部件,因为内部蕴含了几许个 icon,以及气象消息的切换,同期必要贯彻切换分化的站点的时候能够创新音讯提示窗。供给小心音讯提示窗音信初次点击消息的起初化,以及切换不相同icon 时分别显示不一致的新闻,比如卫生间音讯只怕出入口消息,以及对此时刻表,切换不一样的路径的时候更新对应的时刻表。那个情形的中间转播,须要值得注意。别的值得一题的点正是,在切换不一致站点的时候的情状,即使作者正在看有些站点的卫生间音讯的时候,小编点击别的三个站点,那时候弹出的新闻提醒窗应该是时刻表消息依旧卫生间音讯吗?小编的挑三拣四照旧卫生间消息,作者对此这一气象举行了维系,那样的客商体验从逻辑上来讲就像是更佳。具体完结的代码细节就不一一表明了,里面肯能满含越来越多的细节,招待使用体验。

属性优化

如上那么些的开销得益于以前的维护,所以重构进度依然相当的慢的,稍微熟知了下 react 的用法就做到了重构。不过,在上线之后采用 lighthouse 做深入分析,performan 的得分是 0 分。首屏渲染以及可相互得分都以 0 分,首先来深入分析一下。因为整个应用都以透过 js 来渲染,而最为基本的正是可怜 svg。整个看下去,有几点值得注意:

  • 代码直接将 json 导入,导致 js 体积过大
  • 具备组件都在渲染的时候举办加载

找到难题点,就足以想到一些施工方案了。第三个比较简单,压缩 json 数据,去除一些无需的新闻。第三个,好的化解办法正是透过异步加载来完成组件加载,效果明摆着,越发是对于 InfoCard 组件:

同步

class InfoCard extends React.Component { constructor(props) {    super(props) { ...    }  }  ... }

1
2
3
4
5
6
7
8
9
class InfoCard extends React.Component {
  constructor(props) {
   super(props) {
    ...
   }
 }
 ...
}
 

异步

export default function asyncInfoCard (importComp) { class InfoCard extends React.Component {    constructor(props) { super(props); this.state = { component: null }; } asyncComponentDidMount() { const { default: component } = await importComp(); this.setState({ component: component })    }  } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default function asyncInfoCard (importComp) {
  class InfoCard extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
        component: null
      };
    }
    
    asyncComponentDidMount() {
      const { default: component } = await importComp();
      this.setState({
        component: component
      })
   }
 }
}
 

如此我们就兑现了将一块组件退换成贰个异步加载的组件,那样就无需一下子加载全数的零部件。那样大家就足以在 Map 中接纳异步的秘技来扩充零部件的加载:

import asyncInfoCard from './InfoCard' const InfoCard = asyncInfoCard(() => import('./InfoCard')

1
2
3
import asyncInfoCard from './InfoCard'
const InfoCard = asyncInfoCard(() => import('./InfoCard')
 

通过上线之后的属性深入分析,lighthouse 性能评分一下子就回升到了 80 多分,申明那样的考订要么相比较实用的。别的三个值得说的点就是首屏,因为历史原因,整张图 svg 相月素的地方都以定死的,及横坐标和纵坐标皆已然是概念好的,而 svg 被定为在个中。在移动端加载时,呈现的正是左侧的空白区域,所以给顾客一种程序未加载达成的错觉。在此之前的本子的做法就是透过 scroll 来贯彻滚动条的滚动,将视图的症结移动到中间地方。这一次的主见是通过 transform 来实现:

.svg { transform: translate(-100px, -300px) }

1
2
3
.svg {
transform: translate(-100px, -300px)
}

如此落成了整整 svg 图地方的偏移,使用 lighthouse 实行分析,品质分降到了 70 多分。继续思量有未有其余的法子,后来小编想在最左上上角定义三个箭头动画。

img src="right_arrow.png" alt="right arrow" title="right arrow" class="right-arrow"/>

1
img src="right_arrow.png" alt="right arrow" title="right arrow" class="right-arrow"/>

.right-arrow { animation: moveright 3s linear infinite; } @keyframs moveright { 0% { transform: translateX(2rem); } 50% { transform: translateX(3rem); } 100% { transform: translateX(5rem); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.right-arrow {
  animation: moveright 3s linear infinite;
}
@keyframs moveright {
  0% {
    transform: translateX(2rem);
  }
  50% {
    transform: translateX(3rem);
  }
  100% {
    transform: translateX(5rem);
  }
}

图片 3

诸如此比大家就能够创设三个巡回向右移动的卡通片,提醒客户向右滑动。计划之后察觉品质分立马降到 0,索性也就放任了那些做法。最终来时间调控制选拔 transform: translateX(-200px) translateY(-300px); ,因为那样经过 css3 的本性能够在有些平移设备上仍可以使用 GPU 加速,而且 translateX 不会孳生页面包车型大巴重绘也许重排,只会促成图层重组,最小幸免对品质的熏陶。

部署

脚下的计划方案是行使 create-react-app 的合法提议,通过 gh-pages 实现将 build 的打包文件上传到 gh-pages 分支上进而达成安排。

兼容性

新葡萄京娱乐场8522 ,当下该利用在 Chrome 浏览器的援助性是最棒的,安卓浏览器建议设置 Chrome 浏览器选取,小编平时也都相比喜欢在手提式有线电话机上应用Google浏览器。对于 Safari 浏览器,另外的浏览效用就好像并未有何样大难点,前段时间应有还没支持增添到主荧屏。可是在之后的 ios 版本好像对于 pwa 有着更上一层楼的支撑。

结语

图片 4

花了两个礼拜的时间成功了类其他一体化的重构,从今年来的 commit 记录能够观望十二月份发狂 commit 了一波,重若是首先个周天花费了二日的光阴修改了大多代码,被非常 InfoCard的情事切换搞了非常久,后边即是对准质量做了有的优化。进程好疼楚,一度猜疑本人的 coding 手艺。然而最后如故有以下感悟:

  • 世界上未曾最佳的言语,最棒的框架,只有最合适的
  • 最优雅的完结都不是简单的,都以贰个个试出来的

末了一个冷笑话:

妙龄问禅师:“请问大师,笔者写的次序为何未有到手预期的出口?” 禅师答到:“年轻人,那是因为你的程序只会按您怎么写的实践,不会按您怎么想的推行啊……”

源代码地址,欢迎 star 或者 pr。

 

1 赞 收藏 评论

图片 5

本文由新浦京娱乐场官网-301net-新浦京娱乐www.301net发布于301net网站建设,转载请注明出处:但是由于代码都是通过原生的 js

您可能还会对下面的文章感兴趣: