這是三部分系列中的第二部分,將教您如何使用 CanJS 和 jQuery 在 JavaScript 中建立聯絡人管理器應用程式。學完本教學後,您將擁有使用 CanJS 建立自己的 JavaScript 應用程式所需的一切!
#在第一部分中,您建立了顯示聯絡人所需的模型、視圖和控件,並使用了模擬 REST 服務的固定裝置。
在這一部分中,您將:
您將添加到第一部分中的來源文件,因此如果您還沒有這樣做,請先跟上。當你準備好時我會在這裡。
路由有助於管理單頁 JavaScript 應用程式中的瀏覽器歷史記錄和用戶端狀態。
路由有助於管理單頁 JavaScript 應用程式中的瀏覽器歷史記錄和用戶端狀態。 URL 中的雜湊包含應用程式讀取和寫入的屬性。應用程式的各個部分可以偵聽這些變更並做出相應的反應,通常會更新目前頁面的部分內容而不載入新頁面。
can.route
是一個特殊的可觀察對象,它更新並回應 window.location.hash
中的變更。使用 can.route
將 URL 對應到屬性,從而產生漂亮的 URL,例如 #!filter/all
。如果沒有定義路由,則雜湊值只會序列化為 URL 編碼表示法,如 #!category=all
。
在此應用程式中,路由將用於按類別過濾聯絡人。將以下程式碼加入您的 contacts.js
檔案中:
can.route( 'filter/:category' ) can.route('', {category: 'all' })
第一行建立一個帶有 category
屬性的路由,您的應用程式將能夠讀取和寫入該屬性。第二行建立一個預設路由,將 category
屬性設為 all
。
A Model.List
是模型實例的可觀察陣列。當您定義 Model
(如 Contact
)時,會自動建立該類型模型的 Model.List
。我們可以擴展這個創建的 Model.List
以添加對模型實例列表進行操作的輔助函數。
Contact.List
將需要兩個輔助函數來過濾聯絡人清單並報告每個類別中有多少聯絡人。將其新增至 contacts.js
緊接在 Contact
模型之後:
Contact.List = can.Model.List({ filter: function(category){ this.attr('length'); var contacts = new Contact.List([]); this.each(function(contact, i){ if(category === 'all' || category === contact.attr('category')) { contacts.push(contact) } }) return contacts; }, count: function(category) { return this.filter(category).length; } });
這裡的兩個輔助函數是:
filter()
循環存取清單中的每個聯絡人,並傳回類別內聯絡人的新 Contact.List
。 this.attr('length')
包含在此處,因此當我們在視圖中使用此幫助程式時,EJS 將設定即時綁定。 count()
使用 filter()
輔助函數傳回類別中的聯絡人數量。由於 this.attr('length')
在 filter()
中,當我們在視圖中使用此幫助器時,EJS 將設定即時綁定。 如果您要在 EJS 中使用幫助程序,請在清單或實例屬性上使用
attr()
來設定即時綁定。
接下來,您將修改 contactsList.ejs
視圖,以根據哈希中的類別屬性過濾聯絡人。在contactsList.ejs
視圖中,將傳遞給list()
幫助器的參數變更為contacts.filter(can.route.attr('category'))
。完成後,您的 EJS 檔案應如下所示:
<ul class="unstyled clearfix"> <% list(contacts.filter(can.route.attr('category')), function(contact){ %> <li class="contact span8" <%= (el)-> el.data('contact', contact) %>> <div class=""> <%== can.view.render('contactView', {contact: contact, categories: categories}) %> </div> </li> <% }) %> </ul>
在第二行,使用 can.route
中的目前類別呼叫 filter()
。由於您在filter()
和can.route
中使用了attr()
,因此當其中任何一個發生變更時,EJS 將設定即時綁定以重新渲染您的UI。
現在您應該清楚即時綁定的強大功能了。透過對視圖進行輕微調整,應用程式的 UI 現在不僅與聯絡人清單完全同步,還與路線中定義的類別屬性完全同步。
當哈希中的類別屬性更改時,聯絡人將被過濾。現在您需要一種方法來列出所有可用類別並更改雜湊值。
首先,建立一個新視圖來顯示類別清單。將此程式碼儲存為 filterView.ejs
在 views
資料夾中:
<ul class="nav nav-list"> <li class="nav-header">Categories</li> <li> <a href="javascript://" data-category="all">All (<%= contacts.count('all') %>)</a> </li> <% $.each(categories, function(i, category){ %> <li> <a href="javascript://" data-category="<%= category.data %>"><%= category.name %> (<%= contacts.count(category.data) %>)</a> </li> <% }) %> </ul>
讓我們看一下這段程式碼中的幾行,看看它們做了什麼:
<% $.each(categories, function(i, category){ %>
$.each
循環遍歷類別並為每個類別執行回呼。
<a href="javascript://" data-category="<%= category.data %>"><%= category.name %> (<%= contacts.count(category.data) %>
每个链接都有一个 data-category
属性,该属性将被拉入 jQuery 的数据对象中。稍后,可以使用 <a></a>
标记上的 .data('category')
来访问该值。类别的名称和联系人数量将用作链接测试。实时绑定是根据联系人数量设置的,因为 count()
调用 filter()
其中包含 this.attr('length')
。
can.Control
监听事件
创建实例时,控件会自动绑定看起来像事件处理程序的方法。事件处理程序的第一部分是选择器,第二部分是您要侦听的事件。选择器可以是任何有效的 CSS 选择器,事件可以是任何 DOM 事件或自定义事件。因此,像 'a click'
这样的函数将监听控件元素内任何 <a></a>
标记的点击。
Control 使用事件委托,因此您不必担心在 DOM 更改时重新绑定事件处理程序。
通过将此代码添加到 contacts.js
紧随 Contacts
控件之后来创建管理类别的控件:
Filter = can.Control({ init: function(){ var category = can.route.attr('category') || "all"; this.element.html(can.view('filterView', { contacts: this.options.contacts, categories: this.options.categories })); this.element.find('[data-category="' + category + '"]').parent().addClass('active'); }, '[data-category] click': function(el, ev) { this.element.find('[data-category]').parent().removeClass('active'); el.parent().addClass('active'); can.route.attr('category', el.data('category')); } });
让我们检查一下您刚刚创建的“Filter”控件中的代码:
this.element.html(can.view('filterView', { contacts: this.options.contacts, categories: this.options.categories }));
就像在 Contacts
控件中一样,init()
使用 can.view()
来呈现类别,并使用 html()
将其插入到控件的元素中。
this.element.find('[data-category="' + category + '"]').parent().addClass('active');
查找与当前类别相对应的链接,并将“active”类添加到其父元素。
'[data-category] click': function(el, ev) {
监听与选择器 [data-category]
匹配的任何元素上的 click
事件。
this.element.find('[data-category]').parent().removeClass('active'); el.parent().addClass('active');
从所有链接中删除“活动”类,然后向单击的链接添加“活动”类。
can.route.attr('category', el.data('category'));
使用 jQuery 数据对象中所单击的 <a></a>
的值更新 can.route
中的类别属性。
就像第一部分中的 Contacts
控件一样,您需要创建 Filter
控件的新实例。更新您的文档就绪函数,如下所示:
$(document).ready(function(){ $.when(Category.findAll(), Contact.findAll()).then(function(categoryResponse, contactResponse){ var categories = categoryResponse[0], contacts = contactResponse[0]; new Contacts('#contacts', { contacts: contacts, categories: categories }); new Filter('#filter', { contacts: contacts, categories: categories }); }); })
通过此更改,将在 #filter
元素上创建 Filter
控件的实例。它将传递联系人和类别列表。
现在,当您在浏览器中运行应用程序时,您将能够通过单击右侧的类别来过滤联系人:
这就是第二部分的全部内容!以下是我们所取得的成就:
在第三部分中,您将更新现有控件以允许编辑和删除联系人。您还将创建一个新的控件和视图,以便您添加新的联系人。
迫不及待想了解更多信息?该系列的第三部分已发布在这里!
以上是深入了解CanJS:第二部分的詳細內容。更多資訊請關注PHP中文網其他相關文章!