項目爲單頁web應用,只針對chrome瀏覽器,無開發文檔。因爲是追求進度的項目,開發約定極少,除了jquery、LAB.js、bootstrap以及一些UI組件外,沒有使用其餘開源組件。
項目簡單封裝了ajax請求
,form表單信息獲取
,緩存
,獲取和渲染模板函數
以及一些UI組件,ajax請求沒有按照restful api進行封裝。
如今項目開發中所遇到的問題:javascript
代碼命名不規範,例如action
,do_action
css
代碼結構不清晰,沒有按照功能或mvc拆分紅獨立的文件,只能依靠dom去查找具體的業務代碼在哪裏html
模板寫的有問題,複用模板使用id來作dom索引,或混入javascript業務邏輯,也有整個模板只包含一行代碼前端
工具類封裝與引用不規範,主要是沒有註釋,沒有規範的例子可作參照,致使出現錯誤的使用工具類java
業務邏輯的流轉依靠dom操做,例如,在實現數據聯動的時候,每每須要手動點擊刷新按鈕或者$(...).click()。node
模板渲染封裝太薄,致使不一樣模塊的模板渲染方法各異,且會渲染模板中的javascript代碼jquery
沒法對代碼進行代碼測試,只能依靠人工測試確保代碼質量web
css文件過大,基本上全部的css都集中在一個css文件下ajax
頁面跳轉策略是隱藏老頁面,顯示新頁面。chrome
css規範: http://www.iteye.com/news/27577
重點注意命名規範。
javascript命名規範: http://blog.sina.com.cn/s/blog_8db76d6d010143pi.html
javascript註釋規範:http://www.jetbrains.com/webstorm/webhelp/creating-jsdoc-comments.html
具體規範要待確立註釋要達到什麼效果後(例如:是否要自動生成doc)再寫
前提:
儘可能不動現有文件夾名稱
儘可能少的移動文件
儘可能減小修改現有代碼
如何重構:
//fileStructure//注意,一個模塊可按照功能繼續往下劃分,相應的,與之對應的css和img也要在目錄上與之對應{ src:{//開發環境,主要作業務邏輯 新增 moduleName:{//模塊名稱 src:[sourceJSFiles], style:[cssFiles] } }, components:{//開發環境:自行開發的插件,公共組件等, 新增//組件也能夠做爲單獨項目獨立出來,便於測試,維護 componentName:{ src:[sourceJSFiles], style:[cssFiles]//可能存在的style } } libs:{//存放項目依賴的插件 新增 pluginName:[plugin_files], ...:... }, javascripts:{//生產環境的js源碼 moduleName:[combineJSFiles], ...:... components:{ component:[CombineJSFIles] ...:... } }, stylesheets:{//生產環境的css,css文件可合併在一塊兒,但注意合併的順序配置。 moduleName:[combineCSSFile], ...:... components:{ component:[CombineJSFIles] ...:... } }, views:{//存放模板,開發生產統一爲一個文件 moduleName:[tempFiles], ...:... }, images:{//存放圖片 moduleName:[imgFiles], components:[imgFiles]//粒度再也不往下劃分 }, file:[files],//存放被下載的資源 test:{//測試 moduleName:[filesName]//fileName要以Spec結尾。例如 abcSpec.js 方便寫腳本 }, node_modules:{//存放開發環境 grunt依賴的插件 ...:... }, app.js//總的js文件,負責加載、配置以及開發和生產環境的切換。 app.css//總的css文件,可放在stylesheets文件夾下面。 main.html//index頁面 grunt.js//引入grunt來作集成化測試以及代碼的合併壓縮 新增 package.json }
思考:
咱們真需經過文件結構去劃分去記憶去調試代碼嗎?對一個前端項目來說。雖然剛開始認爲:這個是必須去作的事情。但後來,隨着思考的加深,文件結構這方面,反而是無關緊要的。咱們直接能夠經過chrome debug 來快速鎖定具體的文件甚至是具體的代碼在哪裏,咱們還真的迫切須要文件結構嗎?
前提:
全部用到的javascript文件會在用戶登陸前加載好。
依據現有代碼,每一個業務邏輯模塊都會將其引用暴露在handler全局變量下面。
公用組件可重寫
如何重構:業務邏輯代碼:
關於現有javascript邏輯代碼的重構,重點放在將現有js文件進行分拆,按照功能和模板細化到具體的文件夾下面去。
而後寫好grunt合併壓縮腳本,可將一個js模塊按照特定順序合併到一個js文件裏,而後,再將合併的文件壓縮後,放置在文件夾javascripts相應的模塊下面去。css:
在修改業務邏輯代碼的時候,儘可能將相應的css歸到相應的文件夾下。公共組件:
公共UI組件儘可能不使用width
,height
css樣式,多用margin
,padding
,max-width
等,無特殊狀況下,不要使用id對組件進行索引,多使用class。寫公共組件的大致格式以下:
//組件可不提供命名衝突處理,儘可能人爲避免衝突,命名格式爲name+"Mod" //例如:showDialogMod //參數若是超過三個的話,使用{}來替代 //須要寫註釋,最好在註釋中,給個使用例子 var componentName=(function(args){ 'use strict'; //... //... return {//如需對組件進行操做(例如對組件中的值進行從新賦值),至少要返回dom引用,更好的方案是返回相應的操做方法 //...:... } })
注意:
寫組件的時候,不要使用jquery,用原生瀏覽器提供的方法,畢竟咱們沒法預言會不會出現更好的前端框架。
不實現
不實現也就是使用已有代碼的流轉方式:用戶經過view觸發事件>>導向至相應的controller->組裝數據,發送ajax請求->請求返回->(獲取模版->根據模板渲染數據)->改動與之有牽連view。括號內表示可能不須要的步驟。
例如:在記錄內容展現頁面刪除這條記錄,就須要更新當前模板,以及更新記錄列表內的數據。實現
業務邏輯代碼的流轉方式會變成:用戶經過view觸發事件>>導向至相應的controller->組裝數據,發送ajax請求->請求返回->修改緩存model。
須要實現一批filter來對顯示數據和model數據進行轉換。
avalon
源碼4000,易掌控,不會破壞現有數據流轉和模板,但頁面的渲染方式會發生改變。可經過$watch
的運用來減小代碼重構的難度。修改幅度相較其餘mvc框架小。angular
須要根據angular對項目結構修改進行,還須要學習scope、directive 等概念,且渲染方式會更改,要本身實現一套router,簡單的使用ng-include沒法知足頁面緩存的現狀。ember
不推薦。須要改動的地方太多,最致命的是,它是對dom侵入的,不易於小幅度修改現有項目。backbone
屬於輕量級的,須要引入underscore.js
。render函數會有較多的改動。編程的重心會轉移到view展現的編寫以及和服務器請求的匹配(backbone按照restful api 設計),雖然代碼量不會減小太多,但代碼結構會清晰不少,underscore.js提供script模板渲染。
本身寫
不具有短時間內開發一個較爲完善的mvc框架的技術儲備。
注意:
以上的實現,對傳輸的數據結構的規整性和方式都有必定的要求,對於現有的關於歷史方面等不須要進行監聽的數據,要作相應的處理。
以上框架,除了avalon
,都須要爲服務器請求過來的數據作適配器(angular
的$resource
要更改)。
前提:
模板使用的流程:獲取模板(若是已緩存,則從緩存中獲取模板),渲染模板(String.replace的增強版),將渲染後的模板添加到dom中。
重構前提:
可大規模的合併模板
模板內能夠不容許擁有js代碼片斷(簡單一點的,例如onclick="abc()"
能夠有)。即便容許有js代碼片斷,也不容許js代碼片斷可被渲染。
chrome debug熟練使用
如何重構:去除模板id
前端id的做用是用來標識dom全局惟一變量,是用來作dom結構和邏輯塊劃分的,不能拿來作數據索引轉換,並且因爲頁面的轉換方式,沒法肯定,某一個公共模板是否有多個實例存在於當前dom下,爲了解決這個問題。出現了構建模板間的溝通機制
以及修改模板命名
。
構建模板間的溝通機制
TODO:
沒有雙向綁定所致使的額外手段
主要功能:防止公共模板(尤爲存在模板以id做爲索引)多個實例存在於dom時,操做紊亂。如今的想法是,作個當前系統運行時模板狀態集合以及模板操做的工具集。
模板集合的數據結構:
{ tempName:[ { status:$num,//表明當前的模板是在顯示,仍是被隱藏,被銷燬的會被直接幹 node:$document,//document引用 path:$stirng,//格式 nodeName[id|className] 整個路徑都小寫,父div索引 } ] } }
模板操做的工具集的功能:
可按照模板名稱和加載當前模板(模板加載方式是$(div).html(template)
)的父div element或索引來查到具體模板實例。
封裝個具體查詢模板下dom的方法,方便操做,要兼容jquery。
封裝模板加載函數,用來替換當前的模板加載方式,要兼容jquery。
修改模板命名
因爲沒有比較好的文件結構,模板命名就變得尤其重要,爲此,咱們能夠適當的在模板內添加一些註釋(註釋的主要做用:經過debug頁面元素,能夠快速查找到模板文件)。
重寫模板渲染流程
TODO:
現有的模板渲染函數過於簡單,也爲了減小模板不容許寫js所帶來的麻煩,須要重寫此函數以及添加模板filter機制。
filter機制:就是在讀取模板的時候,若是遇到自定義的標籤,就將其進行替換,並在模板加載到dom後,當即加載相應的js特效(這個地方遇到的問題,是如何辨識以及保存相應的dom信息,html comments?)。
重寫後的渲染函數要達到:
/** * 支持for循環和if斷定 。這個屬於額外的,可在實現基礎功能後,再來作這個。 * option 選項:{ * method:'after|html|before',//模板加載方式,默認html 兼容jquery語法 * dataFill:$fn|$string,//當遇到要渲染的數據爲undefined或null是,要作的處理,默認渲染成""。 * interpolate: /\{\{(.+?)\}\}/g //自行改寫匹配內容 默認匹配{{...}} * *} * * * @data #object 數據 * @elem #document * @callback #func 可選 渲染成功後的回調函數 * @option #ojbect 可選 配置 * * return obj 用到的filter引用,數據結構待思考 */ function render(data,elem,callback,option){ //...實現 //...修改模板狀態,要考慮模板嵌套的問題 }
實現可參考 underscore.js的template函數。或者avalon.js的bindingHandlers. each處理。
合併模板
模板的不能太過單薄,一個頁面展現出來後僅須要用到只有6到10個模板就能夠了。像<div id='abc'></div>
這種一行代碼一個模板文件的,注意刪除。
轉移模板中的javascript
爲何要轉移模板中的javascript代碼呢?很簡單,在模板中寫的javascript代碼沒法debug
如何重構:
TODO:
相似avalon的雙工綁定(觀察者模式)。但因爲和服務器交互的數據不會以model的形式進行緩存,就只能在dom之間封裝觀察者模式。
使用場景:兩個input的值同步。
作這個以前,要把模板操做的工具集寫好,在實現雙向的時候,要好好思考這麼一個場景,是否是有多個地方,對同一個數據源作了修改?
/** * 實現個簡單的,先不考慮集合的問題 * source/target爲object時,數據結構爲: * { * ele:node, * * attr:string,//attributeName,不填的話,根據ele是不是表單元素 默認爲 value或 text * } * @source object|node * @target object|node * * return object 返回一個object,包含,unwatch和fire方法,用來解除觀察和觸發觀察 * */ function watch(source,target){ } /** * 注意,來回觸發,形成的死循環問題。 * */ function duplexWatch(t1,t2){ return { "":"" } }