【单页应用】一起来单页应用吧,实现简单微博功能!(下)

简介:
前言

PS:回家发现代码没拷贝回来,明天继续吧。。。

开始之前先扯点其它的,我上午去理发,居然才7元,但是那个阿妈给我搞成和尚的造型了,我想说点什么,但转念一想节约点洗头水也好!!!

PS:其实主要原因是我掉头发。。。。。。

好了,接昨天的内容:【单页应用】一起来单页应用吧,实现简单微博功能!(上)

昨天我们一起准备了两大核心,继承与view,虽说有问题,而且必定有问题,但是我们暂时不管他。

我们先继续先往下面写,到最后整体流程拉通后再一起优化就好,现在去纠结也不一定有结果,于是我们开始吧。

继承之实现APP

我们这里APP要干的事情,与其说担任MVC中控制器的角色,不如说他就是充当了一下路由选择的角色,根据不同的URL导向不同的view,并且会管理hash。

由于我们会处理request请求,压入hash以达到后退功能有效,所以这里先来实现一个hash类吧

实现Hash对象

先来一个辅助函数,用于计算某个字符在数组的位置:

复制代码
 1 var indexOf = function (k, arr) {
 2     if (!arr) {
 3         return -1;
 4     }
 5     //若是对象本身便居然indexof,便使用自身的,比如字符串
 6     if (arr.indexOf) {
 7         return arr.indexOf(k);
 8     }
 9     for (var i = 0, len = arr.length; i < len; i++) {
10         if (arr[i] == k) {
11             return i;
12         }
13     }
14     return -1;
15 };
复制代码
PS:这个hash的实现不算太好,后面也许会改动

复制代码
 1 b.Hash = b.Class({
 2     _propertys_: function () {
 3         this.keys = [];
 4         this.values = [];
 5     },
 6     init: function (obj) {
 7         (typeof obj == 'object') || (obj = {}); //???
 8         for (var k in obj) {
 9             if (obj.hasOwnProperty(k)) {
10                 this.keys.push(k);
11                 this.values.push(obj[k]);
12             }
13         }
14     },
15     length: function () {
16         return this.keys.length;
17     },
18     getItem: function (k) {
19         var index = indexOf(k, this.keys);
20         if (index < 0) {
21             return null;
22         }
23         return this.keys[index];
24     },
25     getKey: function (i) {
26         return this.keys[i];
27     },
28     getValue: function (i) {
29         return this.values[i];
30     },
31     add: function (k, v) {
32         return this.push(k, v);
33     },
34     del: function (k) {
35         var index = indexOf(k, this.keys);
36         return this.delByIndex(index);
37     },
38     delByIndex: function (index) {
39         if (index < 0) return this;
40         this.keys.splice(index, 1);
41         this.vaules.splice(index, 1);
42         return this;
43     },
44     //移除栈顶hash,并返回
45     pop: function () {
46         if (!this.keys.length) return null;
47         this.keys.pop();
48         return this.values.pop();
49     },
50     push: function (k, v, order) {
51         if (typeof k == 'object' && !v) {
52             for (var i in k) {
53                 if (k.hasOwnProperty(i)) {
54                     this.push(i, k[i], order);
55                 }
56             }
57         } else {
58             var index = indexOf(k, this.keys);
59             if (index < 0 || order) {
60                 if (order) this.del(k);
61                 this.keys.push[k];
62                 this.values.push[v];
63             } else {
64                 this.values[index] = v;
65             }
66         }
67     },
68     //查找hash表,返回key
69     indexOf: function (v) {
70         var index = indexOf(v, this.vaules);
71         if (index >= 0) {
72             return this.keys[index];
73         }
74         return -1;
75     },
76     each: function (handler) {
77         if (typeof handler == 'function') {
78             for (var i = 0, len = this.length(); i < len; i++) {
79                 handler.call(this, this.keys[i], this.vaules[i]);
80             }
81         }
82     },
83     getObj: function () {
84         var obj = {};
85         for (var i = 0, len = this.length(); i < len; i++) {
86             obj[this.keys[i]] = this.values[i];
87         }
88         return obj;
89     }
90 });
复制代码
此hash对象基本就是数组的写照,各位可以对照着看,于是我们继续我们的app

app雏形

