原生开发移动web单页面(step by step)6——history api应用

简介: 以上几篇的内容成功的将多页面合成到单页面上,然而还是有很多区别的, 多页面切换的时候,通过浏览器的自带后退前进键可以进行导航,然而到目前为止,是没有办法进行的导航的,这一篇主要是引入了这个功能。

以上几篇的内容成功的将多页面合成到单页面上,然而还是有很多区别的, 多页面切换的时候,通过浏览器的自带后退前进键可以进行导航,然而到目前为止,是没有办法进行的导航的,这一篇主要是引入了这个功能。

在进入正题之前,我们还需要对整体做一下调整, 一般情况下, 一个页面分为两个部分,一部分是静态部分,只要起到布局作用,还有一部分为改变部分,主要用来切换页面的作用。在布局中设置一块改动的区域,放置动态页面, 不同的动态页面调用静态部分提供的方法来调整不同的布局。 这样的结构如下图所示。

界面的布局

这里的做法就是让静态布局部分和动态部分都是Page实例对象,通过App的实例对象初始化并渲染首页,如以下代码:

app.initialize(staticPage, indexPage);

切换页面的代码与之前的一样, 介绍了这个后,接下来介绍history api。

浏览器history记录是类似一个数组, 通过一个索引值代表当前的页面,如果按后退键,将会索引值减一, 跳到之前的页面,按前进键则相反,如下图所示。


history栈

浏览器history api提供了两个方法来操作这个历史数据的数组: pushState和replaceState。 pushState方法的作用为在当前页面所在的索引值插入一个新的记录,然后移除所有后面的记录,与用户单击一个链接大致相同, 并将历史的索引值转到新的记录。如下图所示


pushState操作

replaceState方法的作用为替换当前的记录,不影响历史记录数组中其它数据的更改,如下图所示


replaceState操作

当点击浏览器的前进后退键的时候,就会触发popstate的事件, 通过监听事件获取到的历史数组中状态的改变而动态更改页面,调用history的方法也会触发popstate事件。
下面介绍了如何把它集成到App对象中,App构造函数的代码如下

function App() {
    this.currentPage = null;
    this.staticPage = null;
    this.pageContainer = null;
    this.routeObj = {};
}

staticPage存放静态布局页面,可以调用其方法更改外部布局
pageContainer是可变页面的容器
routeObj对象放置页面对象,key代表页面的url, value为Page对象
nitialize方法代码如下

initialize: function (staticPage, indexPage) {
    staticPage = this.staticPage = staticPage || App.emptyPage;
    var that = this;

    staticPage.render(function (html) {
        var body = document.body;
        body.insertAdjacentHTML("afterbegin", html);
        staticPage._initialize(body);
        if (staticPage.domList.pageContainer) {
            that.pageContainer = staticPage.domList.pageContainer;
        }
        else {
            console.error("staticPage must have pageContainer");
        }
        that.render(indexPage, true);

        window.addEventListener("popstate", function (ev) {
            if (ev.state && ev.state.data) {
                var url = ev.state.data;
                var page = that.routeObj[url];
                that._renderPage(page);
            }
        }, false);
    });
},

这里需要静态布局页面有个PageContainer,让动态页面放置。
_attachHistory方法的代码如下

_attachHistory: function (page, isBack) {
    var newUrl =  page.url;
    
    if (isBack) {
        history.replaceState({data: newUrl}, "", newUrl);
    }
    else {
        history.pushState({data: newUrl}, "", newUrl);
    }
},

_renderPage方法的代码如下

_renderPage: function (page) {
    if (this.currentPage) this.currentPage._dispose();
    this.currentPage = page;
    page.app = this;

    document.title = page.title;
    var pageContainer = this.pageContainer;
    page.render(function (html) {
        pageContainer.innerHTML = html;
        page._initialize(pageContainer);
    });
}

修改Page构造函数与App.createPage函数
Page构造函数如下

function Page(title, url) {
    this.title = title;
    this.url = url;
    this.domList = {};
    this.eventList = [];
}

App.createPage代码如下

App.createPage = function (title, url, options) {
    var page = new Page(title, url);
    App.extend(page, options);
    return page;
}

然后对应创建一个App.emptyPage, 代码如下

App.emptyPage = App.createPage("", "", {
    render: function (fn) {
        fn("<div class='pageContainer'></div>");
    },
    getDomObj: function (dom) {
        this.attachDom(".pageContainer", "pageContainer", dom);
    }
});

修改entry.js, login.js, register.js和goal.js,定义各自Page实例对象的时候,增加url的字段,
分别为/serve/entry, /serve/login, /serve/register和/serve/goal, 以serve开头的,是为了页面刷新的时候,服务器检索到url以/serve开头,然后跳转到首页。

更改提供后台服务页面的serverFile.js修改exports.getFile方法,代码如下

