Fork me on GitHub

移动前端开发-单页应用(spa)模型

一门新的技术诞生总会引来一番争议,单页Web应用程序也不例外,其最大的优势在于用户体验,对于内容的改动不需要加载整个页面;对服务器压力很小,消耗更少的带宽,与面向服务的架构更好地结合。使用HTML+CSS+JavaScript编写应用程序,能使更多的开发者都加入到程序开发的行列。

单页面应用是指用户通过浏览器加载独立的HTML页面并且无需离开此导航页面,这也是其独特的优势所在。对用户操作来说,一旦加载和执行单个页面应用程序通常会有更多的响应,这就需要返回到后端Web服务器,而单页面应用为用户提供了更接近一个本地移动或桌面应用程序的体验。

单页Web应用程序的优点:

  1. 首先,最大的好处是用户体验,对于内容的改动不需要加载整个页面。这样做好处颇多,因为数据层和UI的分离,可以重新编写一个原生的移动设备应用程序而不用(对原有数据服务部分)大动干戈。
  2. 单页面Web应用层程序最根本的优点是高效。它对服务器压力很小,消耗更少的带宽,能够与面向服务的架构更好地结合。 

在艾伦项带领的项目组工作也有一年多了,他实现了一套非常完整的单页应用框架。非常复杂,到今天我也还没有理清里边的所有实现。

下面请允许我展示一下这个应用的结果

 看起来和原生应用程序没有什么两样吧。于是呢,我就做了一个简单的模型,和往常一样,只是用来演示原理。

下面发一下我的模型图:

虽然样子是丑陋了一点,但是用来学习刚刚好,下面看一下具体的javascript代码:

/*
 * Swipe 2.0
 * @author bjtqti
 * @description 基于javascript的单页应用
 * Copyright 2014, MIT License
 *
*/

function Swipe(container, options) {

  "use strict";

  // quit if no root element
  if (!container) return;
  options = options || {};
  this.container = container;
  //页面数据
  this.pages = options.pages||[];
  this.pointer = {};
  //设备屏宽
  this.screenWidth = 640;
  this.init();
}

Swipe.prototype = {

    //初始化
    init : function(){
      var maxLen = this.pages.length;
      var index =  Number(localStorage.getItem('index'))||0;
      var next,prev;
      if(!maxLen) return;
      //创建页面基础元素
      this.createLeftButton();
      this.createSwipeWrap();
      this.createRightButton();
      //缓存页码索引信息
      this.curIndex = index;
      this.maxLen = maxLen;
      this.pointer.cur = this.createPage(index);

      if(maxLen ==1) return;

      switch(index){
        case 0:
          next = this.createPage(index+1);
          break;
        case maxLen -1:
          prev = this.createPage(index-1);
          break;
        default:
          prev = this.createPage(index-1);
          next = this.createPage(index+1);
      }
      this.pointer.next = next;
      this.pointer.prev = prev;
      next && this.move(next,this.screenWidth);
      prev && this.move(prev,-this.screenWidth);
    },

    //创建翻页容器
    createSwipeWrap : function(){
      var ele = document.createElement('ul');
      ele.className = "xut-container";
      this.container.appendChild(ele);
      this.box = ele;
    },

    //创建左翻页按钮
    createLeftButton : function(){
      var that = this;
      this.createBtn({
        name : "xut-left",
        text : "<",
        fn   : function(){
          that.prev();
        }
      })
    },

    //创建右翻页按钮
    createRightButton : function(){
      var that = this;
      this.createBtn({
        name : "xut-right",
        text : ">",
        fn   : function(){
          that.next();
        }
      })
    },

    //创建按钮
    createBtn : function(options){
      var ele = document.createElement('div');
      ele.className = options.name;
      ele.innerHTML = options.text;
      this.container.appendChild(ele);
      ele.addEventListener('click',options.fn,false);
      return ele;
    },

    //创建页面
    createPage : function(index){
      var li = document.createElement('li');
      li.setAttribute('class','xut-flip');
      li.innerHTML = index;
      //这里可以进行自由扩展,数据从this.pages添加
      this.box.appendChild(li);
      return li;
    },

    //上一页
    prev : function(){
      if(this.curIndex > 0){
        var prev = this.pointer.prev;
        var cur  = this.pointer.cur;
        this.curIndex--;
        //当前页移到右边
        this.slide(cur,this.screenWidth);
        //上一页移到中间
        this.slide(prev,0);
        //清除下下一页
        this.destory(this.pointer.next);
        //更新标记
        this.pointer.next = cur;
        this.pointer.cur = prev;
        //预创建上一页
        if(this.curIndex -1 > -1){
          this.pointer.prev = this.createPage(this.curIndex-1);
          this.move(this.pointer.prev,-this.screenWidth);
        }else{
          this.pointer.prev = null;
        }
        localStorage.setItem('index',this.curIndex)
      }
    },

    //下一页
    next : function(){
      if(this.curIndex < this.maxLen-1){
        var next = this.pointer.next;
        var cur  = this.pointer.cur;
         this.curIndex++;
         //当前页移到左边
         this.slide(cur,-this.screenWidth);
         //下一页移到中间
         this.slide(next,0);
         //清除上上一页
         this.destory(this.pointer.prev);
         //更新标记
         this.pointer.prev = cur;
         this.pointer.cur = next;

         //预创建下一页
         if(this.curIndex+1 < this.maxLen){
            this.pointer.next = this.createPage(this.curIndex+1);
            this.move(this.pointer.next,this.screenWidth);
         }else{
            this.pointer.next = null;
         }
         localStorage.setItem('index',this.curIndex)
      }
    },

    //滑动
    slide : function(ele,distance){
      var time = 300;
      ele.style['webkitTransitionDuration'] = time+'ms';
      this.move(ele,distance);
    },

    //移位
    move : function(ele,distance){
      ele.style['-webkit-transform'] = 'translate3d('+distance+'px, 0, 0)';
    },

    //销毁
    destory : function(ele){
      if(!ele) return;
      this.box.removeChild(ele);
    }
}

这段代码没有做滑动翻页的模拟,为的尽量简化。如果大家有兴趣,可以下载下来演示一下。

https://github.com/bjtqti/xxt/tree/master/spa

 

posted on 2014-07-10 15:36  bjtqti  阅读(1724)  评论(1编辑  收藏  举报