SPA初试-1

本篇内容是在上一次的基础上进行改进,对状态的定义进行了修改,一个状态的定义如下:

function state(stateName, template, templateUrl) {
  this.stateName = stateName;
  if (template) {
    this.template = template;
  }
  if (templateUrl) {
    this.templateUrl = templateUrl;
  }
}

即每一个页面对应着一个状态,一个状态有一个状态名,还有一个模板/模板url,这样我们就可以将不同页面的内容写到不同的html里,然后通过templateUrl将他们动态加载进来渲染页面。

先贴上js代码:

var states = [];
var currentState;
$(document).ready(function() {
  registState();
  console.log(states);
  currentState = init();
  //监听hash路由变化
  window.addEventListener("hashchange", hashChange)
})

//哈希路由處理事件
function hashChange() {
  var nextState;
  console.log(window.location.hash);
  //判断地址是否为空,若为空,则默认到main-view页面
  if (window.location.hash == "") {
    nextState = "mainView";
  } else {
    //若不为空,则获取hash路由信息,得到下一个状态
    nextState = window.location.hash.substring(1);
  }
  //判断当前状态是否注册过(是有存在这个状态)0g
  var validState = checkState(states, nextState);
  //若不存在,则返回当前状态
  if (!validState) {
    createState(nextState, "", "./test.html");
    currentState = nextState;
    return;
  }
  $('#' + currentState).remove();
  if (!nextState.view) {
    states.forEach( function(element, index) {
      if (element.stateName == nextState) {
        createView(element);
      }
    });
  }
  currentState = nextState;
}

//状态注册
function registState() {

  var newState = new state("mainView", "", "./main-view.html");
  var newState1 = new state("listView", "", "./list-view.html");
  var newState2 = new state("detailView", "", "./detail-view.html");

  states.push(newState);
  states.push(newState1);
  states.push(newState2);
}

//初始化,对用户一开始输入的url进行处理
function init() {
  nextState = window.location.hash.substring(1);
  //若用户输入的hash值为空,则默认跳转到states[0]的页面
  if (nextState == "") {
    createView(states[0]);
    return states[0].stateName;
  }
  states.forEach( function(element, index) {
      if (element.stateName == nextState) {
        createView(element);
      }
    });
  return nextState;
}

//判断状态是否存在
function checkState(states, nextState) {
  var tof = false;
  states.forEach(function(element) {
      if (element.stateName == nextState) {
        tof = true;
      }
    })
  return tof;
}

//创建一个状态
function createState(stateName, template, templateUrl) {
  var newState = new state(stateName, template, templateUrl);
  createView(newState);
  $("#" + newState.stateName).css("display", "block");
  $('#'+ currentState).css("display", "none");
  currentState = newState;
  states.push(newState);
}

//创建状态所对应的视图,并将视图放到body里
function createView(state) {
  if (state.template) {
    template = state.template;
    state.view = $("<div id='" + state.stateName + "'></div>").html(template);
    $("body").append(state.view);
  }  else if (state.templateUrl) {
    htmlobj = $.ajax({url: state.templateUrl, async: false});
    template = htmlobj.responseText;
    state.view = $("<div id='" + state.stateName + "'></div>").html(template);
    $("body").append(state.view);
  }
}

//状态对象
function state(stateName, template, templateUrl) {
  this.stateName = stateName;
  if (template) {
    this.template = template;
  }
  if (templateUrl) {
    this.templateUrl = templateUrl;
  }
}

处理逻辑

  1. 一开始进入页面的时候,先利用registState()注册一些状态,然后利用init()函数来对用户一开始输入的url进行处理
  2. 当用户输入的路由发送变化的时候,调用hashChange()函数:
    1. 获取用户输入的hash值,这个hash值即为状态名
    2. 检查这个状态是否已经注册,若已经注册过,则将当前的页面内容清除掉,然后为输入的状态创建视图
    3. 若状态未注册,则创建一个新的默认状态

文件结构如下:

index.html里的内容

里面没有任何东西,内容都是我们动态加载进去的

<!DOCTYPE html>
<html>
  <head>
    <title>SPA</title>
    <link rel="stylesheet" type="text/css" href="index.css" />
    <script type="text/javascript" src="jquery-3.1.1.min.js"></script>
    <script type="text/javascript" src="spa.js"></script>
  </head>
  <body>
  </body>
</html>

注意

我使用的是chrome浏览器,由于安全问题,chrome必须通过http等方式才能用$.ajax来获取到文件内容,因此我用了nodejs的http-server自己搭建了一个简单的服务器. 其他的页面都只是单纯的html文件,没有什么特别,所以就不列举出来了

截图

输入服务器的url

修改url,在后面加上#listView(之前在初始化的时候就已经注册过的状态)

输入一个没有注册过的状态(注册了一个默认的状态)

接下来打算做一下嵌套状态,如果有什么好的建议,麻烦告诉下我~~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏草根专栏

使用xUnit为.net core程序进行单元测试(1)

一. 导读 为什么要编写自动化测试程序(Automated Tests)? 可以频繁的进行测试 可以在任何时间进行测试,也可以按计划定时进行,例如:可以在半夜进...

36650
来自专栏林冠宏的技术文章

C++ 连接数据库的入口和获取列数、数据

这里不具体放出完整的程序,分享两个核心函数: 由于这里用到的函数是编译器自己的库所没有的,需要自己下载mysql.h库或者本地有数据库,可以去bin找到,放进去...

29180
来自专栏Hadoop实操

如何开发HBase Endpoint类型的Coprocessor以及部署使用

41220
来自专栏Python自动化测试

测试驱动之xml文件的处理

Xml是可扩展标记语言,关于xml的技术本人这里不在介绍,感兴趣的同学可以去w3c看看详细的资料,这里,我仅仅介绍的是如何获取xml文档结构中的...

17330
来自专栏Android先生

Android开发者怎么能不会写后台接口呢?

然后在src下创建三个包,一个放Servlet,一个放mysql的工具类,一个放对象;

9730
来自专栏谈补锅

NSFileManager和NSFileHandler的作用, category的理解

NSFileManager类可以管理文件系统中的文件和目录,也可以定位、判断是否存在、创建、拷贝、删除文件和目录,还可以获得文件和目录的信息;

17550
来自专栏分布式系统进阶

Influxdb的Meta data分析

Influxdb定义了一个Service:Precreator Serivec(services/precreator/service.go),实现比较简单,周...

17520
来自专栏雨尘分享

2018 - iOS 面试题汇总一般面试题BAT面试题

5.2K30
来自专栏积累沉淀

Java批处理

批处理 JDBC对批处理的操作,首先简单说一下JDBC操作sql语句的简单机制。 JDBC执行数据库操作语句,首先需要将sql语句打包成为网络字...

54650
来自专栏Java帮帮-微信公众号-技术文章全总结

数据库连接池、dbutil_知识点全掌握

数据库连接池、dbutil ? 数据库连接池 1 数据库连接池的概念 用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用...

31150

扫码关注云+社区

领取腾讯云代金券