【单页应用】关于博客园的补发(高清有码)。。。

前言

上周的时候,做了一点单页应用的研究,但是给断了,本来说最近继续的,但是最近有点其它事情给耽搁了,就给忘了。

PS:其实是师傅(http://www.cnblogs.com/aaronjs/)叫我读jquery源码,我给读跪了。。。

最近两天又朋友问怎么还没写,所以有了今天的东西。

这个单页应用的框架问题很多,就是个简单的demo,喜欢的朋友就看看吧,需要源码的可以下载,但是里面的图片资源文件我给删除了,需要的就留言吧。

这次代码增加了本地存储的应用,将model搞出来了,但是不太完善,过段时间再更新吧。

关于博客园

我想说博客园的接口很难用吗???而且全部是xml的,我这里还写了一个后端程序作为转换呢:

  1 <%@ WebHandler Language="C#" Class="Handler" %>
  2 
  3 using System;
  4 using System.Web;
  5 using System.Net;
  6 using System.IO;
  7 using System.Text;
  8 using System.Collections;
  9 using System.Xml;
 10 
 11 
 12 
 13 public class Handler : IHttpHandler {
 14     
 15     public void ProcessRequest (HttpContext context) {
 16         context.Response.ContentType = "text/plain";
 17         string url = context.Request["url"] != null ?  context.Request["url"].ToString() : ""; 
 18         string sException = null;
 19         string sRslt = null;
 20         WebResponse oWebRps = null;
 21         WebRequest oWebRqst = WebRequest.Create(url);
 22         oWebRqst.Timeout = 50000;
 23         try
 24         {
 25             oWebRps = oWebRqst.GetResponse();
 26         }
 27         catch (WebException ex)
 28         {
 29             sException = ex.Message.ToString();
 30             context.Response.Write(sException);
 31         }
 32         finally
 33         {
 34             if (oWebRps != null)
 35             {
 36                 StreamReader oStreamRd = new StreamReader(oWebRps.GetResponseStream(), Encoding.GetEncoding("utf-8"));
 37                 sRslt = oStreamRd.ReadToEnd();
 38                 oStreamRd.Close();
 39                 oWebRps.Close();
 40             }
 41         }
 42 
 43         XmlDocument doc = new XmlDocument();
 44      
 45         doc.InnerXml = sRslt;
 46         // Convert XML to a JSON string
 47         string JSON = XmlToJSON(doc);
 48 
 49         // Replace \ with \\ because string is being decoded twice
 50         //JSON = JSON.Replace(@"\", @"\\");
 51 
 52         context.Response.Write(JSON);
 53         
 54     }
 55     private static string XmlToJSON(XmlDocument xmlDoc)
 56     {
 57         StringBuilder sbJSON = new StringBuilder();
 58         sbJSON.Append("{ ");
 59         XmlToJSONnode(sbJSON, xmlDoc.DocumentElement, true);
 60         sbJSON.Append("}");
 61         return sbJSON.ToString();
 62     }
 63 
 64     //  XmlToJSONnode:  Output an XmlElement, possibly as part of a higher array
 65     private static void XmlToJSONnode(StringBuilder sbJSON, XmlElement node, bool showNodeName)
 66     {
 67         if (showNodeName)
 68             sbJSON.Append("\"" + SafeJSON(node.Name) + "\": ");
 69         sbJSON.Append("{");
 70         // Build a sorted list of key-value pairs
 71         //  where   key is case-sensitive nodeName
 72         //          value is an ArrayList of string or XmlElement
 73         //  so that we know whether the nodeName is an array or not.
 74         SortedList childNodeNames = new SortedList();
 75 
 76         //  Add in all node attributes
 77         if (node.Attributes != null)
 78             foreach (XmlAttribute attr in node.Attributes)
 79                 StoreChildNode(childNodeNames, attr.Name, attr.InnerText);
 80 
 81         //  Add in all nodes
 82         foreach (XmlNode cnode in node.ChildNodes)
 83         {
 84             if (cnode is XmlText)
 85                 StoreChildNode(childNodeNames, "value", cnode.InnerText);
 86             else if (cnode is XmlElement)
 87                 StoreChildNode(childNodeNames, cnode.Name, cnode);
 88         }
 89 
 90         // Now output all stored info
 91         foreach (string childname in childNodeNames.Keys)
 92         {
 93             ArrayList alChild = (ArrayList)childNodeNames[childname];
 94             if (alChild.Count == 1)
 95                 OutputNode(childname, alChild[0], sbJSON, true);
 96             else
 97             {
 98                 sbJSON.Append(" \"" + SafeJSON(childname) + "\": [ ");
 99                 foreach (object Child in alChild)
100                     OutputNode(childname, Child, sbJSON, false);
101                 sbJSON.Remove(sbJSON.Length - 2, 2);
102                 sbJSON.Append(" ], ");
103             }
104         }
105         sbJSON.Remove(sbJSON.Length - 2, 2);
106         sbJSON.Append(" }");
107     }
108 
109     //  StoreChildNode: Store data associated with each nodeName
110     //                  so that we know whether the nodeName is an array or not.
111     private static void StoreChildNode(SortedList childNodeNames, string nodeName, object nodeValue)
112     {
113         // Pre-process contraction of XmlElement-s
114         if (nodeValue is XmlElement)
115         {
116             // Convert  <aa></aa> into "aa":null
117             //          <aa>xx</aa> into "aa":"xx"
118             XmlNode cnode = (XmlNode)nodeValue;
119             if (cnode.Attributes.Count == 0)
120             {
121                 XmlNodeList children = cnode.ChildNodes;
122                 if (children.Count == 0)
123                     nodeValue = null;
124                 else if (children.Count == 1 && (children[0] is XmlText))
125                     nodeValue = ((XmlText)(children[0])).InnerText;
126             }
127         }
128         // Add nodeValue to ArrayList associated with each nodeName
129         // If nodeName doesn't exist then add it
130         object oValuesAL = childNodeNames[nodeName];
131         ArrayList ValuesAL;
132         if (oValuesAL == null)
133         {
134             ValuesAL = new ArrayList();
135             childNodeNames[nodeName] = ValuesAL;
136         }
137         else
138             ValuesAL = (ArrayList)oValuesAL;
139         ValuesAL.Add(nodeValue);
140     }
141 
142     private static void OutputNode(string childname, object alChild, StringBuilder sbJSON, bool showNodeName)
143     {
144         if (alChild == null)
145         {
146             if (showNodeName)
147                 sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
148             sbJSON.Append("null");
149         }
150         else if (alChild is string)
151         {
152             if (showNodeName)
153                 sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
154             string sChild = (string)alChild;
155             sChild = sChild.Trim();
156             sbJSON.Append("\"" + SafeJSON(sChild) + "\"");
157         }
158         else
159             XmlToJSONnode(sbJSON, (XmlElement)alChild, showNodeName);
160         sbJSON.Append(", ");
161     }
162 
163     // Make a string safe for JSON
164     private static string SafeJSON(string sIn)
165     {
166         StringBuilder sbOut = new StringBuilder(sIn.Length);
167         foreach (char ch in sIn)
168         {
169             if (Char.IsControl(ch) || ch == '\'')
170             {
171                 int ich = (int)ch;
172                 sbOut.Append(@"\u" + ich.ToString("x4"));
173                 continue;
174             }
175             else if (ch == '\"' || ch == '\\' || ch == '/')
176             {
177                 sbOut.Append('\\');
178             }
179             sbOut.Append(ch);
180         }
181         return sbOut.ToString();
182     }
183     public bool IsReusable {
184         get {
185             return false;
186         }
187     }
188 
189 }
View Code

因为博客园没有手机端,所以简单做了一个,真的非常简单啊。。。

多上一张图:

 

 

 

 

 

 

 

 

功能一览

其实说白了就只有一个博客页与博客详情页了

博客页

其中滚动会分页:我们来看看我们的数据吧:

核心代码:

  1 define(['$', '_', 'cBase', 'cView', getViewPath('index'), getViewPath('index_item'), 'blogModel', 'blogStore'], function ($, _, b, v, html, itemTpt, model, store) {
  2     var getPageScrollPos = function () {
  3         var left = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
  4             top = Math.max(document.documentElement.scrollTop, document.body.scrollTop),
  5             height = Math.min(document.documentElement.clientHeight, document.body.clientHeight),
  6             width = Math.min(document.documentElement.clientWidth, document.body.clientWidth),
  7             pageWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth),
  8             pageHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
  9         return {
 10             top: top,
 11             left: left,
 12             height: height,
 13             width: width,
 14             pageWidth: pageWidth,
 15             pageHeight: pageHeight
 16         };
 17     };
 18     var model = model.blogList.getInstance();
 19     var blogStore = store.blog.getInstance();
 20 
 21     var pageSize = 10;
 22     var curpage = 1;
 23     var isLoading = false; //正在加载
 24     var blogs = {};
 25 
 26 
 27     var View = b.Class(v.PageView, {
 28         _propertys_: function () {
 29         },
 30         init: function (superInit, request, interface) {
 31             superInit(request, interface);
 32             console.log('init');
 33         },
 34         createHtml: function () {
 35             return html;
 36         },
 37         attrs: {
 38             'data-id': 'test',
 39             className: 'yexiaoc'
 40         },
 41         events: {
 42             '.orderItem,click': function (el) {
 43                 var id = el.attr('data-id');
 44                 var blog = blogs[id];
 45                 blogStore.set(blog);
 46                 this.forward('detail');
 47                 this._unbindScroll();
 48                 var s = '';
 49             }
 50         },
 51         onCreate: function () {
 52             console.log('onCreate');
 53             this.tpl = _.template(itemTpt);
 54             this._loadData();
 55         },
 56         //dom创建后数据加载时执行,用于加载后执行我们的逻辑
 57         onLoad: function () {
 58             console.log('onLoad');
 59             
 60             var scope = this;
 61             $(window).bind('scroll', function () {
 62                 scope._onWindowScroll.call(scope)
 63             });
 64 
 65         },
 66         _loadData: function (onSuc, onError) {
 67             var tpl = this.tpl;
 68             var list = this.find('#lstbox');
 69             var param = {};
 70             param.url = 'http://wcf.open.cnblogs.com/blog/sitehome/paged/' + curpage + '/' + pageSize;
 71             model.setParam(param);
 72             var scope = this;
 73             isLoading = true;
 74             model.execute(function (data) {
 75                 var listData = data.feed && (data.feed.entry || []);
 76                 if (listData) {
 77                     if (listData.length == 0) {
 78                         list.html('<li>暂无数据</li>');
 79                     } else {
 80                         $.each(listData, function (i, item) {
 81                             blogs[item.id] = item; //将博客存储
 82                             var htm = tpl(item) || '';
 83                             list.append(htm);
 84                         });
 85                     }
 86                     (typeof onSuc === 'function') && (onSuc.call(scope, data));
 87                 }
 88                 isLoading = false;
 89             });
 90         },
 91         _onWindowScroll: function () {
 92             var pos = getPageScrollPos();
 93             if (pos.pageHeight - (pos.top + pos.height) < 500 && !isLoading) {
 94                 curpage++;
 95                 this._loadData();
 96             }
 97         },
 98         _unbindScroll: function () {
 99             $(window).unbind('scroll');
100         },
101         //dom创建后,未显示
102         onShow: function () {
103 
104             console.log('onShow');
105         },
106         //dom隐藏前
107         onHide: function () {
108             console.log('onHide');
109         }
110     });
111 
112     return View;
113 });
View Code

