此篇文章因為一開始使用mac pages製作,後來再轉成html輸出至此,格式很亂(因為我還不太會用pages),因此code的部分皆使用純文字貼上,請見諒
Scope:use ng-include
angularJs的Scope繼承概念在一般情形下是很直觀的,然而在2-way-data binding的primitive情況下有些必須注意,以下來做些ng-include的小測試:
首先我們準備檔案index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<!-- class="show-scope-demo"-->
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body ng-controller="scopeCtrl as ctrl">
<h1>Hello!Scope</h1>
use myPrimitive: <input ng-model="myPrimitive">
use myObject.aNumber: <input ng-model="myObject.aNumber">
<p>myPrimitive:{{myPrimitive}}</p>
<p>myObject.aNumber:{{myObject.aNumber}}</p>
</body>
再來準備script.js:
var app = angular.module('myApp',[]);
app.controller('scopeCtrl' ,['$scope', function($scope){
$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};
$scope.setMyPrimitive = function(value) {
$scope.myPrimitive = value;
}
}]);
執行測試:
- 當一開始載入後,一切如我們所想,兩個input輸入框與下方顯示都很完美的反應我們設定的初始值:
- 接下來我們試驗者改變兩個輸入框,將它們各自改變為22與66,一切如我們預期般執行
接下來我們試驗使用ng-include方式,首先新增tpl1.html:
myPrimitive:
<input ng-model="myPrimitive">
<br>
再新增tpl2.html:
myObject.aNumber:<input ng-model="myObject.aNumber">
變更原先index.html(body部分):
<body ng-controller="scopeCtrl as ctrl">
<h1>Use ng-include</h1>
<div ng-include src="'tpl1.html'"></div>
<div ng-include src="'tpl2.html'"></div>
<p>myPrimitive:{{myPrimitive}}</p>
<p>myObject.aNumber:{{myObject.aNumber}}</p>
</body>
準備完畢,再一次執行測試:
- 當一開始載入後,一切如我們所想,兩個input輸入框與下方顯示都很完美的反應我們設定的初始值:
- 然而,這次我們一樣改變兩個輸入框,將它們各自改變為22與66,卻發生了如下的情況
第一個myPrimitive沒有如果們預想的變更成功,這是怎麼一回事?
首先,我們知道使用ng-include會增加新的scope,因此一開始(初始載入後)的內部結構如下:
此時除了原先的RootScope與ParentScope以外,又多了兩個ChildScope,分別為ng-include=‘tpl1.html’與ng-include=‘tpl12.html’所產生。
而當我們變更輸入框的數值的時候,輸入框2(myObject.aNumber)還是維持與之前一樣的方式,參考至$parent.myObject.aNumber並且更改了他;然而輸入框1(myPrimitive)就不是這麼一回事了,他首先確認所屬的ChildScope1是否擁有myPrimitive這個變數,發現沒有,此時並不會如我們預想般自動去尋找$parent.myPrimitive,而是直接在ChildScope1下建立了myPrimitive,並且assign新值:22,因此目前內部結構變更如下:
以上的問題全部都不是AngularJS才有的,屬於AngularJS的只有使用ng-include,建立了新scope;而不如我們預想般尋找$parent.myPrimitive並且變更而是產生新的myPrimitive則是Javascript中Prototypal Inheritance的概念(請參考連結文章,有很詳盡的說明)。
那麼如何去變更$parent.myPrimitive呢?有以下兩種方式:
- 一定使用關鍵字$parent
- 使用function()
以下我們繼續變更code測試上面兩個方式,首先測試第一種方式:使用$parent
變更tpl1.html:
myPrimitive:
<input ng-model=“$parent.myPrimitive">
<br>
測試,變更輸入框為22與66:
執行成功!接下來測試第二種方式:使用function()
變更tp1.html:
myPrimitive:
<input ng-model="myPrimitive">
<button ng-click="setMyPrimitive(myPrimitive)">$scope.setMyPrimitive()</button>
<br>
變更script.js:
var app = angular.module('myApp',[]);
app.controller('scopeCtrl' ,['$scope', function($scope){
$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};
$scope.setMyPrimitive = function(value) {
$scope.myPrimitive = value;
}
注意在這邊tpl1.html中的<input ng-model=“myPrimitive”>不是使用$parent.myPrimitive
因為沒有使用方法1的$parent.myPrimitive 因此myPrimitive如上所說一樣維持50
這時我們按下<button>,呼叫$scope.setMyPrimitive(),確實變更成我們要的22了!