精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Ember.js 的視圖層

開發 前端
本指導會詳盡闡述 Ember.js 視圖層的細節。為想成為熟練 Ember 開發者準備,且包 含了對于入門 Ember 不必要的細節。

本指導會詳盡闡述 Ember.js 視圖層的細節。為想成為熟練 Ember 開發者準備,且包 含了對于入門 Ember 不必要的細節。

Ember.js 有一套復雜的用于創建、管理并渲染連接到瀏覽器 DOM 上的層級視圖的系 統。視圖負責響應諸如點擊、拖拽以及滾動等的用戶事件,也在視圖底層數據變更時更 新 DOM 的內容。

視圖層級通常由求值一個 Handlebars 模板創建。當模板求值后,會添加子視圖。當 那些 子視圖求值后,會添加它們的子視圖,如此遞推,直到整個層級被創建。

即使你并沒有在 Handlebars 模板中顯式地創建子視圖,Ember.js 內部仍使用視圖系 統更新綁定的值。例如,每個 Handlebars 表達式 {{value}} 幕后創建一個視圖, 這個視圖知道當值變更時如何更新綁定值。

你也可以在應用運行時用 Ember.ContainerView 類對視圖層級做出修改。一個容器 視圖暴露一個可以手動修改的子視圖實例數組,而非模板驅動。

視圖和模板串聯工作提供一套用于創建任何你夢寐以求的用戶界面的穩健系統。最終用 戶應從諸如當渲染和事件傳播是的計時事件之類的復雜東西中隔離開。應用開發者應可 以一次性把他們的 UI 描述成 Handlebars 標記字符串,然后繼續完成他們的應用,而 不必煩惱于確保它一直是最新的。

它解決了什么問題?

子視圖

在典型的客戶端應用中,視圖同時在本身和 DOM 中表示嵌套的元素。在解決這個問題 的天真方案中,獨立的視圖對象表示單個 DOM 元素,專門的引用解決不同種類的視圖 保持對概念中嵌套在它們內部的視圖的跟蹤。

這里是一個簡單的例子,表示一個應用主視圖,里面有一集合嵌套視圖,且獨立的元素在集合內嵌套。

 

 這個系統第一眼看上去毫無異樣,但是想象我們要在上午 8 點而不是上午 9 點開放喬 的七鰓鰻小屋。在這種情況下,我們會想要重新渲染應用視圖。因為開發者需要構建指 向在一個特殊基礎上的子視圖的引用,這個重渲染過程存在若干問題。

為了重新渲染應用視圖,應用視圖也必須手動重新渲染子視圖并重新把它們插入到應用 視圖的元素中。如果實現得完美,這個過程會正常工作,但它依賴于一個完美的,專門 的視圖層級實現。如果任何一個視圖沒有精確地實現它,整個重新渲染過程會失敗。

為了避免這些問題,Ember 的視圖層級從概念上就帶有子視圖的烙印。 

  

 當應用時圖重新渲染時,Ember 而不是應用代碼負責重新渲染并插入子視圖。這也意味 著 Ember 可以為你執行任何內存管理,比如清理觀察者和綁定。

這不僅在一定程度上消滅了樣板代碼,也破除了有瑕疵的視圖層級實現帶來的未期失敗的可能。

#p#

事件委派

在過去,web 開發者已經用在獨立的單個元素上添加事件監聽器來獲知什么時候用戶與 它們交互。例如,你會有一個 <div> 元素,其上注冊了一個當用戶點擊它時觸發的 函數。

盡管如此,這個途徑在處理大數量交互元素上不會縮放。比如,想象一個帶有 100 個 <li><ul> ,每個項目后都有一個刪除按鈕。既然所有的這些項目行為都是一 致的,為每個刪除按鈕創建共計 100 個事件監聽器無疑是低效的。   

 

 

 

 

 

 

 

 要解決這個問題,開發者發現了一種名為“事件委派”的技術。你可以在容器元素上注冊 一個監聽器并使用 event.target 來識別哪個元素是用戶點擊的,而不是為問題中的 每個項目創建一個監聽器。

 

 

 

 

 

 

實現這有一些微妙,因為一些事件(比如 focusblurchange )不會冒 泡。幸運的是,jQuery 已經徹底解決了這個問題;用 jQuery 的 on 方法可以可靠 地處理所有原生瀏覽器事件。

其它 JavaScript 框架用兩種方法中的其一來處理這個問題。第一種是,它們要你自己 實現原生解決方案,為每個項目創建獨立的視圖。當你創建視圖,它在視圖的元素上設 置一個監聽器。如果你有一個含有 500 個項目的列表,你會創建 500 個視圖并且每個 視圖都會在它自己的元素上設置一個監聽器。

第二種方法是,框架在視圖層內置事件委派。當創建一個視圖,你可以提供一個事件列 表來在事件發生時委派一個方法來調用。這只剩下識別接受事件的方法的點擊上下文 (比如,列表中的哪個項目)。

你現在要面對兩個令人不安的選擇:為每個項目創建一個新視圖,這樣會喪失事件委派 的優勢,或是為所有項目創建單個視圖,這樣必須存儲 DOM 中底層 JavaScript 的信息。

