當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
MV* 框架 与 DOM操作为主 JS库 的案例对比
生活随笔
收集整理的這篇文章主要介紹了
MV* 框架 与 DOM操作为主 JS库 的案例对比
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近分別使用 Zepto 和 Avalon框架寫了個 SPA項目,貼出來討論下 JS DOM操作為主 JS庫 與 MV* 框架的對比
案例(MV* 框架 與 DOM操作 JS庫 實例對比)
購物車頁面 JS業務邏輯(忽略 Ajax請求--Ajax請求時機根據產品具體情況而定)
- 以列表方式展示購物車商品
- 每件商品有"+"、"-" 按鈕,點擊該按鈕則:
- 檢測是否達到購買極限(如:最小購買數量不能小于 1件)
- 達到購買極限則給該按鈕添加相應的 class 以便提示用戶該按鈕不能再點擊
- 反之則去掉該按鈕上的該 class(如:現在商品數量為 1,"-" 為不可用狀態,現在點擊 "+" 則 "-"變為可用狀態)
- 改變該件商品數量
- 計算 并 更新該商品總價金額
- 重新計算 并 更新 購物車所有商品金額
- 移除單種商品
- 從視圖上找到該 DOM
- 然后移除該 DOM
- 重新計算 并 更新 購物車所有商品金額
- 移除購物車所有商品
- 顯示購物車無商品 div,引導用戶到商品列表等其它頁面
實現:
實現一:Zepto 版
以 DOM操作 JS庫實現:jQuery、Zepto、MooTools)
通過后端控制器渲染頁面
view:
<{css src="page/cart.css"}><header class="titleHead"><div class="leftBtns"><a class="leftBack goBack" href="javascript:void(0)">←</a></div><b>購物車</b> </header><div id="emptyBox" <{if !empty($cart.cartList)}> style='display: none;'<{/if}> > <p>購物車空空如也</p><p><a href="<{link app='wechatecoupon' ctl='site_cashcoupon' act='group'}>">去添加</a></p> </div><{if !empty($cart.cartList)}><div class="box"><div id="topTotal"><span>商品總價(不含運費)<b class="total"><{$cart.totalAmount|cur}></b></span><a href="<{link app='wechatecoupon' ctl='site_order' act='create'}>" class="topBtn">去結算</a></div><div class="goodslistWrap"><{foreach from=$cart.cartList item=item}><div class="goodslist" data-cart-id="<{$item.cart_id}>" data-cashcoupon-id="<{$item.obj_id}>"data-price="<{$item.cashcoupon.price}>"><div class="imgWrap"><img src="<{$item.cashcoupon.image_id|storager}>" height="100%"/></div><div class="txtWrap"><p><{$item.cashcoupon.name}></p><div class="handleBox"><div class="numBox"><span class="handle minus <{if 1==$item.quantity}>bg_gray<{/if}>">-</span><span><input type="text" name="num" value="<{$item.quantity}>"data-max-count="<{$item.cashcoupon.sale_count}>" maxlength="4"readonly="readonly" /></span><span class="handle plus <{if $item.quantity >= $item.cashcoupon.sale_count}>bg_gray<{/if}>">+</span></div><div class="trashBox del"><i class="trash"></i></div></div></div><div class="priceWrap"><span><strong><{$item.cashcoupon.price|cur}></strong></span><span><del><{$item.cashcoupon.mktprice|cur}></del></span></div></div><{/foreach}><div class="clear"></div></div><div class="goodslistTotal"><span>商品總價(不含運費)<b class="total"><{$cart.totalAmount|cur}></b></span></div><div class="bottomTotal"><div class="delAll"><i class="trash_b"></i><span>清空全部</span></div><div class="payBtnBox"><a href="<{link app='wechatecoupon' ctl='site_order' act='create'}>" class="bottomBtn">去結算</a></div></div> </div><{script src="page/cart.js"}> <{/if}>JS 邏輯
javascript// 全局常量var UA = navigator.userAgent; var ipad = !!(UA.match(/(iPad).*OS\s([\d_]+)/)),isIphone = !!(!ipad && UA.match(/(iPhone\sOS)\s([\d_]+)/)),isAndroid = !!(UA.match(/(Android)\s+([\d.]+)/)),isMobile = !!(isIphone || isAndroid);var CLICK = isMobile ? "tap" : 'click'; // 移動端觸摸、PC單擊 事件// 購物車 var Cart = {// 更新 infoupdate: function ($id, $number, fun) {var data = {id: $id || '',number: $number || 0};CGI.POST('wecart-update.html', data, function (data) {// 回調方法fun && fun(data);});},// 計算總價figurePrice: function () {var goodsList = $(".goodslist");console.log(goodsList);if (0 === goodsList.length) {this.removeAll();return false;}// 當前商品金額var price;// 當前商品數量var number;// 總金額var allPrice = 0;$.each(goodsList, function (index, item) {item = $(item);price = parseFloat(item.attr("data-price"));number = parseInt(item.find("input").val());console.log({'數量': number, '單價': price});allPrice += price * number;});console.log('總價:' + allPrice);// DOM 操作$(".total").text("¥" + allPrice.toFixed(2));},// 移除所有removeAll: function () {// DOM 操作$("#emptyBox").show();$(".box").hide();}};// 遞增、遞減 $(".numBox").on(CLICK, function (e) {// numBoxvar _t = $(this);var dom = $(e.target);// 商品數量 DOMvar numDom = _t.find("input");//console.log(numDom);// 數量var _v = parseInt(numDom.val()), now_v;// 最大購買數var max = parseInt(numDom.attr("data-max-count"));if (dom.hasClass("plus")) {// 遞增// 最大購買數量限制if (_v === max) {return false;}now_v = (_v < 1) ? 1 : (_v >= max ? max : _v + 1);} else if (dom.hasClass("minus")) {// 遞減// 最小購買數量限制if (_v === 1) {return false;}now_v = (_v < 1) ? 1 : (_v > max ? max : _v - 1);} else {return false;}var cartId = dom.parents(".goodslist").attr("data-cashcoupon-id");// ajaxCart.update(cartId, now_v, function (data) {// 更改數量numDom.val(now_v);// 遞減數量按鈕var minus = _t.find(".minus");// 遞增數量按鈕var plus = _t.find(".plus");now_v > 1 && minus.hasClass("bg_gray") && minus.removeClass("bg_gray");now_v === 1 && !minus.hasClass("bg_gray") && minus.addClass("bg_gray");now_v < max && plus.hasClass("bg_gray") && plus.removeClass("bg_gray");now_v >= max && !plus.hasClass("bg_gray") && plus.addClass("bg_gray");// 計算總價Cart.figurePrice();});event.preventDefault(); });// 刪掉商品 $(".del").on(CLICK, function () {var dom = $(this).parents(".goodslist");var cartId = dom.attr("data-cashcoupon-id");cartId && Cart.update(cartId, 0, function (data) {// 提示SD.Toast({'text': '刪除成功!'});// 移除當先列dom.remove();// 計算總價Cart.figurePrice();}); });// 刪掉所有商品 $(".delAll").on(CLICK, function (event) {SD.Confirm({content: '你確定要清空購物車嗎?',//lock: false,ok: {text: '殘忍清空',fun: function () {Cart.update('', 0, function (data) {// 提示SD.Toast({'text': '刪除成功!'});// DOM 操作Cart.removeAll();});}},cancel: {text: '再忍忍'}}); });
實現二:Avalon版
以 MV* 框架實現:Angular、Avalon)
通過后端接口獲取購物車數據,JS動態渲染頁面
view:
html<div ms-controller="cart"><div id="emptyBox" ms-visible="goodsList.length==0" style="display: none"><p>購物車空空如也</p><p><a href="#!/">去添加</a></p></div><div ms-visible="goodsList.length>0"><div id="topTotal"><span>商品總價(不含運費)<b>{{price|currency}}</b></span><a href="pay.html" class="topBtn">去結算</a></div><div class="goodslistWrap"><div class="goodslist" ms-repeat="goodsList"><div class="imgWrap"><img ms-src="{{el.cashcoupon.image}}" height="100%"/></div><div class="txtWrap"><p>{{el.cashcoupon.name}}</p><div class="handleBox"><div class="numBox"><span class="handle minus" ms-class-bg_gray="el.quantity<=1" ms-click="minus($index)">-</span><span><input type="text" ms-attr-value="{{el.quantity}}"/></span><span class="handle plus" ms-click="plus($index)">+</span></div><div class="trashBox" ms-click="remove($index,$remove)"><i class="trash"></i></div></div></div><div class="priceWrap"><span><strong>{{el.cashcoupon.price|currency}}</strong></span><span><del>{{el.cashcoupon.mktprice|currency}}</del></span></div></div><!--last--><div class="clear"></div></div><div class="goodslistTotal"><span>商品總價(不含運費)<b>{{price|currency}}</b></span></div><div class="bottomTotal"><div class="delAll" ms-click="removeAll"><i class="trash_b"></i><span>清空全部</span></div><div class="payBtnBox"><a href="pay.html" class="bottomBtn">去結算</a></div></div></div> </div>
JS 業務代碼
javascriptdefine("cart", ["avalon", "request"], function (avalon) {var avalonAjax = avalon.ajax;var model = avalon.define({$id: "cart",toggle: true,price: 0, // 總金額goodsList: [],// 遞加數量plus: function (index) {model.goodsList[index].quantity = parseInt(model.goodsList[index].quantity) + 1;// 計算總數量 和 總金額count();},// 遞減數量minus: function (index) {if (model.goodsList[index].quantity <= 1) {return false;}model.goodsList[index].quantity = parseInt(model.goodsList[index].quantity) - 1;// 計算總數量 和 總金額count();},// 移除當前remove: function (index, perish) {perish(); // 移除},// 移除所有removeAll: function () {avalon.vmodels.cart.goodsList.clear();// 計算總數量 和 總金額count();}});// 獲取數據var getData = function () {if (avalonAjax) {avalon.getJSON('', {method: 'ecoupon.cart.list'}, function (data) {model.price = data.totalAmount;model.goodsList = data.cartList;})}}();// 計算總數量 和 總金額function count() {var _count = 0;var _price = 0;model.goodsList.forEach(function (goods, index) {_count += parseInt(goods.quantity);_price += parseFloat(goods.cashcoupon.price) * parseInt(goods.quantity);});avalon.vmodels.page.cartNum = _count;model.price = _price.toFixed(2);};// 購物車數量監聽(目前只能監聽商品種類變化, 不能監聽商品數量變化)model.goodsList.$watch("length", function () {count();});return model;});zepto 版本中,js 業務代碼大量使用了 選擇器 來 操作DOM,導致 js 與 view 極度耦合。
avalon版本,利用avalon可以大大加快我們項目的開發速度,可以使我們遠離 DOM的世界,我們的編程變成了只圍繞 model層而不圍繞 DOM,即操作 model就是操作 DOM,同時能讓我們開發人員離開 DOM都能輕松進行前端開發。avalon中定義的 VM處理業務邏輯與提供數據源,HTML中的綁定負責渲染與響應用戶點擊拖拽等行為,這樣就最大保證了視圖邏輯相分離。
優點
- JS 與 view 解耦。遠離 DOM的世界,圍繞 model層
- 控制器、路由從后端放到前端,更加適合 Web APP開發。SPA應用可以提供更好的用戶體驗
- 業務實現的方式轉變(由直接操作 DOM變為 操作 VM,更加適合后端童鞋思維方式)
- 更容易實現前后端分離
- 官方講代碼量比 jQuery減少50%
- ....
缺點
- MV* 框架學習成本高,概念多(控制器、路由、指令、過濾器、服務、依賴注入...)[哈哈、后端同學最喜歡這種了,學習起來無壓力]
- 發展時間沒有 jQuery這種時間長,組件相比 jQuery相差比較大(大多數需要自己實現)
- 動畫
- SEO(貌似有解決方案了)
- ...
具體選擇就看場景了吧,動畫效果、特效多用 jQuery這種,業務復雜用 MV* 這種
原文發在:http://www.webdevs.cn/article/93.html
總結
以上是生活随笔為你收集整理的MV* 框架 与 DOM操作为主 JS库 的案例对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ipython中如何输入汉字
- 下一篇: Linux例行工作crontab