对应两个模板页

 1 <input class="login" type="button" value="点击登录" />
 2 <header>
 3     <b class="icon_home i_bef" id="js_home"></b>
 4     <h1>
 5         博客园</h1>
 6     <i id="js_return" class="returnico"></i>
 7 </header>
 8 <section class="cont_wrap" style="margin: 17px 0 40px;">
 9     <ul class="pro_list" id="lstbox">
10     </ul>
11 </section>
12 <ul class="tab_search fix_bottom">
13     <li class="tabcrt">博客</li>
14     <li class="tab_hotel ">新闻</li>
15     <li class="tab_hotel ">48小时</li>
16     <li class="tab_hotel ">推荐</li>
17 </ul>
 1 <li class="arr_r orderItem" data-id="<%=id %>">
 2     <article class="blog_item">
 3         <h3>
 4             <a href="<%=link.href %>" target="_blank"><%=title.value || '无题' %></a>
 5             </h3>
 6             
 7         <div class="author pro_list_rank">
 8             <%if(author.avatar){ %>
 9             <a href="<%=author.uri %>" target="_blank">
10                 <img src="<%=author.avatar %>">
11             </a>
12             <%} %>
13             JavaScript 是根据 "ECMAScript"标准制定的网页脚本语言。这个标准由 ECMA 组织发展和维护。ECMA-262 是正式的 JavaScript标准。JavaScript是目前Web客户端开发的主要编程语言,也是Ajax的核心技术之一。
14         </div>
15         <div class="item_footer">
16             <a href="<%=author.uri %>" class="lightblue">Scut</a> <%=published %> <a href="<%=link.href %>" title="2013-08-21 15:21" class="gray">评论(<%=comments %>)</a>
17             <a href="<%=link.href %>" class="gray">阅读(<%=views %>)</a> <span class="price1">推荐(<%=diggs %>)</span></div>
18     </article>
19 </li>