复制代码
  1 var Application = new b.Class({
  2     _propertys_: function () {
  3         var scope = this;
  4         this.webRoot = ''; //应用跟目录
  5         this.head = $('head');
  6         this.body = $('body');
  7         this.viewRoot = 'views/'; //视图所在目录
  8         this.defaultView = 'index'; //默认加载视图
  9 
 10         this.request; //请求对象
 11         this.viewPath; //当前请求视图路径,解析request得出
 12         this.mainFrame; //主框架
 13         this.viewPort; //视图框架
 14         this.stateDom; //状态栏
 15 
 16         this.views = new b.Hash(); //views保存浏览器存储的hash
 17         this.curView; //当前视图
 18         this.interface = {}; //提供给视图访问的接口,暂时不管
 19         this.history = []; //历史记录
 20 
 21         //        this.stopListening = false;//是否开启监听
 22 
 23         this.onHashChange = function () {
 24             scope.history.push(window.location.href);
 25             var url = decodeURIComponent(window.location.hash.replace(/^#+/i, '')).toLowerCase();
 26             scope._onHashChange(url);
 27         };
 28 
 29         this.lastHash = '';
 30         this.lastFullHash = '';
 31         this.isChangeHash = false; //hash是否发生变化
 32     },
 33     init: function (opts) {
 34         //为属性赋值
 35         opts = opts || {};
 36         for (var k in opts) {
 37             this[k] = opts[k];
 38         }
 39         this.createViewPort();
 40         this.bindEvent(); //事件绑定
 41     },
 42 
 43     //创建app页面基本框架,此处不能使用id,因为。。。
 44     createViewPort: function () {
 45         var htm = [
 46             '<div class="main-frame">',
 47                 '<div class="main-viewport"></div>',
 48                 '<div class="main-state"></div>',
 49             '</div>'
 50         ].join('');
 51         this.mainframe = $(htm);

 52         this.viewport = this.mainframe.find('.main-viewport');
 53         this.statedom = this.mainframe.find('.main-state');
 54         var body = $('body');
 55         body.html('');
 56         body.append(this.mainframe);
 57     },
 58     //!!!!!!非常重要哦!!!!!!
 59     bindEvent: function () {
 60         var scope = this;
 61         //暂时不使用requireJS
 62         //        requirejs.onError = function () {};
 63         $(window).bind('hashchange', this.onHashChange);
 64     },
 65     _onHashChange: function (url) {
 66         url = url.replace(/^#+/i, '');
 67         var req = this.parseHash(url);
 68 
 69         this.request = req;
 70         this.viewPath = this.viewPath || this.defaultView;
 71         this.loadView(this.viewPath); //!!!重要的视图加载
 72     },
 73     //该方法慢慢看吧。。。
 74     parseHash: function (hash) {
 75         var fullhash = hash,
 76                 hash = hash.replace(/([^\|]*)(?:\|.*)?$/img, '$1'),
 77                 h = /^([^?&|]*)(.*)?$/i.exec(hash),
 78                 vp = h[1] ? h[1].split('!') : [],
 79                 viewpath = (vp.shift() || '').replace(/(^\/+|\/+$)/i, ''),
 80                 path = vp.length ? vp.join('!').replace(/(^\/+|\/+$)/i, '').split('/') : [],
 81                 q = (h[2] || '').replace(/^\?*/i, '').split('&'),
 82                 query = {}, y;
 83         this.isChangeHash = !!(!this.lastHash && fullhash === this.lashFullHash) || !!(this.lastHash && this.lastHash !== hash);
 84         if (q) {
 85             for (var i = 0; i < q.length; i++) {
 86                 if (q[i]) {
 87                     y = q[i].split('=');
 88                     y[1] ? (query[y[0]] = y[1]) : (query[y[0]] = true);
 89                 }
 90             }
 91         }
 92 
 93         this.lastHash = hash;
 94         this.lashFullHash = fullhash;
 95         return {
 96             viewpath: viewpath,
 97             path: path,
 98             query: query,
 99             root: location.pathname + location.search
100         };
101     },
102     //!!!非常重要
103     loadView: function (viewPath) {
104         var id = viewPath;
105         var scope = this;
106         //此处本来应该判断是否已经有该视图,但是我们暂时不管,我们只要加载了相关视图就算成功
107         /*
108         一些操作
109         */
110 
111         //此处应该加载我们的js文件
112         $.getScript(this.buildUrl(viewPath), function () {
113             var view = new PageView();
114             view.show();
115             scope.viewport.append(curView.$el);
116             var s = ''; 
117         });
118         //!!!暂时不使用requireJS
119         //        var self = this;
120         //        requirejs([this.buildUrl(path)], function (View) {
121         //            callback && callback.call(self, View);
122         //        });
123     },
124     buildUrl: function (path) {
125         return this.viewRoot = path;
126     }
127 });
复制代码
好了,至此,我们粗制滥造版app结束,我们来试试先,再一并讲解其主要流程。

简单测试

html代码:

复制代码
 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta charset="utf-8" />
 5     <title></title>
 6     <script src="res/libs/jquery.js" type="text/javascript"></script>
 7     <script src="res/test/c.base.js" type="text/javascript"></script>
 8 </head>
 9 <body>
10 </body>
11 <script src="res/test/app.js" type="text/javascript"></script>
12 <script type="text/javascript">
13     var app = new Application();
14 
15 </script>
16 </html>
复制代码
base代码:

 base核心
app代码:

 APP
文件结构:



测试结果



我可耻的觉得自己成功了一半了。。。

基本流程讲解

app是我们整个框架的核心,我们来简单讲解一下:

① 在整个_propertys_函数中,定义了我们app会用到的一些实例属性、方法

② init方法(一定会执行,因为我们使用了c.base的方法创建类),他主要干了两件事:

创建基本dom结构;

绑定事件,这个绑定事件就非常重要了

③ 59行开始,便是该文件的核心之一,这里为window绑定了hashchange事件,于是hash一旦改变(以#号方式),那么就会触发onhashchange事件

④ 触发hashchange事件后,会获得请求url#后面的参数,根据约定,他就是我们请求的view的路径,所以开始执行loadView方法,开始加载视图

⑤ 102行,开始加载视图,这里本应该使用requireJS,但是这里便于讲解,便于各位理解,我们暂时没有使用,于是动态加载我们的index文件,在成功后实例化view并且将view装入我们的视口中。

⑥ 整体流程结束

于是我们的粗制滥造版本也结束了。

阶段总结

好了,我们现在回过头来看看我们整个框架现在变成什么样了。

① 我们拥有实现类的通用b.class

② 我们有了我们的抽象视图类

③ 我们有了我们的control application

假使以上流程都流程问题不大,那么我们整个功能其实就七七八八了,因为还差的model可以轻松补上。

但是明显我们现在的APP是有缺陷的,而且缺陷比较大,比如我们的hash相关其实根本没有用上,所以现在我们来完善他们吧!

RequireJS组织代码

在这里,我们便开始使用我们的RequireJS了,然后将我们的整个逻辑慢慢铺开,首先我将我们的文件目录分开。



 html页
 main
 app
 c
 c.base
 c.view
 index
至此我们的代码便完全分离开了,接下来我们来细化我们的app文件。

细化app

待续......

 

结语

写了几个小时了,有点累,休息下,我们晚上在继续

 


本文转自叶小钗博客园博客,原文链接http://www.cnblogs.com/yexiaochai/p/3251397.html如需转载请自行联系原作者

相关文章
|
2月前
单页404源码
单页404源码
23 4
单页404源码
|
3月前
|
数据安全/隐私保护
短视频解析单页源码
这个一个网页html解析短视频无水印视频的源码,电脑直接打开也可以本地使用,也可以上传到网站搭建成网页使用。
65 1
|
Web App开发 JavaScript 前端开发
单页切屏效果的原理
1.实现过程中的注意事项: 鼠标滚轮事件的兼容性问题: W3C并没有对鼠标滚轮事件进行规范,各浏览器厂商封装了不同的实现方法,事件属性也不一样,FireFox用了一个私有实现DOMMouseScroll。其他浏览器都是用mousewheel实现,所以需要做一下兼容处理(详见下面的js关键代码的截图)
121 0
单页切屏效果的原理
|
Web App开发 移动开发 前端开发
20+免费精美响应式Html5 网站模板01(含源码)
20+免费精美响应式Html5 网站模板01(含源码)
459 0
20+免费精美响应式Html5 网站模板01(含源码)
|
Web App开发 移动开发 前端开发
20+免费精美响应式Html5 网站模板02(含源码)
20+免费精美响应式Html5 网站模板02(含源码)
291 0
20+免费精美响应式Html5 网站模板02(含源码)
|
Web App开发 移动开发 前端开发
20+免费精美响应式Html5 网站模板03(含源码)
20+免费精美响应式Html5 网站模板(含源码)
466 0
20+免费精美响应式Html5 网站模板03(含源码)
|
移动开发 前端开发 数据可视化
单页网站不是梦,几款国外的单页网站创建工具
  单页网站已经流行很久了,受到很多人的喜爱。从立体动感的视差滚动效果和流畅的动画到固定和干净的菜单,你会发现单页网站的效果真的很酷!   在这篇文章中,我们寻找了一些真正好用的单页网站创建工具分享给大家。
1407 0
|
移动开发 前端开发 JavaScript
怎样制作单页网站?国外优秀案例给你灵感
  单页网站是提供给用户简约易用的体验的好方法。在一个单页面中展示你需要的所有内容可能是一个充满挑战性的过程,但很多设计师喜欢这个风格,并创作出很多惊人的单页网站作品。   从用图片和文字构成的简单页面到惊人的视差滚动效果,有几种不同的方法来创建单页网站。
831 0

热门文章

最新文章