使用Angular編寫TodoMVC Vol 4

序言

本章將通過angular默認的ng-route組件來復用視圖與前端的路由控制。

上一個章節(jié)的完成圖

Vol3 完成圖

本章目的

在底部增加一個狀態(tài)的過濾屈暗,可以分別顯示“全部”妨蛹,“未完成”和“已完成”不同狀態(tài)下的清單屏富。

1. 使用ng-route復用視圖

1.1 調(diào)整index.html

首先我們先來審閱一下當年的index.html代碼

<!doctype html>
<html lang="en" data-framework="angularjs">
<head>
    <meta charset="utf-8">
    <title>AngularJS ? TodoMVC</title>
    <link rel="stylesheet" href="node_modules/todomvc-common/base.css">
    <link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head>
<body ng-app="todomvc" ng-controller="TodoController as vm">
<section id="todoapp">
    <header id="header">
        <h1>todos</h1>
        <form id="todo-form" ng-submit="vm.addTask()">
            <input id="new-todo" placeholder="添加新的任務?" ng-model="vm.newTask" autofocus>
        </form>
    </header>
    <section id="main" ng-cloak>
        <ul id="todo-list">
            <li ng-repeat="task in vm.tasks" ng-class="{completed: task.completed, editing: task === vm.editedTask}">
                <div class="view">
                    <input class="toggle" type="checkbox" ng-model="task.completed">
                    <label ng-dblclick="vm.editTask(task)">{{task.title}}</label>
                    <button class="destroy" ng-click="vm.removeTask(task)"></button>
                </div>
                <form>
                    <input class="edit" ng-trim="false" ng-model="task.title"  >
                </form>
            </li>
        </ul>
    </section>
</section>
    <script src="node_modules/angular/angular.js"></script>
    <script src="node_modules/angular-route/angular-route.js"></script>
    <script src="js/app.js"></script>
    <script src="js/controllers/todo.controller.js"></script>
</body>
</html>

body標簽的section標簽內(nèi)的內(nèi)容才是有有邏輯并且可分離的視圖代碼。
故我們使用ng-route來規(guī)劃前端的url分發(fā)控制與對應的蛙卤,通過對目標URL的撞他變化加載對應的視圖與控制器文件狠半。

1.2 分離業(yè)務視圖至partials/todo.html文件

我們將index.html代碼分離出來,新建一個partials/todo.html颤难,其內(nèi)容如下神年。
目錄結(jié)構(gòu)

新建partials目錄存放視圖文件
<section id="todoapp">
    <header id="header">
        <h1>todos</h1>
        <form id="todo-form" ng-submit="vm.addTask()">
            <input id="new-todo" placeholder="添加新的任務?" ng-model="vm.newTask" autofocus>
        </form>
    </header>
    <section id="main" ng-cloak>
        <ul id="todo-list">
            <li ng-repeat="task in vm.tasks" ng-class="{completed: task.completed, editing: task === vm.editedTask}">
                <div class="view">
                    <input class="toggle" type="checkbox" ng-model="task.completed">
                    <label ng-dblclick="vm.editTask(task)">{{task.title}}</label>
                    <button class="destroy" ng-click="vm.removeTask(task)"></button>
                </div>
                <form>
                    <input class="edit" ng-trim="false" ng-model="task.title"  >
                </form>
            </li>
        </ul>
    </section>
</section>

消除這段代碼后整個index.html就只剩下相關(guān)的入口及配置信息代碼就變得干凈很多。
因為使用了ng-route之后控制器的初始化就不需要我們顯式的寫在視圖中行嗤。故我們刪除掉body標簽中的ng-controller屬性已日。

<!--
<body ng-app="todomvc" ng-controller="TodoController as vm">
-->
<body ng-app="todomvc">

最后在body標簽下引入ng-route的動態(tài)視圖指令ng-view

<body ng-app="todomvc">
    <ng-view />

    <script src="node_modules/angular/angular.js"></script>
    <script src="node_modules/angular-route/angular-route.js"></script>
    <script src="js/app.js"></script>
    <script src="js/controllers/todo.controller.js"></script>