exports.getFile = function (req, res, key, root) {
    if (key.indexOf("/public/")  === 0) {
        serveFile(req, res, root + key, root);
    }
    else if (key.indexOf("/serve") === 0) {
        serveFile(req, res, root + "/public/serve/index.html", root);
    }
    else {
        res.statusCode = 404;
        res.end("404");
    }
}

修改index.js的代码,如下

var app = new App();
app.initialize(null, entryPage);

如果想要刷新跳到当前页面,那就需要在类似在sessionStorage的存储机制中存放当前的页面url,然后在初始化的时候,将entryPage替换为该url的page对象即可。

总结: 加入history api后,页面表现和普通的多页面相差无几了,可以跳转, 可以后退。 改变页面后title和url也随着改变,刷新直接跳到首页也可以跳到当前页。到了这篇为止,单页面改造完毕,然而,单页面的灵活性远非多页面可比的, 如果处理得到,复杂性却不会增加很多。 接下来的篇章就是为了让单页面更加出彩, 甚至达到原生app的水准。

后续更新:下一篇将重点介绍css3的animation, 配合页面切换, 让页面切换动态化。css3的animation模块在后面的部分使用的非常频繁,为理解后面的代码做一下基础。

案例链接


原生开发移动web单页面(step by step)1——传统页面的开发
原生开发移动web单页面(step by step)2——Page对象
原生开发移动web单页面(step by step)3——App对象
原生开发移动web单页面(step by step)4——tap事件与slide事件
原生开发移动web单页面(step by step)5——nodejs服务器的搭建

相关文章
|
17天前
|
自然语言处理 Java 数据库连接
掌握JSP页面编程:动态生成Web内容
【4月更文挑战第3天】Java Server Pages (JSP) 是一种用于创建动态Web内容的Java技术,它结合HTML并允许在页面中嵌入Java代码。JSP支持代码片段、表达式语言(EL)和JSTL标签库,简化动态内容生成。当服务器接收到请求时,执行JSP中的Java代码并将结果嵌入HTML返回给客户端。示例展示了如何显示当前日期和时间。JSP可与Servlet、JavaBeans、数据库等结合,用于构建功能丰富的交互式Web应用。
掌握JSP页面编程:动态生成Web内容
|
25天前
|
机器学习/深度学习 人工智能 前端开发
机器学习PAI常见问题之web ui 项目启动后页面打不开如何解决
PAI(平台为智能,Platform for Artificial Intelligence)是阿里云提供的一个全面的人工智能开发平台,旨在为开发者提供机器学习、深度学习等人工智能技术的模型训练、优化和部署服务。以下是PAI平台使用中的一些常见问题及其答案汇总,帮助用户解决在使用过程中遇到的问题。
|
1月前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
解释如何在 Python 中实现 Web 服务(RESTful API)。
25 0
|
7天前
|
小程序 前端开发 API
小程序全栈开发中的RESTful API设计
【4月更文挑战第12天】本文探讨了小程序全栈开发中的RESTful API设计,旨在帮助开发者理解和掌握相关技术。RESTful API基于REST架构风格,利用HTTP协议进行数据交互,遵循URI、客户端-服务器架构、无状态通信、标准HTTP方法和资源表述等原则。在小程序开发中,通过资源建模、设计API接口、定义资源表述及实现接口,实现前后端高效分离,提升开发效率和代码质量。小程序前端利用微信API与后端交互,确保数据流通。掌握这些实践将优化小程序全栈开发。
|
17天前
|
前端开发 Java API
构建RESTful API:Java中的RESTful服务开发
【4月更文挑战第3天】本文介绍了在Java环境中构建RESTful API的重要性及方法。遵循REST原则,利用HTTP方法处理资源,实现CRUD操作。在Java中,常用框架如Spring MVC简化了RESTful服务开发,包括定义资源、设计表示层、实现CRUD、考虑安全性、文档和测试。通过Spring MVC示例展示了创建RESTful服务的步骤,强调了其在现代Web服务开发中的关键角色,有助于提升互操作性和用户体验。
构建RESTful API:Java中的RESTful服务开发
|
21天前
|
机器学习/深度学习 前端开发 API
实现以图搜货功能,淘宝API开发实战分享
实现以图搜货功能,淘宝API开发实战分享
24 0
|
29天前
|
缓存 前端开发 API
构建高效可扩展的RESTful API:后端开发的最佳实践
【2月更文挑战第30天】 在现代Web应用和服务端架构中,RESTful API已成为连接前端与后端、实现服务间通信的重要接口。本文将探讨构建一个高效且可扩展的RESTful API的关键步骤和最佳实践,包括设计原则、性能优化、安全性考虑以及错误处理机制。通过这些实践,开发者可以确保API的健壮性、易用性和未来的可维护性。
|
1月前
|
XML JSON API
通过Flask框架创建灵活的、可扩展的Web Restful API服务
通过Flask框架创建灵活的、可扩展的Web Restful API服务
|
1月前
|
缓存 监控 API
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
Python Web框架FastAPI——一个比Flask和Tornada更高性能的API框架
57 0