然后就是详情页了

详情页

 1 define(['$', '_', 'cBase', 'cView', getViewPath('detail'), getViewPath('detail_article'), 'blogModel', 'blogStore'], function ($, _, b, v, html, itemTpt, model, store) {
 2 
 3     var model = model.blog.getInstance();
 4     var blogStore = store.blog.getInstance();
 5     var tpl = _.template(itemTpt);
 6 
 7     var View = b.Class(v.PageView, {
 8         _propertys_: function () {
 9         },
10         init: function (superInit, request, interface) {
11             superInit(request, interface);
12             console.log('init');
13         },
14         createHtml: function () {
15             return html;
16         },
17         attrs: {
18         },
19         events: {
20             '#js_return,click': function () {
21                 this.forward('index');
22             }
23         },
24         onCreate: function () {
25             console.log('onCreate');
26 
27         },
28         _loadData: function () {
29             var box = this.find('.cont_wrap');
30             box.html('');
31             var param = { url: 'http://wcf.open.cnblogs.com/blog/post/body/' + blogStore.get().id }
32             $.get('Handler.ashx', param, function (data) {
33                 (typeof data === 'string') && (data = $.parseJSON(data));
34                 data && data.string && (blogStore.setAttr('value', data.string.value));
35                 var d = blogStore.get();
36                 box.append(tpl(d));
37                 var ss = '';
38             });
39         },
40         //dom创建后数据加载时执行,用于加载后执行我们的逻辑
41         onLoad: function () {
42             console.log('onLoad');
43         },
44         //dom创建后,未显示
45         onShow: function () {
46             console.log('onShow');
47             this._loadData();
48 
49         },
50         //dom隐藏前
51         onHide: function () {
52             console.log('onHide');
53         }
54     });
55 
56     return View;
57 });

其中模板各位自己下载看吧。

结语

之前已经详细描述了整个代码逻辑这次就不说了,各位觉得不错可以下载下来看看,后面点还会更新。

源码

https://files.cnblogs.com/yexiaochai/page.zip(page.zip

 

posted on 2013-08-22 17:59  叶小钗  阅读(3627)  评论(25编辑  收藏  举报