</body>

1.3 引入route配置信息

我們重新編輯app.js文件增加根路徑的視圖與控制器加載邏輯。

(function(){
    'use strict';

    angular.module('todomvc', ['ngRoute'])
        .config(routerConfig);
    routerConfig.$inject = ['$routeProvider'];


    function routerConfig($routeProvider){
        $routeProvider
        .when('/',{
            controller: 'TodoController',
            templateUrl: 'partials/todo.html',
            controllerAs: 'vm'
        })
    };
})();

routeConfig中操作$routeProvider服務栅屏,向其添加路由規(guī)則飘千。

.when('/',{
            controller: 'TodoController', //控制器
            templateUrl: 'partials/todo.html', //視圖
            controllerAs: 'vm' // 控制器As的別名語法堂鲜,Angular1.2以后提倡的語法
        })

這樣我們就讓angular在客戶端維護了一個可以根據(jù)url做出影響的前端運行時環(huán)境,這個時候我們重新在瀏覽器刷新地址則發(fā)現(xiàn)應用與之前是沒區(qū)別的护奈,唯一的區(qū)別是路徑上多了一個#符號缔莲。


多了一個#號

默認模式下,瀏覽器都只訪問index.html的入口頁 /#/之后的路徑為ng-route控制的url部分霉旗,這樣即使前端便可以進行無刷新的頁面url的跳轉(zhuǎn)操作了痴奏。

2. 向應用中添加底部狀態(tài)控制欄

這次我們希望通過不同的url來顯示不同的任務清單列表:

  • 在/路徑下顯示所有狀態(tài)的任務清單
  • 在/active路徑下顯示所有未完成的任務清單
  • 在/completed路徑下顯示所有完成的任務清單

2.1 修改ng-route

添加新/:status路由,將active于completed作為參數(shù)傳給controller做數(shù)據(jù)的篩選奖慌。

      .when('/:status', {
        controller: 'TodoController',
        templateUrl: 'partials/todo.html',
        controllerAs: 'vm'
      })

2.2 在controller層獲取路由參數(shù)

我們在Controller層想要獲取路徑上的參數(shù)抛虫,則需要向Controller注入$routeParams服務,在通過$routeParams.paramName的形式便可以獲取對應的參數(shù)值简僧。
我們修改我們TodoController使其可以對不同的status狀態(tài)做出不同的過濾操作建椰。
首先,我們編寫一個函數(shù)可以根據(jù)不同的status值來過濾處理controller中的任務清單數(shù)組

        function _filterDataByStatus(tasks,status){
            if (status === 'active'){
                return tasks.filter(function(task){
                    return (task.completed != true )
                }) 
            }else if(status === 'completed'){
                return tasks.filter(function(task){
                    return (task.completed == true )
                }) 
            }else{
                return tasks;
            }
        }

然后,調(diào)整TodoController中的初始化邏輯,通過$routeParam服務來獲取路徑中的status的值岛马。

        function init(){

            var tasks = [
            {
                title: "第一個任務",
                completed: true
            },
            {
                title: "第二個任務",
                completed: false

            }];
            vm.status = $routeParams.status||"";
            vm.tasks = _filterDataByStatus(tasks,vm.status)
        }

我們額外聲明了一個vm.status變量用于記錄當前的status的值棉姐,用于模板中的底部狀態(tài)過濾標簽對當前激活的過濾條件做高亮顯示。

2.3 增加底部的狀態(tài)切換區(qū)域

我們在todo.html中增加一段新的footer標簽區(qū)域用于顯示底部的狀態(tài)切換的狀態(tài)標簽按鈕啦逆。


    <footer id="footer" ng-show="vm.tasks.length" ng-cloak>
        <span id="todo-count"><strong>{{remainingCount}}</strong>
            <ng-pluralize count="remainingCount" when="{ one: 'item left', other: 'items left' }"></ng-pluralize>
        </span>
        <ul id="filters">
            <li>
                <a ng-class="{selected: vm.status == ''} " href="#/">All</a>
            </li>
            <li>
                <a ng-class="{selected: vm.status == 'active'}" href="#/active">Active</a>
            </li>
            <li>
                <a ng-class="{selected: vm.status == 'completed'}" href="#/completed">Completed</a>
            </li>
        </ul>
    </footer>

