[toc]html
一個統一的好的編碼風格好過一打大牛
前端
你怎麼看別人的代碼呢?數據庫
每一個人都有本身的編碼風格,這個受到我的的學習以及工做歷程影響。編程
多人協同開發,不可避免的會遇到一個功能幾我的一塊兒開發,或者同一個功能,先後由不一樣的人開發。這個時候問題來了,若是是你,你會怎麼看待別人的代碼呢?呵呵,這其實已經不言而喻了。api
說實話對於我的來講,真不能怎麼樣,誰沒有一兩個盡是坑的項目呢,又有誰不是從最開始的垃圾代碼中慢慢提煉出本身的編碼風格呢。數組
可是對於一個項目,那太可怕的,不會有人會想要遇到這樣的項目,不少人會在項目風險爆發以前逃之夭夭,留下滿地狼藉,等待重建。瀏覽器
可是你真的但願你本身的項目,親手寫的代碼,最後會是這樣的結果?或者當你進入一家新公司的時候,居然拿不出一點能夠用來的炫耀的東西。緩存
若是每一回看到別人的代碼都痛不欲生,那麼咱們的人生還有什麼快樂。你要相信你不會永遠只關注於你本身的一個小角落。網絡
那麼咱們要怎麼作呢?若是你能看別人的代碼如同你本身的寫的,你寫的代碼每一行都是猶如ISO般的標準,那麼是否是會有這樣的感受:「我靠,我當初怎麼這麼傻」。app
這就是咱們如今要作的,
統一編碼風格
:不一樣的人寫同樣風格的代碼,對應業務處理有着相同的代碼邏輯。
講了這麼多,只是爲了闡述
統一編碼風格
的重要。在這裏我須要提出這樣一個概念:約定大於規範,及凡是在約定範圍裏的內容,必須被徹徹底底的實行,不然咱們的這些約定又有什麼意義呢。
如今定義的這些確定不會是所有,在之後的開發中必然會遇到更多的問題,從而提煉出更多的約定,這是好事情,也是正確的方向。讓咱們滿懷期待這樣盼望。
BB了半天,讓咱們進入正題,這篇文檔既是此次代碼重構的指導文檔,也會是前端小組的內部代碼規範定義文檔,用來給每個新加入的兄弟姐妹們套上一個足夠結實的轡頭,以約束大家過於奔放的想法,編程畢竟是一個嚴謹的工做。
DOM元素 縮進是兩個空格,便於在屏幕中展現更多的內容。
ng指令換行且縮進4個空格
<div id="" name="" class="" ng-show="" ng-click-"" ng-class=""> </div>
縮進是兩個空格
爲了方便理解,用[ ]表明一個空格。
var i = 0; // var[ ]i[ ]=[ ]0; var i, j; //var[ ]i,[ ]j; var i = 1, j = 2; //var[ ]i[ ]=[ ]1,[ ]j[ ]=[ ]2;
function定義的空格
函數表達式函數定義** var
不能省略**
var somting = function (p1, p2, p3) {s } //var[ ]somting[ ]=[ ]funtion[ ](p1,[ ]p2,[ ]p3)[ ]{}
for (var i=0; i<list.length; i++) { } //for[ ](var[ ]i=0;[ ]i<list.length;[ ]i++)[ ]{} for (key : obj) { } //for[ ](key[ ]:[ ]obj)[ ]{}
if () { } else { } //if[ ](true)[ ]{}[ ]else[ ]{}
var obj = { doSmting: function () { }, list: [{}, {}] } /* var[ ]obj[ ]=[ ]{ doSomting:[ ]function[ ]()[ ]{ }, list:[ ][{},[ ]{}] } */
var obj = {1: "", 2: ""} //var[ ]obj[ ]=[ ]{1:[ ]"",[ ]2:[ ]""}
js代碼中統一使用單引號,設計一些html模板時單引號內部可使用雙引號
html代碼中統一使用雙引號
這項原本是不想說的,可是做爲將來前端代碼規範文檔,這裏仍是須要提一下。
禁止一切無心義命名,禁止全局變量的定義,
rootScope中的變量須要統一在app.js中定義。
變量的命名,首先是這確定是一個名詞,
禁止使用中文拼音以及拼音縮寫
。遵循小駝峯命名,首字符小寫。scope底下禁止獨立變量的存在
。禁止省略寫法,var 必須寫
var isBoolean = true; //布爾值以is開頭 var arrayList = []; //數組以List結尾 $scope.type = 1; /**這種寫法是禁止使用的**/
函數通常是執行一組操做的代碼塊,因此用動名詞結合的方式命名,使用var name = function(agrs)。函數內部須要用到一些關鍵參數,做爲入參傳入,即便在scope中存在,也須要做爲入參傳入(好處是提升函數複用的可能)。
當前項目中不須要匿名函數(回調函數除外),以及自運行函數。
var getSomting = function (id) {} //獲取某個值 var loadSomting = function (agrs[]) {} //從後臺加載數據,涉及到restService var postSomting = function (obj{}) {} //提交表單操做,新建 var deleteSomting = function (id) {} //刪除操做 var putSomting = function (id, obj{}) {} //提交表單操做,修改 var initSomting = function () {} //初始化函數,通常是用來獲取某個獲取後臺的某個資源 $scope.views = { showSomting: function () {} chooseSomting: function () {} }
controller的命名爲首字母大寫的大駝峯規則(PS:這個寫法不知道是從哪裏流行起來的,彷佛你們都是這麼用的)。
factory的命名爲首字母小寫的小駝峯規則,英文命名,儘可能精簡同時語義明確。
同factory
這裏的全局常量須要定義在單獨的app_static.js文件下,方便統一管理以及協同開發。定義一個全局的常量約定以下:
命名:全大寫英文,用下劃線"_"分割單詞
定義方法: constant() 或者 value()
angular.module('myApp.static', []) .constant("USER_TYPE", {1: "我的", 2: "企業"})
全局的動態變量來自後臺提供的一些業務數據,大部分來自數據庫字典表,這裏使用factory的定義service的方式來實現全局動態變量的定義,約定以下:
命名:全大寫英文,用下劃線"_"分割單詞
定義方法: factory
angular.module('myApp.somting',[]) .factory("SOME_TYPES", function ($resource) { var SOME_TYPES = {}; $resource(url, 'GET').then(function (result) { SOME_TYPES = result }); return SOME_TYPES; })
註釋是用來解釋當前代碼的功能,一個好的註釋就是能讓人一眼看懂複雜的內部實現邏輯,而一個規範的註釋可以造成最後的api文檔。固然最重要的是註釋能夠你知道究竟該找誰痛扁一頓,因此凡寫過必留下痕跡。
寫在文件的最開頭
/** * @author * @date * @module name * @description */
寫在controller內部第一行
.controller(function () { /** * @author * @date * @controller name * @description */ })
寫在函數外面,入參和出參若是沒有就不要寫
/** * @fuction name * @param {agr[0]:"描述",agr[1]:"描述"} * @return {agr[0]:"描述",agr[1]:"描述"} * @description * @author * @date */ function () { return ; }
單行註釋
var obj = "" ; //參數定義註釋 function () { ... // 對函數內部代碼或者邏輯的特殊說明 ... }
基礎數據模型依賴於後臺接口提供的數據,同時根據前臺具體的業務場景或不變或轉換格式保存在前臺緩存對象下,同時也能夠將變化過的數據更新到當前數據模型中。
service中的函數命名,儘可能精簡,避免ById 之類的命名。
保留五種方法:getList,getDetail,post,update,delete
app.factory("userService",function ($q, $resource) { var service = { getList : function () { //來自後臺數據 return $q(function(resolve, reject){ //success resolve() //failed reject() }) } getDetail : function (id) { //來自後臺數據 return $q(function(resolve, reject){ //success resolve() //failed reject() }) }, post : function (user) { //來自後臺數據 return $q(function(resolve, reject){ //success resolve() //failed reject() }) }, update : function (id, user) { //來自後臺數據 return $q(function(resolve, reject){ //success resolve() //failed reject() }) }, delete : function (id) { //來自後臺數據 return $q(function(resolve, reject){ //success resolve() //failed reject() }) } } return service; })
<form name="myForm" ng-submit="postSomting" novalidate> <div> <span>用戶名:</span> <input type="text" name="username" placeholder="請輸入URL信息" ng-model="some.username" required ng-pattern="REG"/> <div> <div ng-messages="myForm.username.$error"> <div class="error" ng-message="required">用戶名不能爲空</div> <div class="error" ng-message="pattern">請輸入正確的用戶名</div> </div> </div> </div> <input type="submit" ng-disable="myForm.$validate" value="提交"> </form>
代碼塊的分號不可被省略
,由於考慮到之後的壓縮,混淆。
大部分的if判斷,else 分支都是有必定意義的,只有某一些時候是能夠省略的。if 直接return 能夠忽略。
if (true) return; if (true) return somtion;
當src和href中包含$scope中變量時,使用ng-src和ng-href避免錯誤的網絡請求
注
:正常的靜態資源地址不須要這樣處理。
每一個controller中都要定義 view 對象,即便是空的。
.controller(function($scope){ $scope.view = {} })
controller 禁止定義全局變量,變量只存在於函數內部,或者 view 上
代碼順序既是對於controller中的N多行代碼究竟誰先誰後的約定。順序依次是:
注:
只要是在scope中用到的變量所有須要最早聲明。
.controller(function () { /*scope底下的對象最早聲明*/ $scope.somting = {}; /*scope底下的function*/ $scope.doSomting = function () {} /*controller局部函數*/ var doSomting = function () {} /*controller的初始化函數定義*/ var run = function () {} /*運行初始化函數*/ run(); })
controller中的離散變量將經過scope.views(做爲試圖模型對象)統一控制,甚至某些複雜頁面視圖模型,能夠在views中用單獨的對象處理。
實際上針對數據模型,也有一篇正在寫的博客「angular項目中實現數據分層」
//頁面視圖控制數據模型 $scope.views = { somting: "", isSomting: true, chooseSomting: function () { this.sonting = ""; }, oneObj: { oneType: "", showOne: fucntion () { this.one = ""; } } } //後臺返回數據模型 $scope.somting = somtingService.get();
業務數據模型通常是有別於基礎數據模型和視圖數據模型,通常是包含視圖內容的數據對象,例如表單數據對象,或者被選中的某些數據,這些數據通常用於界面控制也會提取出接口參數用於交互。
$scope.somtingSelectedList = [{ id: 1, ... selected: true }, { id: 2, ... selected: true }, { id: 3, ... selected: false }...]
一些數據模型會有一些相應的操做,這個時候可使用數據對象來處理, 就函數以及數據自己包含在一個數據對象上。(
PS
:儘可能減小controller下面的孤立函數)
$scope.somting = { list: [{}], select: function(){}, delete: function(){}, getDate: function(){} }
大部分時候頁面初始化須要controller的一些賦值操做,以及數據請求。這部分初始操做定義成 run 函數。
注
:run是controller下的保留函數,無論有沒有用到,都要定義,並且必定不要綁定在 $scope 下
.controller(function(){ var run = function(){ } run(); })
計劃開一篇「ui-router使用心得」
使用$stateParams傳遞數據
//config中定義參數 $stateProvider.state('stateTo',{ url: '', templateUrl: '', params: {p1: '', p2: ''} }) //state.go $state.go('stateTo', {p1: '1', p2: '2'}) //controller中接收 controller(function($stateParams){ $stateParams.p1; $stateParams.p2; })
主要用來對controller依賴的service中的數據進行初次加載,同時避免因爲數據單例形成的數據不一樣步問題。
最近的一些使用,發現resolve的使用有一些侷限性,以及對代碼結構的一些限制,也在考慮是否引入resolve的概念。其實在contrlller上面的一些處理也能實現數據加載展現的效果。保留意見。
$stateProvider.state('stateTo', { url: '', templateUrl: '', resolve: { someService:"someService", init: function () { //方法名自定義,全部方法都會在頁面加載前被調用 someService.load(); } } })