【單頁應用】關於博客園的補發(高清有碼)。。。


前言

上周的時候,做了一點單頁應用的研究,但是給斷了,本來說最近繼續的,但是最近有點其它事情給耽擱了,就給忘了。

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 });

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

結語

之前已經詳細描述了整個代碼邏輯這次就不說了,各位覺得不錯可以下載下來看看,后面點還會更新。

源碼

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM