在angular的服務中,有一些服務你不得不去了解,因為他可以說是ng的核心,而今天,我要介紹的就是ng的兩個核心服務,$parse和$compile。其實這兩個服務講的人已經很多了,但是100個讀者就有100個哈姆雷特,我在這裡講講自己對於他們兩個服務的理解。
大家可能會疑問,$eval呢,其實他並不是一個服務,他是scope裡面的一個方法,並不能算服務,而且它也基於parse的,所以只能算是$parse的另一種寫法而已,我們看一下ng源碼中$eval的定義是怎樣的就知道了
$eval: function(expr, locals) { return $parse(expr)(this, locals); },
相信看完源碼大家就明白了吧,好了,現在就開始兩種核心服務的講解了,如果感覺我說的不對的話,歡迎在留言區或私聊指出,免得禍害其他讀者。
再講這兩個服務的時候,我要先講一個在本貼的概念:上下文
我相信,很多人都聽過這個“上下文”,但是可能有點模糊,在我這裡給大家解釋解釋看看大家接不接受這個說法。
還記得angular的資料綁定嗎?例如:我現在有個有個叫TestCtrl的控制器,他的內容如下:
.controller('TestCtrl', function($scope) { $scope.test = "Boo!!!" })
而在html中我們的程式碼是這樣的
<body ng-controller="TestCtrl"> {{test}} </body>
var getter = $parse('user.name'); var setter = getter.assign; var context = {user:{name:'angular'}}; var locals = {user:{name:'local'}}; expect(getter(context)).toEqual('angular'); setter(context, 'newValue'); expect(context.user.name).toEqual('newValue'); expect(getter(context, locals)).toEqual('local');
getter(context)).toEqual('angular') //实际上就是 $parse('user.name')(context)
所以這句測試程式碼是成功的。 我們看第二個方法setter方法
setter(context, 'newValue');//实际上就是 $parse('user.name').assign(context, 'newValue') expect(context.user.name).toEqual('newValue');//测试数据上下文的值是否被改变
expect(getter(context, locals)).toEqual('local');//实际上就是$parse('user.name')(context, locals)
重新回到$eval這個地方,我們看待$eval源碼中可以看出$eval只有get功能,而沒有set功能,但是有些時候我們可以選擇傳遞第二個上下文,來達到修改值得效果。
在這裡$parse服務就已將說完了,接下來就是$compile
------------------------------ --------------------
如果你了解了$parse的概念之後,我想$compile也差不多理解了,其實和$parse很像。但他是解析一段html程式碼的,他的功能就是把死模板變成活模板,也是指令的核心服務。
例如你有一段html程式碼
$compile('死模板')(上下文物件),這樣就將死模板編程了活模板,你就可以對這段活的html程式碼做操作了,例如增加到當前節點,等等。
但是在指令中,她會回傳兩個函數pre-link和post-link
第一個執行的是pre-link,它對於同一個指令的遍歷順序是從父節點到子節點的遍歷,在這個階段,dom節點還沒有穩定下來,無法做一些綁定事件的操作,但是我們可以在這裡進行一些初始化資料的處理。
第二個執行的是post-link,也就是我們常說的link函數,他是從子節點到父節點遍歷的,在這個階段,DOM節點已經穩定下來了,我們通常會在這裡進行很多的操作。