要解決這個問題,Ember 用 jQuery 把所有事件委派到應用的根元素(通常是文檔的 body )。當一個事件發生,Ember 識別出最近的處理事件視圖并調用它的事件處理 器。這意味著你可以創建視圖來保存一個 JavaScript 上下文,但仍然從事件委派上受 益。

進一步地,因為 Ember 只為整個 Ember 應用注冊一個事件,創建新視圖永遠都不需要 設置事件監聽器,這使得重渲染高效且免于出錯。當視圖有一個子視圖,這也意味著不 需要手動取消委派重新渲染過程中替換掉的視圖。

渲染管道

大多數 web 應用用特殊的模板語言標記來指定它們的用戶界面。對于 Ember.js,我們 已經完成用可在值修改的時候自動更新模板的 Handlebars 模板語言來編寫模板。

雖然顯示模板的過程對開發者是自動的,但其遮蓋了把原始模板轉換為最終模板、生成 用戶可見的 DOM 表示的一系列必要步驟。

這是 Ember 視圖的近似生命周期: 

 

 

 

 

 

1. 模板編譯

應用的模板通過網絡加載或以字符串形式作為應用的載荷。當應用加載時,它發送模板 字符串到 Handlebars 來編譯成函數。一經編譯,模板函數會被保存,且可以被多個視 圖重復使用,每次都它們都需重新編譯。

這個步驟會在應用中服務器預編譯模板的地方發出。在那些情況下,模板不作為原始的 人類可讀的模板傳輸,而是編譯后的代碼。

因為 Ember 負責模板編譯,你不需要做任何額外的工作來保證編譯后的模板可以重用。

#p#

2. 字符串的連接

當應用在視圖上調用 appendappendTo 時,一個視圖渲染過程會被啟動。 appendappendChild 調用 安排 視圖渲染并在之后插入。這允許應用中的 延遲邏輯(譬如綁定同步)在渲染元素之前執行。

要開始渲染過程,Ember 創建一個 RenderBuffer 并把它呈遞給視圖來把視圖的內容 附加到上面。在這個過程中,視圖可以創建并渲染子視圖。當它這么做時,父視圖創建 并分配一個 RenderBuffer 給子視圖,并把它連接到父視圖的 RenderBuffer 上。

Ember 在渲染每個視圖前刷新綁定同步隊列。這樣,Ember 保障不會渲染需要立即替換 的過期數據。

一旦主視圖完成渲染,渲染過程會創建一個視圖樹(即“視圖層級”),連接到緩沖區樹 上。通過向下遍歷緩沖區樹并把它們轉換為字符串,我們就有了一個可以插入到 DOM 的字符串。

這里是一個簡單的例子: 

 

 

 

 

除子節點之外(字符串和其它 RenderBuffer ), RenderBuffer 也會封裝元素標 簽名稱、id、class、樣式和其它屬性。這使得渲染過程修改這些屬性(例如樣式)成 為可能,即使在子字符串已經渲染完畢。因為這些屬性的許多都可以通過綁定(例如用 bindAttr )控制,這使得渲染過程穩健且透明。

3. 元素的創建和插入

在渲染過程的最后,根視圖向 RenderBuffer 請求它的元素。 RenderBuffer 獲得 它的完整字符串并用 jQuery 把它轉換成一個元素。視圖把那個元素分配到它的 element 屬性并把把它放置到 DOM 中正確的位置( appendTo 指定的位置,如果 應用使用 append 即是應用的根元素)。

雖然父視圖直接分配它的元素,但每個子視圖惰性查找它的元素。它通過查找 id 匹 配它的 elementId 屬性的元素來完成這。除非顯式提供,渲染過程生成一個 elementId 屬性比你更分配它的值給視圖的 RenderBuffer ,RenderBuffer 允 許視圖按需查找它的元素。

4. 重新渲染

在視圖把自己插入到 DOM 后,Ember 和應用都會要重新渲染視圖。它們可以在視圖上 調用 rerender 方法來出發一次重渲染。

重新渲染會重復上面的步驟 2 和步驟 3,有兩點例外:

  • rerender 用新元素替換已有的元素,而不是把元素插入到顯式定義的位置。
  • 除了渲染新元素,它也刪除舊元素并銷毀它的子元素。這允許 Ember 在重新渲染視 圖時自動處理撤銷合適的綁定和觀察者。這使得路徑上的觀察者可行,因為注冊和撤銷 注冊所有的嵌套觀察者都是自動的。

最常見的導致視圖重新渲染的原因是當綁定到 Handlebars 表達式( {{foo}} )變 更。Ember 內部為每個表達式創建一個簡單的視圖,并且在路徑上注冊一個觀察者。當 路徑變更時,Ember 用新值更新那個區域的 DOM。

