使用唯一的一個VelocityEngine全局的靜態實例,優化了小泥鰍blog中每次請求都要創建VelocityEngine實例對象,減少了對象的開銷
通過UA判斷請求來自的設備,從而初始化不同的模板目錄,從而實現手機和PC訪問展示出不同的頁面效果
參數初始化Page_Init:
初始化請求上下文對象
請求對象
Cookie對象
貨幣對象
語言對象
初始化貨幣執行業務邏輯并寫入到客戶端的Cookie中
驗證用戶的身份 Authenticate_User
頁面預加載Page_PReLoad:會加載一些公共的數據,比如:圖片URL地址,廣告圖片地址...;加載語言包數據;判斷Form參數個數引發Post事件
頁面加載事件Page_Load:需要留給各個子頁面實現,必須實現的一個,主要在子頁面中完成各自的業務處理,數據獲取與填充
頁面預結束事件Page_PreEnd:暫時還沒有做處理
頁面結束事件 Page_End:合并模板和業務數據
this.pcMobile【判斷請求時做的初始化】 + this.templateFile 【在各個子頁面重寫Page_Load事件時做初始化】
使用虛擬的protected virtual void Authenticate_User()來實現,這樣可以被子類重寫,從而可以做后臺管理類的程序,比如會員中心里面的頁面,需要用戶登錄之后才能訪問
判斷用戶登錄使用的是檢查session中登陸的用戶對象來實現的 同時還有關于匿名用戶登陸的問題,這個在后面解決
多貨幣 它屬于每個訪客自定義的數據,所以它不能存儲在application中,應該存儲在Cookie中,或者session中
Octopus使用是Cookie的方式實現的
不讓Entity承擔過多的業務邏輯
在寫的過程中,為貨幣Cookie的問題困擾了好久,產品價格的計算需要,產品對象拿到貨幣對象之后才能進行
起初我是在Entity中讀取Cookie值來獲得貨幣對象,后來發現這樣做不好
一是,每個產品對象的創建需要不能的讀取cookie
二是,在ProductInfo 實體中承擔了過多的業務處理邏輯
再者,好像在entity中不應該有訪問Cookie之類的代碼吧,
后來進行了改進,將這部分代碼轉移到業務層,在業務層中接收CurrencyInfo對象,對ProductInfo對象做屬性的初始化,這樣解決了這個問題
同時cookie的讀取則轉移到了表現層的Page_Load中,而且并不是直接訪問cookie,而是在數據上下文容器中取得貨幣符號,進而得到貨幣對象來實現的
這個算是比較成功一次代碼的升級
分頁樣式也是一個比較重要的問題,Octopus是考慮多語言的,分頁樣式也是有一定多樣性的
一般我們來實現就是編碼生成 一段分頁條的HTML代碼片段,然后配合CSS樣式實現分頁,這個我參考了DTCMS中的代碼,拿來主義
我感覺還是不錯的,而且DTCMS上使用的是雙top的分頁算法,還是比較高效的
這是一種處理思路,Octopus就是這種方式實現的
第二種思路是,將分頁條進行模板化,也有現成的代碼,不過我沒有采用這種方式,有點復雜,但是樣式的可定義性,就非常的高
分頁樣式的處理和我后面介紹的關于無限級別分類的處理思路上是一樣的。Octopus借助了NV模板引擎,所以在實現上要考慮NV引擎這一點
思路說完了,還是需要做一點改進的,前面第一種思路幫我實現了分頁的算法問題,這個是解決掉了
那么多語言切換的時候,分頁條該怎么變化呢?要和語言包定義的數據進行交互
比如:首頁【中文】---First【英語】
我將生成分頁條的OutPageList算法增加了一個paramsstring[] langPage類型的參數,將里面固定的 字符使用傳遞進來的參數進行替換掉
犧牲掉了一部分的樣式靈活性,在調用的時候,需要從NV引擎的數據上下文中讀取定義的 首頁 上一頁 下一頁 尾頁 等數據 就可以了
備注:在頁面周期的Page預加載事件中我們加載了語言包的數據【這個地方還需要做一定的優化,需要將數據進行一個緩存的處理】
這樣分頁條多語言的問題也解決掉了
無限分類的問題是最早開始解決的問題,也是花費時間比較長的問題,
大概有兩個難點
一是:怎么設計無限分類的信息表,怎么存儲無限分類的數據
二是:Octopus使用了NV引擎,產品分類的展示樣式也是千變萬化的,我在NV模板中該怎么寫這樣的代碼呢?
先說第一個問題吧,表設計,其實大家都很清楚,有一個Parentid字段來標識當前分類的父分類ID,還會有一些附加的字段
ClassPath,記錄分類的導航路徑【一個分類ID以逗號分隔的一段字符】ClassLayer【節點的深度】,可以研究一下DTCMS中的設計
我基本就是參考它的。
還有一種設計方案叫做 左右值的無限分類 在網上有說明的,不過我沒研究清楚,沒法使用,基本就這兩種吧,看大家怎么選擇
下面一個比較關鍵的問題:如果所有分類讀取出來放到NV引擎上展示出來?---后續會有
提供幾種思路實現
其內部的觸發機制是:通過請求的參數個數來進行觸發的
if (_Request.Form.Count > 0) { OnPost(); }
這種方式來處理頁面的提交機制
然后通過兩種方式區分頁面發起的不同類型的請求
1.通過"成功控件實現"
2.通過"hd_action"隱藏域的類型來判斷
不過這種方式 有個問題:用戶在 右鍵單擊 “重新加載”時 會提示重新 表單提交的問題
解決這個方式 也有兩種方式:
1.使用${reload} js代碼 響應到客戶端,一旦用戶觸發頁面的post事件時,就從服務端響應一段js腳本到客戶端,在客戶端在重新發起一次請求
這樣就不會有 重復表單的提示。
2.后來發現可以不用這樣做哦:使用Context.Response.Redirect(Request.RawUrl, true); 重新加載一次頁面就可以了,一旦執行完畢post
的動作:更新,或刪除,直接讓客戶端重新定向到新的URL發起一次請求,通過fiddler可以發現,每執行一個動作先是302的http代碼,然后是200
兩種方式都可以解決這個問題
使用js的方式 稍微慢了一點,因為post動作多執行了一次頁面的周期Page_Load
優點:可以在任意的放加上任意多的form標記,這個和aspx只有一個form標記不同
既可以使用submit和image標簽提交表單,也可以自定義函數調用表單的submit()函數從而完成表單的提交
還有就是不使用該死的腳本了,不用調試了 哈哈 只要有form就可以提交 簡單死了
缺點:只要對象和服務端進行交互,就一定要有form標記,而且還有借助很多的隱藏標記
前面說了上一種方式的實現 離不開form的標記,如果我們不用form標記,并且有時還要有get方式提交咋個辦呢?
那就只能通過腳本Ajax的方式實現了
首先:如何存儲自定義的數據,form中我們要存儲自定義數據的話 使用的是hidden標記。使用思路二時: 使用data-*自定儀的屬性
將一次請求所有用到的參數數據都存儲在data-*里面,通過jq和js方式逐個獲取,唉沒有jq.serialize();的方法方便啊【后面自己寫一個類似的方式實現data-*的批量獲取】
function DomSerialize(dom){ if (dom) { var attr = dom.attributes; var attrArr = []; if (attr.length > 1) { //追加附加屬性 for (var i = 0; i < attr.length; i++) { if (attr[i].name.indexOf("data-") != -1) { if (attr[i].name.indexOf("data-action") != -1) { attrArr.push(encodeURIComponent(attr[i].name.replace(/data-/, "my")) + "=" + encodeURIComponent(attr[i].value)); } else { attrArr.push(encodeURIComponent(attr[i].name.replace(/data-/, "hd_")) + "=" + encodeURIComponent(attr[i].value)); } } } //追加當前元素的屬性 attrArr.push(encodeURIComponent(dom.name) + "=" + encodeURIComponent(dom.value)); } return attrArr.join("&"); } //attributes返回當前元素的所有屬性數組 我們只選取包含data 開頭的屬性,并添加到當前數組中去,并將當前元素的name屬性和value也添加進去}
好了,準備工作完畢。接下來 發起請求就行了,通過ajax的請求配置包 common.js和Lee輔助腳本實現即可
對了,刷新說一下【如果請求成功將會執行】,使用js的方式進行刷新
思路三:使用ajax+模板的方式【名字還沒想好先暫時到這兒】;
已經實現了登錄,購物車 ,注冊等模塊的組件化
實現思路有三種方式,第三種方式目前還不是很確定是否能實現
思路1:會員中心的實現都在一個ashx中實現,通過不同參數的傳入,來實現不同的邏輯模塊,實現不用模板的加載,同時將左側的Left,作為一個Widget
思路2:反著來。實現一個母版頁,通過if的判斷語句,在右側的加載各個組件
思路3:利用最原始的"子模板"的思路,這個還在思考中
|
新聞熱點
疑難解答