在實現Angularjs實現mvvm式的選項卡之前,先搬出我們常用的jquery實現。
1、jquery實現簡單粗暴的選項卡效果
var nav = $(".tabs");//tab切換var box = $(".box");//容器nav.on("click", function(){ //點擊事件 var this_index=$(this).index(); $(this).addClass("active").siblings().removeClass("active"); box.eq(this_index).show().siblings().hide();});
在這裡只給出js核心部分,html和css不做贅述。
以上代碼,簡單粗暴的實現了選項卡效果,用點擊事件獲得elem.index()
, 把索引和容器串起來控制顯示隱藏。
2、angularjs實現一個簡單選項卡效果
Html部分
<section ng-app="myApp"> <div class="tabs tabs-style" ng-controller="TabController as tab"> <nav> <ul> <li ng-class="{'current':tab.isSet(1)}"> <a href="#" ng-click="tab.setCurrent(1)"><span>Home</span></a></li> <li ng-class="{'current':tab.isSet(2)}"> <a href="#" ng-click="tab.setCurrent(2)"><span>Work</span></a></li> <li ng-class="{'current':tab.isSet(3)}"> <a href="#" ng-click="tab.setCurrent(3)"><span>Blog</span></a></li> <li ng-class="{'current':tab.isSet(4)}"> <a href="#" ng-click="tab.setCurrent(4)"><span>About</span></a></li> <li ng-class="{'current':tab.isSet(5)}"> <a href="#" ng-click="tab.setCurrent(5)"><span>Contact</span></a></li> </ul> </nav> <div class="content"> <section id="section-1" ng-show="tab.isSet(1)"> <p>1</p> </section> <section id="section-2" ng-show="tab.isSet(2)"> <p>2</p> </section> <section id="section-3" ng-show="tab.isSet(3)"> <p>3</p> </section> <section id="section-4" ng-show="tab.isSet(4)"> <p>4</p> </section> <section id="section-5" ng-show="tab.isSet(5)"> <p>5</p> </section> </div> </div> </section>
css 部分(這裡為了方便我們使用Less
文法,童鞋們可以自訂css實現個性效果)
* { margin: 0; padding: 0;}body { background: #e7ecea; font-weight: 600; font-family: 'Raleway', Arial, sans-serif; text-align: center;}a { color: #2CC185; text-decoration: none; outline: none; &:hover { color: #74777b; }}.tabs { position: relative; width: 100%; margin: 30px auto 0 auto; nav { ul { position: relative; display: flex; max-width: 1200px; margin: 0 auto; list-style: none; flex-flow: row wrap; justify-content: center; li { flex: 1; &.current a { color: #74777b; } } } } a { display: block; position: relative; overflow : hidden; line-height: 2.5; span { vertical-align: middle; font-size: 1.5em; } }}.content { position: relative; section { /* display: none; */ margin: 0 auto; max-width: 1200px; &.content-current { /* display: block; */ } p { color: rgba(40,44,42, 0.4); margin: 0; padding: 1.75em 0; font-weight: 900; font-size: 5em; line-height: 1; } }}.tabs-style { nav { /* background: rgba(255,255,255,0.4); */ ul li { a { overflow: visible; border-bottom: 1px solid rgba(0,0,0,0.2); -webkit-transition: color 0.2s; transition: color 0.2s; } } ul li.current a{ &:after, &:before { content: ''; position: absolute; top: 100%; left: 50%; width: 0; height: 0; border: solid transparent; } &:after { margin-left: -10px; border-width: 10px; border-top-color: #e7ecea; } &:before { margin-left: -11px; border-width: 11px; border-top-color: rgba(0,0,0,0.2); } } }}
js部分
angular.module('myApp', []) .controller('TabController', function() { this.current = 1; this.setCurrent = function (tab) { this.current = tab; }; this.isSet = function(tab) { return this.current == tab; };});
最後效果如下圖所示:
通過以上代碼,我們可以發現實現的核心是angularjs內建的ng-class
和ng-click
,ng-show
指令。
通俗來講:controller裡定義了current 這條資料預設值為1,ng-click
給點擊事件自訂函數,改變current
資料,ng-class
通過獲得current
的值綁定條件,給當前選中的索引添加current
樣式,容器同樣獲得controller
裡的current
資料通過ng-show
控制顯示隱藏。
3、angularjs實現一個稍微複雜的移動端選項卡效果
html部分
<script src="http://cdn.bootcss.com/angular.js/1.3.8/angular.min.js"></script><script src="http://cdn.bootcss.com/angular.js/1.3.8/angular-touch.min.js"></script>//angularjs的一個移動端touch事件庫<div ng-app='myApp' ng-controller="myController"> <div class="type-tabs"> <div ng-repeat="item in [1,2,3,4]" ng-click="changeIndex($index)">Tab{{item}}</div> </div> <div class="guid-bar"> <div class="guid-bar-content" style="left:{{ 25*activeIndex}}%"></div> </div> <div class="tab-content" ng-swipe-right="swipeRight()" ng-swipe-left="swipeLeft()"> <div class="tab-content-inner" style="left:{{ -100*activeIndex}}%"> <div class="tab-content-item" ng-repeat="item in [1,2,3,4]" > <br /><br /><br /><br /> <h1>Tab{{item}} </h1></div> </div> </div></div>
css部分
*{ padding:0; margin:0; font-family:'Arial';}.type-tabs{ width: 100%; height: 40px;}.type-tabs div{ float: left; width: 25%; line-height: 40px; text-align: center; cursor:pointer; user-select:none; -webkit-user-select:none;}.guid-bar{ position: relative; margin-top: -3px;}.guid-bar-content{ width: 25%; height: 3px; background-color: #345; position: absolute; left: 50%; transition:all 400ms ease;}.tab-content{ width: 100%; height: 500px; background-color: #ccc; overflow: hidden;}.tab-content-inner{ width: 400%; position: relative; transition: all 400ms;}.tab-content-item{ width: 25%; float: left; text-align:center;}
js部分
var myApp=angular.module('myApp',['ngTouch']);myApp.controller('myController',function($scope){ $scope.activeIndex=0; $scope.changeIndex=function(index){ $scope.activeIndex=index; }; $scope.swipeLeft=function(){ $scope.activeIndex=++$scope.activeIndex; $scope.check(); }; $scope.swipeRight=function(){ $scope.activeIndex=--$scope.activeIndex; $scope.check(); }; $scope.check=function(){ if($scope.activeIndex>3) $scope.activeIndex=0; if($scope.activeIndex<0) $scope.activeIndex=3; }})
效果如下:
好了,今天我們就給出這兩個例子,對angularjs瞭解過的童鞋,直接看代碼應該可以很快看懂。沒瞭解過的童鞋,也能通過這兩個例子,瞭解到mvvm的黑魔法,以及它的程式碼群組織結構。
4、angularjs的mvvm模式比jquery的dom操作好在哪裡?
1、從宏觀上來說,一種是操作資料處理資料,一種是操作dom和ui互動。
一般網頁項目的流程可以總結為三個流程:1) 你要擷取介面上的資料 2)後台交換資料3)擷取資料後,對介面重新進行渲染。這個過程中,你和後台資料交換怎麼實現?jquery的ajax吧,如果資料交換的API假設20多個,那麼$.get或者$.ajax你要寫多少個才能全部包含進去?而且所有API連結都不在一個地方,管理起來相當麻煩。而angularjs只要配置一下route
就行了。
擷取了資料後,你又如何管理這些資料,如何把資料渲染到介面上去?
如何管理各種事件?jquery本身特性,也就是事件觸發,很多時候,就是你在編寫 觸發事件->處理資料 的流程。很顯然,功能一多,代碼就會和麵條一樣,交織在一起了。身邊不乏兩三年的傳統jquery前端,事件委託、dom操作、瀏覽器渲染過程、外掛程式組件封裝等等都沒有去深入研究,可想而知代碼品質有多爛。事實上jquery是一個類庫,並不是一個開發架構,jq是對js原生api的進一步封裝,讓你更加愉快的進行dom操作、動畫操作以及ajax,正是因為他太過靈活,所以更容易寫出難以維護的代碼。
2、效能方面:DOM操作慢,DOM對象本身也是一個js對象,所以嚴格來說,並不是操作這個對象慢,而是說操作了這個對象後,會觸發一些瀏覽器行為,比如布局(layout)和繪製(paint)。
總結
隨著web產品越來越複雜,分層架構是必不可少的,因此雙向繫結作為解藥,結合很早就流行的MVC架構,衍生出MVVM這神器。博主堅信,mvvm會是前端的終極解決方案。由DOM操作到資料操作需要一個過程去適應,但只要結果是好的,這些付出就都值得。在這個過程中,也是對你專業能力的一種提升。加油小夥伴們!!!