另一個常見的情況是一個 {{#if}}{{#with}} 塊。當渲染一個模板時,Ember 為這些塊輔助標創建虛擬的視圖。這些虛擬的視圖不會出現在公共可訪問的視圖層級里 (當從視圖獲取 parentViewchildViews 時),但它們的存在啟用了一致的重 渲染。

當傳遞到 {{#if}}{{#with}} 的路徑變更,Ember 自動重新渲染虛擬視圖替換 它的內容,重要的是,也會銷毀所有的子視圖來釋放內存。

除了這些情景,應用有時也會要顯式地重新渲染視圖(通常是一個 ContainerView ,見下)。在這種情況下,應用可以直接調用 rerender ,且 Ember 會把一項重渲染工作加入隊列,用相同的語義元素。

這個過程像是這樣:

 

 

  #p#

視圖層級

父與子

當 Ember 渲染一個模板化的視圖,它會生成一個視圖層級。讓我們假設已有一個模板 form

原文鏈接:

  1. {{view App.Search placeholder="Search"}} 
  2. {{#view Ember.Button}}Go!{{/view}} 

然后我們像這樣把它插入到 DOM 中:

  1. var view = Ember.View.create({ 
  2.   templateName: 'form' 
  3. }).append(); 

這會創建一個如下小巧的視圖等級:  

 

 

 

你可以用 parentViewchildViews 屬性在視圖層級中游走。

  1. var children = view.get('childViews') // [ <App.Search><Ember.Button> ] 
  2. children.objectAt(0).get('parentView') // 視圖 

一個常見的 parentView 使用方法是在子視圖的實例里。

  1. App.Search = Ember.View.extend({ 
  2.   didInsertElement: function() { 
  3.     // this.get('parentView') 指向 `view` 
  4.   } 
  5. }) 

生命周期鉤子

為了容易地在視圖的生命周期的不同點上執行行為,有若干你可以實現的鉤子。

  • willInsertElement: 這個鉤子在視圖渲染后插入 DOM 之前調用。它不提供對視圖的 element 的訪問。
  • didInsertElement: 這個鉤子在視圖被插入到 DOM 后立即調用。它提供到視圖的 element 的訪問,且對集成到外部庫非常有用。任何顯式的 DOM 設置代碼應限于這個鉤子。
  • willDestroyElement: 這個鉤子在元素從 DOM 移除前立即調用。這提供了銷毀任何與 DOM 節點關聯的外部狀態的機會。像 didInsertElement 一樣,它對于集成外部庫非常有用。
  • willRerender: 這個鉤子在視圖被重新渲染前立即調用。如果你想要在視圖被重新渲染前執行一些銷毀操作,這會很有用。
  • becameVisible: 這個鉤子在視圖的 isVisible 或它的祖先之一的 isVisible變為真值,且關聯的元素也變為可見后調用。注意這個鉤子只在所有可見性由 isVisible 屬性控制的時候可靠。
  • becameHidden: 這個鉤子在視圖的 isVisible 或它的祖先之一的 isVisible變為假值,且關聯的元素也變為隱藏后調用。注意這個鉤子只在所有可見性由 isVisible 屬性控制的時候可靠。

應用可以通過在視圖上定義一個與鉤子同名的方法來實現鉤子?;蛘?,在視圖上為鉤子 注冊一個監聽器也是可行的。

  1. view.on('willRerender', function() { 
  2.   // do something with view 
  3. }); 

虛擬視圖

正如上文所述,Handlebars 在視圖層級內創建視圖來表現綁定值。每次你使用 Handlebars 表達式,無論是一個簡單值還是一個諸如 {{#with}}{{#if}} 的 塊表達式,Handlebars 會創建一個新視圖。

因為 Ember 只把這些視圖用于內部簿記,它們對于視圖的公共 parentViewchildViews API 是隱藏的。公共視圖層級只反射用 {{view}} 輔助標記或通過 ContainerView 創建的視圖(見下)。

例如,考慮下面的 Handlebars 模板:

  1. <h1>Joe's Lamprey Shack</h1> 
  2. {{controller.restaurantHours}} 
  3. {{#view App.FDAContactForm}} 
  4.   如果你在喬的七鰓鰻小屋用餐后不適,請用下面的表格向 FDA 提交申訴。 
  5.   {{#if controller.allowComplaints}} 
  6.     {{view Ember.TextArea valueBinding="controller.complaint"}} 
  7.     <button {{action submitComplaint}}>提交</button> 
  8.   {{/if}} 
  9. {{/view}} 

渲染這個模板會創建這樣的層級:  

 

 

 幕后,Ember 跟蹤為 Handlebars 表達式創建的額外的虛擬視圖:  

 

 

 

 #p#

TextArea 中, parentView 會指向 FDAContactForm ,并且 FDAContactFormchildViews 會是一個只包含 TextArea 的數組。

你可以通過 _parentView_childViews 來查看內部視圖層級,這會包含虛擬視 圖:

  1. var _childViews = view.get('_childViews'); 
  2. console.log(_childViews.objectAt(0).toString()); 
  3. //> <Ember._HandlebarsBoundView:ember1234> 

警告! 你不應該在應用代碼中依賴于這些內部 API。它們會在任何時候更改并且 沒有任何公共合約。返回值也不能被觀察或被綁定。它可能不是 Ember 對象。如果覺 得有使用它們的需求,請聯系我們,這樣我們可以為你的使用需求暴露一個更好的公共 API。

底線:這個 API 就像是 XML。如果你覺得你需要用到它,那么你很可能沒有足夠理解 問題。三思!

事件冒泡

視圖的一個任務是響應原始用戶事件并把它們翻譯成對你應用而言有語義的事件。

例如,一個刪除按鈕把原始的 click 事件翻譯成應用特定的“把這個元素從數組中刪 除”。

為了響應用戶事件,創建一個視圖的子類來把事件實現為方法:

  1. App.DeleteButton = Ember.View.create({ 
  2.   click: function(event) { 
  3.     var stateManager = this.getPath('controller.stateManager'); 
  4.     var item = this.get('content'); 
  5.     stateManager.send('deleteItem', item); 
  6.   } 
  7. }); 

當你創建一個新的 Ember.Application 實例,它用 jQuery 的事件委派 API 給每個 原生瀏覽器事件注冊一個事件處理器。當用戶觸發一個事件,應用事件分配器會找出離 事件最近的視圖并實現那個事件。

一個視圖通過定義與事件同名的方法來實現事件。當事件名稱由多個詞組成(如 mouseup )方法名會用 Camel 命名法把事件名作為方法名( mousUp )。

事件會在視圖層級中冒泡,直到事件到達根視圖。一個事件處理器可以用與常規 jQuery 事件處理器相同的技術來停止事件傳播:

  • 在視圖中 return false
  • event.stopPropagation

例如,假設你已經定義了如下的視圖類:

  1. App.GrandparentView = Ember.View.extend({ 
  2.   click: function() { 
  3.     console.log('Grandparent!'); 
  4.   } 
  5. }); 
  6. App.ParentView = Ember.View.extend({ 
  7.   click: function() { 
  8.     console.log('Parent!'); 
  9.     return false
  10.   } 
  11. }); 
  12. App.ChildView = Ember.View.extend({ 
  13.   click: function() { 
  14.     console.log('Child!'); 
  15.   } 
  16. }); 

這是使用它們的 Handlebars 模板。

  1. {{#view App.GrandparentView}} 
  2.   {{#view App.ParentView}} 
  3.     {{#view App.ChildView}} 
  4.       <h1>點擊這里!</h1> 
  5.     {{/view}} 
  6.   {{/view}} 
  7. {{/view}} 

如果你點擊 <h1> ,你會在瀏覽器控制臺里看見下面的輸出:

  1. Child! 
  2. Parent! 

你可以看出 Ember 在接受事件的最深層級視圖上調用了處理器。事件繼續上浮到 ParentView ,但不會到達 GrandparentView 因為 ParentView 從它的事件處理 器中返回了 false 。

你可以使用常規事件冒泡技術來實現常見的模式。例如,你可以實現一個帶有 submit 方法的 FormView 。因為瀏覽器在用戶向文本域輸入回車的時候會觸發 submit 事件,在表單視圖上定義一個 submit 方法會“剛好完成任務”。

  1. App.FormView = Ember.View.extend({ 
  2.   tagName: "form"
  3.   submit: function(event) { 
  4.     // 會在任何用戶觸發瀏覽器的 
  5.     // `submit` 方法時被調用 
  6.   } 
  7. });
  1. {{#view App.FormView}} 
  2.   {{view Ember.TextFieldView valueBinding="controller.firstName"}} 
  3.   {{view Ember.TextFieldView valueBinding="controller.lastName"}} 
  4.   <button type="submit">確定</button> 
  5. {{/view}} 

#p#

添加新事件

Ember 內置了如下原生瀏覽器事件的支持:

事件名

方法名

touchstart touchStart
touchmove touchMove
touchend touchEnd
touchcancel touchCancel
keydown keyDown
keyup keyUp
keypress keyPress
mousedown mouseDown
mouseup mouseUp
contextmenu contextMenu
click click
dblclick doubleClick
mousemove mouseMove

事件名

方法名

focusin focusIn
focusout focusOut
mouseenter mouseEnter
mouseleave mouseLeave
submit submit
change change
dragstart dragStart
drag drag
dragenter dragEnter
dragleave dragLeave
dragover dragOver
drop drop
dragend dragEnd

當你創建一個新應用時,你可以向事件分配器添加額外的事件:

  1. App = Ember.Application.create({ 
  2.   customEvents: { 
  3.     // 添加 loadedmetadata 媒體播放器事件 
  4.     'loadedmetadata'"loadedMetadata" 
  5.   } 
  6. }); 

要使這能對自定義事件奏效,HTML5 規范必須定義事件為“bubbling”,否則 jQuery 必 須為這個事件提供一個事件委派折中方案。

模板化視圖

如同迄今你在本指導中所見,你在應用中會用的大多數視圖是依靠模板的。當使用模板 時,你不需要編寫你的視圖層級,因為模板會為你創建它。

渲染時,視圖模板可以把視圖附加到它的子視圖數組中。模板的 {{view}} 輔助標記 內部會調用視圖的 appendChild 方法。

調用 appendChild 會做兩件事:

  1. 把視圖添加到 childViews 數組。
  2. 立即渲染子視圖并把它添加到父視圖的渲染緩沖區。

 

 

 

 

你不應該在視圖離開渲染狀態后調用 appendChild 。模板渲染出“混合內容”(包含 視圖和純文本),所以當渲染過程完成后,父視圖不知道到底把新的子視圖插入到哪 里。

 在上例中,想象試圖把一個新視圖插入到父視圖的 childViews 數組中。它應該立即 放在 App.MyView 的閉合標簽 </div> 后?還是在整個視圖的閉合標簽 </div> 后?這個答案不總是正確的。

因為這種含糊性,創建視圖層級的唯一方法就是用模板的 {{view}} 輔助標記,它總 是把視圖插入到相對任何純文本的正確位置。

雖然這個機制對大多數情景奏效,偶爾你也會想要直接程序控制一個視圖的子視圖。在 這種情況下,你可以用 Ember.ContainerView ,它顯式地暴露了實現此目的的 API。

#p#

容器視圖

容器視圖不包含純文本。它們完全由子視圖(可能依靠模板)構成。

ContainerView 暴露兩個用于修改本身內容的公共 API:

  • 一個可寫的 childViews 數組,你可以把 Ember.View 實例插入到其中。
  • 一個 currentView 屬性,設置時會把新值插入到子視圖數組。如果存在早先的 currentView 值,它會被從 childViews 數組刪除。

這里是一個用 childViews API 創建新視圖的例子,由假想的 DescriptionView 開始,并可以在任何時候用 addButton 方法添加一個新按鈕:

  1. App.ToolbarView = Ember.ContainerView.create({ 
  2.   init: function() { 
  3.     var childViews = this.get('childViews'); 
  4.     var descriptionView = App.DescriptionView.create(); 
  5.     childViews.pushObject(descriptionView); 
  6.     this.addButton(); 
  7.     return this._super(); 
  8.   }, 
  9.   addButton: function() { 
  10.     var childViews = this.get('childViews'); 
  11.     var button = Ember.ButtonView.create(); 
  12.     childViews.pushObject(button); 
  13.   } 
  14. }); 

如你在上例中所見,我們以兩個視圖初始化 ContainerView ,并且可以在運行時添 加額外的視圖。存在一個方便的捷徑來設置視圖,而不用覆蓋 init 方法:

  1. App.ToolbarView = Ember.ContainerView.create({ 
  2.   childViews: ['descriptionView''buttonView'], 
  3.   descriptionView: App.DescriptionView, 
  4.   buttonView: Ember.ButtonView, 
  5.   addButton: function() { 
  6.     var childViews = this.get('childViews'); 
  7.     var button = Ember.ButtonView.create(); 
  8.     childViews.pushObject(button); 
  9.   } 
  10. }); 

如上,當用這個速記方法時,你把 childViews 指定為一個字符串數組。在初始化 時,每個字符串會作為在查找視圖實例或類的關鍵字。那個視圖會被自動實例化,如果 必要,會加入到 childViews 數組中。  

 

          

  1. {{#if controller.isAuthenticated}} 
  2.   <h1>歡迎 {{controller.name}}</h1> 
  3. {{/if}} 
  4. {{#with controller.user}} 
  5.   <p>你有 {{notificationCount}} 條通知。</p> 
  6. {{/with}} 

在上面的模板中,當 isAuthenticated 屬性從 false 變為 true 時,Ember 會 重新渲染這個塊,用原始的外部作用域作為它的上下文。

{{#with}} 輔助標記把它的塊的上下文修改為當前控制器的 user 屬性。當 user 屬性被修改。Ember 重新渲染塊,并用 controller.user 的新值作為它的上 下文。

#p#

視圖作用域

除了 Handlebars 上下文,Ember 中的模板也有當前視圖的概念。無論當前上下文是什 么, view 屬性總是引用到最近的視圖。

注意 view 屬性不會引用由 {{#if}} 之類的塊表達式創建的內部視圖。這允許你 區分 Handlebars 上下文,在 Handlebars 中和在視圖層級中的工作方式是一樣的。

因為 view 指向一個 Ember.View 實例,你可以用 view.propertyName 之類的 表達式訪問視圖上的任何屬性。你可以用 view.parentView 訪問視圖的父視圖。

例如,想象你有一個帶有如下屬性的視圖:

  1. App.MenuItemView = Ember.View.create({ 
  2.   templateName: 'menu_item_view'
  3.   bulletText: '*' 
  4. }); 

……和下面的模板:

  1. {{#with controller}} 
  2.   {{view.bulletText}} {{name}} 
  3. {{/with}} 

盡管 Handlebars 上下文已經變為當前的控制器,你仍然可以用 view.bulletText 訪問視圖的 bulletText 。

模板變量

迄今為止,我們已經在 Handlebars 模板中邂逅了 controller 屬性。它是從哪來的呢?

Ember 中的 Handlebars 上下文可以繼承它們的父上下文中的變量。在 Ember 在當前 上下文中查找變量之前,它首先檢查它的模板變量。當一個視圖創建了一個新的 Handlebars 作用域,它們自動繼承它們父作用域的變量。

Ember 定義了這些 viewcontroller 變量,所以當一個表達式使用 viewcontroller 變量名,它們總是最先被找到。

如上所述,Ember 設置了 Handlebars 上下文中的 view 變量,無論何時模板中使用 了 {{#view}} 輔助標記。起初,Ember 把 view 變量設置為正在渲染模板的視 圖。

Ember 設置了 Handlebars 上下文中的 controller 變量,無論已渲染的視圖是否存 在 controller 屬性。如果視圖沒有 controller 屬性,它從時間上最近的擁有該 屬性的視圖上繼承 controller 變量。

其它變量

Ember 中的 Handlebars 輔助標記也會指定變量。例如, {{#with controller.person as tom}} 形式指定一個 tom 變量,它的后代作用域 是可訪問的。即使一個子上下文有 tom 屬性,這個 tom 變量會廢除它。

這個形式的最大好處是,它允許你簡寫長路徑,而不喪失對父作用域的訪問權限。

{{#each}} 輔助標記中,提供 {{#each person in people}} 形式尤其重要。 在這個形式中,后代上下文可以訪問 person 變量,但在模板調用 each 的地方 保留相同的作用域。

  1. {{#with controller.preferences}} 
  2.   <h1>Title</h1> 
  3.   <ul> 
  4.   {{#each person in controller.people}} 
  5.     {{! prefix here is controller.preferences.prefix }} 
  6.     <li>{{prefix}}: {{person.fullName}}</li> 
  7.   {{/each}} 
  8.   <ul> 
  9. {{/with}} 

注意這些變量繼承了 ContainerView 中的那些,即使它們不是 Handlebars 上下文 層級中的一部分。

從視圖中訪問模板變量

在大多數情況下,你會需要從模板中訪問這些模板變量。在一些不尋常的情景下,你會 想要在視圖的 JavaScript 代碼中訪問范圍內的變量。

你可以訪問視圖的 templateVariables 屬性來達成此目的,它會返回一個包含當視 圖渲染后存在于其作用于的變量的 JavaScript 對象。 ContainerView 也可以訪問 這個屬性,它指向時間上最近的模板依賴的視圖的模板變量。

目前,你不能觀察或綁定一個包含 templateVariables 的路徑。

原文鏈接:http://emberjs.torriacg.org/guides/view_layer/#toc_

 

責任編輯:陳四芳 來源: emberjs.torriacg.org
相關推薦

2013-12-24 11:11:27

ember.jsJavascript

2013-12-24 15:56:20

2013-12-24 14:50:39

Ember.js框架

2013-12-20 14:47:23

ember.js

2013-09-10 14:01:40

WebEmber.jsAngular.js

2016-11-14 15:51:42

JavaScriptAngular.jsReact.js

2013-10-16 10:11:35

JavaScript項目框架

2014-03-13 11:22:00

JavaScriptJS框架

2013-12-25 09:53:22

Ember.js應用

2013-12-25 10:08:42

ember.js異步處理

2013-12-24 13:20:28

EmberEmber.js

2013-05-30 15:16:26

javaScriptMVC模式

2021-11-29 00:17:41

JS符串轉換

2024-04-09 16:19:16

2015-02-09 10:43:00

JavaScript

2023-03-15 08:03:31

2021-12-24 15:46:23

鴻蒙HarmonyOS應用

2010-07-19 09:31:53

SQL Server系

2010-11-16 10:42:45

Oracle創建視圖

2010-11-12 11:19:19

SQL Server視
點贊
收藏

51CTO技術棧公眾號

另类欧美小说| 欧美激情精品久久久久久久变态| 欧美成人精品欧美一级乱| 欧洲一级在线观看| 蜜桃av噜噜一区| 欧美国产日韩在线| 爱爱免费小视频| 豆花视频一区| 婷婷中文字幕一区三区| 天天爽天天狠久久久| av中文字幕免费| 性高湖久久久久久久久| 久久精品人人做人人爽| 中国黄色片视频| 99精品在免费线偷拍| 一区二区三区在线观看动漫| 欧美日韩电影一区二区三区| 99er热精品视频| 性欧美长视频| 欧美成人黄色小视频| 中文字幕一区二区三区人妻电影| 激情综合五月| 一本大道久久a久久精品综合| 国产高清精品软男同| 日韩二区三区| 国产成人鲁色资源国产91色综| 秋霞成人午夜鲁丝一区二区三区| 欧美三级在线免费观看| 黄色不卡一区| 亚洲福利影片在线| 欧美色图色综合| 天天av综合网| 成人综合婷婷国产精品久久免费| 国产精品一区二区电影| 久草手机在线视频| 国产精品www.| 久久久国产91| 久久精品日韩无码| 国产一区二区亚洲| 日韩大陆毛片av| 1314成人网| 亚洲欧美在线人成swag| 色婷婷一区二区三区四区| 成人免费毛片在线观看| 婷婷色在线资源| 亚洲天堂中文字幕| 一区二区三区四区| 大地资源中文在线观看免费版| eeuss鲁片一区二区三区在线观看| 成人性生交大片免费看视频直播 | 97av在线视频| 在线免费观看毛片| 国产精品啊v在线| 九色成人免费视频| 无码人妻精品一区二区三区夜夜嗨| 日韩成人精品一区| 伊人久久精品视频| 精品一区二区6| 日本黄色精品| 最新亚洲国产精品| 国产免费美女视频| 影视亚洲一区二区三区| 精品中文字幕在线| 激情视频在线播放| 亚洲人成久久| 91国产一区在线| 四虎成人永久免费视频| 久久性天堂网| 国产精品久久久久久超碰| 一级黄色在线观看| 蜜桃一区二区三区在线| 成人精品一区二区三区| 国产美女www爽爽爽视频| 国产毛片精品一区| 99精品国产一区二区| 欧美一级特黄aaaaaa| av成人免费在线观看| 久久手机视频| 国产69精品久久app免费版| 国产欧美一区二区精品性色超碰 | 午夜影院免费版| 综合中文字幕| 日韩电影免费观看在线观看| 国产免费一区二区三区网站免费| 成人同人动漫免费观看 | 欧美日韩国产天堂| 四虎国产精品永久免费观看视频| 日韩中文字幕无砖| 国产视频久久久| 美女av免费看| 欧美国产专区| 欧美中文在线观看国产| ,一级淫片a看免费| 国产99久久精品| 久久青青草综合| 免费在线观看黄色| 精品久久中文字幕久久av| 三级在线免费看| 久久国产精品免费一区二区三区| 亚洲激情视频在线播放| 一区二区三区伦理片| 一区二区国产在线| 欧美亚洲国产视频| 99久久夜色精品国产亚洲| 成人av网站在线观看免费| 日韩欧美精品在线不卡| 后进极品白嫩翘臀在线播放| 一本到三区不卡视频| 色偷偷中文字幕| 久久超碰99| 欧美国产日产韩国视频| 亚洲天堂手机版| jlzzjlzz国产精品久久| 在线观看成人免费| 欧美日韩123区| 精品日韩在线观看| 国产精品一区二区亚洲| 国产婷婷精品| 99国产视频| 国产视频二区在线观看| 亚洲国产精品久久人人爱蜜臀| 日本熟妇人妻中出| av在线亚洲色图| 久久精品一区中文字幕| 久久亚洲精品石原莉奈 | 真人bbbbbbbbb毛片| 中文在线播放一区二区| 国产精品第三页| 五月天激情婷婷| 玉足女爽爽91| 男人的天堂最新网址| 久草在线成人| 欧美诱惑福利视频| 亚洲精品视频专区| 亚洲美女屁股眼交3| 色天使在线观看| 日韩免费一区| 国产精品∨欧美精品v日韩精品| 亚洲福利在线观看视频| 亚洲色图制服诱惑| 一级做a免费视频| 日本大胆欧美| 国产精品视频久久久久| 成人在线观看黄色| 欧美主播一区二区三区美女| 性欧美丰满熟妇xxxx性仙踪林| 1024成人| 精品高清视频| freexxx性亚洲精品| 精品国产三级电影在线观看| 永久免费看mv网站入口| 韩国一区二区在线观看| 亚洲伊人婷婷| 99亚洲男女激情在线观看| 中文字幕亚洲国产| 一区二区三区黄色片| 国产精品国产三级国产普通话三级 | 日本高清免费观看| 欧美日韩18| 国产精品日韩一区二区三区| 伊人222成人综合网| 日韩精品一区二区三区老鸭窝| 日韩精品一区二区三区在线视频| 精品一区二区影视| 99热这里只有精品7| 奇米一区二区| 欧美精品久久一区二区| 欧美一级特黄aaaaaa| 欧美日韩免费看| 亚洲自拍偷拍一区二区| 日本视频一区二区三区| 亚洲欧美在线网| www一区二区三区| 欧美成人精品在线观看| 免费看国产片在线观看| 色综合色狠狠天天综合色| 日本欧美一区二区三区不卡视频 | www.桃色.com| 欧美色图麻豆| 麻豆亚洲一区| 久久久加勒比| 欧美极品美女电影一区| 欧美孕妇性xxxⅹ精品hd| 欧美日韩国产一区| 日本三级网站在线观看| 久久青草欧美一区二区三区| 日本激情综合网| 中文字幕一区二区三区欧美日韩| 国内不卡一区二区三区| 欧美日韩在线精品一区二区三区激情综合 | 一级黄色在线播放| 亚洲少妇自拍| 一区二区av| 久久精品色综合| 国产精品香蕉在线观看| 免费网站免费进入在线| 日韩精品在线播放| 国产一区二区在线播放视频| 午夜激情一区二区| 亚洲天堂精品一区| 99久久伊人精品| 亚洲最大天堂网| 亚洲尤物精选| 三年中国中文在线观看免费播放| 欧美黄色影院| 91亚洲人电影| 伊人久久高清| 欧美精品videossex88| lutube成人福利在线观看| 精品国产电影一区二区| 中文字幕日本人妻久久久免费| 亚洲高清在线精品| 小嫩苞一区二区三区| 91看片淫黄大片一级在线观看| 最新免费av网址| 日韩精品91亚洲二区在线观看| 黄色一级片黄色| 国产精品福利在线观看播放| 免费看国产精品一二区视频| 精品国产麻豆| 国产精品综合网站| 欧美理论影院| 2019中文字幕在线免费观看| 日本一级理论片在线大全| 中文字幕欧美日韩va免费视频| 天堂a√中文在线| 精品国产免费视频| 国产日韩在线观看一区| 欧美三电影在线| 丰满人妻老熟妇伦人精品| 亚洲h在线观看| 中文字幕在线观看成人| 国产精品进线69影院| av黄色在线免费观看| 久久亚洲精华国产精华液| 国产+高潮+白浆+无码| 国产美女视频91| 精品国产鲁一鲁一区二区三区| 蜜臀av一区二区| 人妻有码中文字幕| 亚洲女人av| 免费欧美一级视频| 99精品久久久| 欧美啪啪免费视频| 日韩午夜免费| 人妻熟妇乱又伦精品视频| 亚洲经典三级| 精品这里只有精品| 亚洲一区日韩在线| 国产日韩一区二区在线| 午夜综合激情| 国产极品美女高潮无套久久久| 国产视频一区在线观看一区免费| 久久视频这里有精品| 亚洲国产二区| 亚洲午夜精品久久久久久人妖| 亚洲欧洲日本mm| 欧美 丝袜 自拍 制服 另类| 99人久久精品视频最新地址| 日本网站免费在线观看| 香蕉久久国产| 91香蕉视频污版| 久久99精品久久久久久动态图| 亚洲欧美日韩精品一区| 国产激情一区二区三区四区 | 奇米777四色影视在线看| 中文字幕一区二区av| 日本手机在线视频| 久久综合九色| 日本黄色福利视频| 成熟亚洲日本毛茸茸凸凹| 久久午夜夜伦鲁鲁片| 久久久久久久综合色一本| 色www亚洲国产阿娇yao| 依依成人精品视频| 五月婷婷开心网| 日本精品一区二区三区四区的功能| 中文字幕男人天堂| 91精选在线观看| 神马午夜在线观看| 亚洲一区二区久久久| 成人av黄色| 98精品国产高清在线xxxx天堂| 精品欧美一区二区三区在线观看| 亚洲a成v人在线观看| 综合中文字幕| 日韩不卡av| 欧美精品日韩| 日韩精品一区二区三区色欲av| 卡一卡二国产精品 | 亚洲精品aⅴ| 久久av一区二区三区亚洲| 国产影视一区| 精品久久久无码人妻字幂| 久久国产精品毛片| 992kp免费看片| 91麻豆免费看片| frxxee中国xxx麻豆hd| 精品久久香蕉国产线看观看gif| 中文字幕在线观看免费| 精品国产青草久久久久福利| av在线免费观看网站| 国内精品国产三级国产在线专| 欧美日韩激情电影| 国产精品免费观看高清| 色琪琪久久se色| 欧美久久久久久久久久久久久| 麻豆精品一区二区综合av| 亚洲啪av永久无码精品放毛片 | 免费在线观看视频一区| 动漫美女无遮挡免费| 欧美国产国产综合| 国产 欧美 日韩 在线| 5566中文字幕一区二区电影| 青青操在线视频| 久久久久久久999精品视频| 成人交换视频| 欧美极品一区二区| 狠狠入ady亚洲精品| 国产又黄又猛的视频| 久久久精品黄色| 日韩三级免费看| 日韩欧美另类在线| 免费黄网站在线| 国产精品国产三级国产aⅴ9色| 国产在线播放精品| 亚洲精品国产suv一区88| 精品一区二区三区免费| 国产一二三四五区| 欧美日韩国产中字| 色呦呦视频在线| 欧美激情a∨在线视频播放| 精品午夜视频| 久久精品国产精品亚洲精品色 | 欧美色图校园春色| 中文字幕亚洲电影| 一区二区视频在线免费观看| 亚洲欧美中文另类| 性欧美freesex顶级少妇| 国内精品二区| 亚洲精选久久| 国产麻豆剧传媒精品国产av| 亚洲午夜免费电影| 高h放荡受浪受bl| 欧美高跟鞋交xxxxxhd| 欧美一级大片在线视频| 欧美美女黄色网| 国产激情视频一区二区三区欧美 | 亚洲成人动漫av| 污污网站在线免费观看| 97久久精品国产| 日韩深夜影院| 黄色片视频在线播放| 国产日产欧美一区二区三区| 无码人妻一区二区三区免费| 亚洲人成电影在线播放| 亚洲伦理影院| 视频一区二区三区免费观看| 美洲天堂一区二卡三卡四卡视频| 欧美熟妇激情一区二区三区| 欧洲精品中文字幕| 秋霞a级毛片在线看| 91热精品视频| 韩国在线视频一区| 亚洲第一黄色网址| 色成年激情久久综合| 成黄免费在线| 成人激情免费在线| 国产主播一区| 亚洲制服丝袜在线播放| 色欲综合视频天天天| 成人p站proumb入口| 91影视免费在线观看| 亚洲视频免费| 色一情一交一乱一区二区三区| 欧美午夜宅男影院| a视频在线免费看| 国内一区二区在线视频观看| 丝袜亚洲另类丝袜在线| 影音先锋男人资源在线观看| 精品电影一区二区| 欧美xxxx做受欧美护士| 91大学生片黄在线观看| 99精品在线观看视频| 中文文字幕一区二区三三| 久久人人爽人人爽人人片亚洲| 哺乳一区二区三区中文视频 | 国产一区91精品张津瑜| 国产精品午夜影院| 中文字幕免费精品一区| 爱高潮www亚洲精品| 国产又黄又猛视频| 亚洲乱码中文字幕| 日本一二三区在线视频| 成人字幕网zmw| 免费视频一区| 国产成人无码aa精品一区| 亚洲欧美综合区自拍另类| 日韩一区二区三区高清在线观看| av网站在线观看不卡|