单页SPA应用逻辑架构

#### 1. 前言
单页H5现在依然是`H5`的一个重要表现形式,尤其是在一些创意H5中;

那你有没有想过,怎么配置结构,才能让你的单页应用在开发中,更优层次感,更解耦?

我们本篇就来说一个概念,既然是概念的话,就表示,你不使用本篇内容依然可以完成,甚至很好的完成。

接下来,我们就以懒加载和预加载来举例;

#### 2. 懒加载与预加载
为什么要懒加载,又为什么要预加载呢?这两个概念难道不是冲突的么?

一句话简单介绍这两个概念:

懒加载:当使用到的时候,才去加载资源和数据;
预加载:当还没有使用到的时候,就提前去加载资源和数据;

从概念上来讲,这是完成相反的概念;但是两者都是为了能有更好的体验,懒加载可以防止你页面加载资源过多,而导致页面在首次加载时,处于假死状态。而预加载,就是防止,当你操作交互时,页面出现因资源下载导致的空白;

所以,在这个时候,就要好好的把握这个度的问题,即懒加载的同时,也要实现预加载;

这里,希望你可以先想想,你是如何实现懒加载和预加载的呢?

#### 3. 创意H5的SPA应用

创意`H5`的一些特点:
1. 页面很多
2. 每页的操作不同
3. 图片量多
4. 特殊字体多(服务器字体)
5. 动画特别多

或者还有其他的一些因素,这里我也就不一一的列举;

这些因素,都会在不同的方面,影响着整个`H5`的性能和体验,在之后的文章中,会慢慢进行说明,这里呢,我们就主要拿图片懒加载和预加载这个示例来说明一个思想,如何更好的控制懒加载和预加载,甚至更多其他的操作;

首先,我们做以下假设:
1. 页面很多
2. 页面之间的跳转顺序不固定
3. 每个页面有很多图片,包含背景图和`img`标签
4. 所有的`img`标签,图片地址暂存在`data-src`属性上

我们的目标:
1. 页面刚打开的时候,默认加载第一页的资源,然后预加载有可能的第二页资源;
2. 代码解耦,对于非第一页的资源,当前页,并不知道那个页面,会有可能跳转到当前页面,即我不知道我从哪里来,但是我知道我可能去哪里;

那么假设我们的HTML结构布局如下:

“`html

“`

这里,每页都有一个以 “`love-index.jpg`” 命名的图片,以及一个跳转按钮;
以及,所有的页面相关的信息,都是配置在了`data-page`这个属性上面;

那么我们先看看,我们平时会碰到的情况有哪些呢?
1. 当本页显示的时候,期望下一页的内容,可以提前加载好
2. 当本页显示的时候,如果本页可以跳转到多个页面,那就把多个页面的内容,预先加载;

所以,现在来直接看下面的示例吧:
示例1:[按照顺序进行加载DEMO](/study/2019/20190114/index-1.html)
示例2:[预加载多个页面DEMO](/study/2019/20190114/index-2.html)

这里,先去看DEMO,接下来再讲原理

从上面的DEMO中,在页面上有个`lazyLoadCenter`对象;它包含:`add`,`next`,`toPage`等方法;

如果你想把某个页面,添加到预加载的列表中去,那么可以:

“`javascript
// page-1
var page1 = page.eq(0);
lazyLoadCenter.add({
pageName: “pageName”,
fn: function(){
var img = page1.find(“.img”);
img.attr(“src”, img.attr(“data-src”));
}
});
“`

这里,你只需要对本页使用一个:`lazyLoadCenter.add`注册一下,就可以了,而在`fn`中,只需要把本页需要处理的懒加载,处理一下,完全不用管另外的页面;

至于使用,这里就要做一下区分了,首先:如果页面是一条路走到底的,即:页面的显示顺序是不变的,那么可以直接使用`lazyLoadCenter.next()`;直接调用,只要你保证`lazyLoadCenter.add`的顺序就OK了;

还有不少页面,是可能分叉的,即:一个页面有可能跳转到多个页面去,比如:A页面就有B、C页面的入口,这个时候,就需要`lazyLoadCenter.toPage(pageName)`跳转到指定页面了,传入的`pageName`就是注册时的`pageName`;

> 这里现在,还有一个问题,就是`lazyLoadCenter.next`和`lazyLoadCenter.toPage`不同在同一个`SPA`项目中使用,会出现乱序的情况,暂时我还没有想到好的解决方法,所以就遗留在这里吧。

后面说的不清楚,建议还是以前面的demo中的示例为准,如有不理解可以留言讨论。

#### 4. 优势

这样的写法,其目的就是为了:页面之间的逻辑操作解耦,在页面之间,只有一个`pageName`是需要知道的,你只要知道,你下一步跳转到`pageName`是什么,就可以对该页面,进行预加载了,而完全不需要管,它是如何预加载的;

这样,当你再开发一个页面的时候,就可能会出现以下的结构:
// 首页的逻辑

“`
(function(){

//
//

//
//

// 首页的预加载
var wrapper = $(“.page-index”);
lazyLoadCenter.add({
pageName: wrapper.attr(“data-page”),
fn: function(){
var img = wrapper.find(“.img”);
img.attr(“src”, img.attr(“data-src”));
}
});
})();

// 第二页的逻辑
(function(){

//
//

//
//

// 第二页的预加载
var wrapper = $(“.page-2″);
lazyLoadCenter.add({
pageName: wrapper.attr(“data-page”),
fn: function(){
var img = wrapper.find(“.img”);
img.attr(“src”, img.attr(“data-src”));
}
});
})();
“`

在开发和维护上的好处:
1. 代码结构清晰
2. 每一页之间的逻辑,完全解耦
3. 其他人理解简单,那一页出问题,就可以专心看那一页的代码
4. 维护更方便

#### 总结
虽然最终写到了这里,但是总觉得有些东西没有说出来,很久不怎么写文章了,感觉表达能力又下降了,希望可以从代码中,理解我想说的思路;

这不止在懒加载中可以如此,还有很多的功能也可以这样做,在之后的文章中,会进行一些说明,希望把这部分能力,最终可以写出一个系列的文章。

感谢阅读,如有问题,欢迎指正讨论;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>