底部有三個按鈕分別對應路徑"/","/active"與"/completed"伞矩。并根據(jù)vm.status使用ng-class來高亮顯示當前激活的過濾條件標簽。

2.4 測試應用

我們分別測試不同狀態(tài)下的清單顯示情況

2.4.1 默認顯示全部

顯示全部

2.4.2 待完成

待完成

2.4.3 已完成

已完成

2.5 問題

似乎看上去我們的過濾功能以前完成了夏志,但是我們可以添加一個新的任務乃坤,再進行條件過濾,這個時候則會發(fā)現(xiàn)新建的任務清單“不見了”沟蔑。
這是因為不同路由下的雖然為同名controller但是其中的實例變量還是會重新初始化湿诊。兩個Controller實例沒有進行數(shù)據(jù)的共享。
vm.tasks的賦值邏輯

            var tasks = [
            {
                title: "第一個任務",
                completed: true
            },
            {
                title: "第二個任務",
                completed: false

            }];

            vm.status = $routeParams.status||"";

            //此處的進行雙向綁定
            vm.tasks = _filterDataByStatus(tasks,vm.status)
不同路由下不同Controller實例中的變量不同享

在下一章的文章中我們將介紹Angular中常見幾種在controller中共享瘦材、傳遞數(shù)據(jù)的方法并選取一種來調(diào)整我們的代碼厅须。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市食棕,隨后出現(xiàn)的幾起案子朗和,更是在濱河造成了極大的恐慌,老刑警劉巖簿晓,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眶拉,死亡現(xiàn)場離奇詭異,居然都是意外死亡抢蚀,警方通過查閱死者的電腦和手機镀层,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唱逢,你說我怎么就攤上這事吴侦。” “怎么了坞古?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵备韧,是天一觀的道長。 經(jīng)常有香客問我痪枫,道長织堂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任奶陈,我火速辦了婚禮易阳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吃粒。我一直安慰自己潦俺,他們只是感情好,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布徐勃。 她就那樣靜靜地躺著事示,像睡著了一般。 火紅的嫁衣襯著肌膚如雪僻肖。 梳的紋絲不亂的頭發(fā)上肖爵,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音臀脏,去河邊找鬼劝堪。 笑死,一個胖子當著我的面吹牛揉稚,可吹牛的內(nèi)容都是我干的幅聘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窃植,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荐糜?” 一聲冷哼從身側(cè)響起巷怜,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暴氏,沒想到半個月后延塑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡答渔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年关带,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡宋雏,死狀恐怖芜飘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磨总,我是刑警寧澤嗦明,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站蚪燕,受9級特大地震影響娶牌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜馆纳,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一诗良、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲁驶,春花似錦鉴裹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寿羞,卻和暖如春猖凛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绪穆。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工辨泳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玖院。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓菠红,卻偏偏與公主長得像,于是被迫代替她去往敵國和親难菌。 傳聞我的和親對象是個殘疾皇子试溯,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • AngularJS是什么?AngularJs(后面就簡稱ng了)是一個用于設(shè)計動態(tài)web應用的結(jié)構(gòu)框架郊酒。首先遇绞,它是...
    200813閱讀 1,606評論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)燎窘,斷路器摹闽,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 序言 本章我們將學習如果利用service在controller之間共享、傳遞數(shù)據(jù)褐健。還將調(diào)整我們在不同狀態(tài)下顯示不...
    AkiraPan閱讀 614評論 0 1
  • AngularJSAngularJS 是一個 MV* 框架付鹿, 最適于開發(fā)客戶端的單頁面應用。它不是個功能庫,...
    一直以來都很好閱讀 899評論 0 0
  • 通過AngularJS仿豆瓣一刻的案例:https://github.com/zhongxiaolian/doub...
    中小戀閱讀 1,759評論 1 21