摘要:中定義的處理業(yè)務(wù)邏輯與提供數(shù)據(jù)源,中的綁定負(fù)責(zé)渲染與響應(yīng)用戶點(diǎn)擊拖拽等行為,這樣就最大保證了視圖邏輯相分離。遠(yuǎn)離的世界,圍繞層控制器路由從后端放到前端,更加適合開發(fā)。
最近分別使用 Zepto 和 Avalon框架寫了個(gè) SPA項(xiàng)目,貼出來討論下 JS DOM操作為主 JS庫 與 MV* 框架的對比
案例(MV* 框架 與 DOM操作 JS庫 實(shí)例對比) 購物車頁面 JS業(yè)務(wù)邏輯(忽略 Ajax請求--Ajax請求時(shí)機(jī)根據(jù)產(chǎn)品具體情況而定)以列表方式展示購物車商品
每件商品有"+"、"-" 按鈕,點(diǎn)擊該按鈕則:
檢測是否達(dá)到購買極限(如:最小購買數(shù)量不能小于 1件)
達(dá)到購買極限則給該按鈕添加相應(yīng)的 class 以便提示用戶該按鈕不能再點(diǎn)擊
反之則去掉該按鈕上的該 class(如:現(xiàn)在商品數(shù)量為 1,"-" 為不可用狀態(tài),現(xiàn)在點(diǎn)擊 "+" 則 "-"變?yōu)榭捎脿顟B(tài))
改變該件商品數(shù)量
計(jì)算 并 更新該商品總價(jià)金額
重新計(jì)算 并 更新 購物車所有商品金額
移除單種商品
從視圖上找到該 DOM
然后移除該 DOM
重新計(jì)算 并 更新 購物車所有商品金額
移除購物車所有商品
顯示購物車無商品 div,引導(dǎo)用戶到商品列表等其它頁面
實(shí)現(xiàn): 實(shí)現(xiàn)一:Zepto 版以 DOM操作 JS庫實(shí)現(xiàn):jQuery、Zepto、MooTools)
通過后端控制器渲染頁面
view:
<{css src="page/cart.css"}>購物車 style="display: none;"<{/if}> ><{if !empty($cart.cartList)}>購物車空空如也
<{script src="page/cart.js"}> <{/if}>商品總價(jià)(不含運(yùn)費(fèi)) <{$cart.totalAmount|cur}> " class="topBtn">去結(jié)算<{foreach from=$cart.cartList item=item}><{/foreach}><{$item.cashcoupon.name}>
- +<{$item.cashcoupon.price|cur}><{$item.cashcoupon.mktprice|cur}>商品總價(jià)(不含運(yùn)費(fèi))<{$cart.totalAmount|cur}>
JS 邏輯
javascript實(shí)現(xiàn)二:Avalon版
// 全局常量 var UA = navigator.userAgent; var ipad = !!(UA.match(/(iPad).*OSs([d_]+)/)), isIphone = !!(!ipad && UA.match(/(iPhonesOS)s([d_]+)/)), isAndroid = !!(UA.match(/(Android)s+([d.]+)/)), isMobile = !!(isIphone || isAndroid); var CLICK = isMobile ? "tap" : "click"; // 移動(dòng)端觸摸、PC單擊 事件 // 購物車 var Cart = { // 更新 info update: function ($id, $number, fun) { var data = { id: $id || "", number: $number || 0 }; CGI.POST("wecart-update.html", data, function (data) { // 回調(diào)方法 fun && fun(data); }); }, // 計(jì)算總價(jià) figurePrice: function () { var goodsList = $(".goodslist"); console.log(goodsList); if (0 === goodsList.length) { this.removeAll(); return false; } // 當(dāng)前商品金額 var price; // 當(dāng)前商品數(shù)量 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({"數(shù)量": number, "單價(jià)": price}); allPrice += price * number; }); console.log("總價(jià):" + allPrice); // DOM 操作 $(".total").text("¥" + allPrice.toFixed(2)); }, // 移除所有 removeAll: function () { // DOM 操作 $("#emptyBox").show(); $(".box").hide(); } }; // 遞增、遞減 $(".numBox").on(CLICK, function (e) { // numBox var _t = $(this); var dom = $(e.target); // 商品數(shù)量 DOM var numDom = _t.find("input"); //console.log(numDom); // 數(shù)量 var _v = parseInt(numDom.val()), now_v; // 最大購買數(shù) var max = parseInt(numDom.attr("data-max-count")); if (dom.hasClass("plus")) { // 遞增 // 最大購買數(shù)量限制 if (_v === max) { return false; } now_v = (_v < 1) ? 1 : (_v >= max ? max : _v + 1); } else if (dom.hasClass("minus")) { // 遞減 // 最小購買數(shù)量限制 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"); // ajax Cart.update(cartId, now_v, function (data) { // 更改數(shù)量 numDom.val(now_v); // 遞減數(shù)量按鈕 var minus = _t.find(".minus"); // 遞增數(shù)量按鈕 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"); // 計(jì)算總價(jià) 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": "刪除成功!"}); // 移除當(dāng)先列 dom.remove(); // 計(jì)算總價(jià) 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: "再忍忍" } }); });
以 MV* 框架實(shí)現(xiàn):Angular、Avalon)
通過后端接口獲取購物車數(shù)據(jù),JS動(dòng)態(tài)渲染頁面
view:
html
JS 業(yè)務(wù)代碼
javascriptdefine("cart", ["avalon", "request"], function (avalon) { var avalonAjax = avalon.ajax; var model = avalon.define({ $id: "cart", toggle: true, price: 0, // 總金額 goodsList: [], // 遞加數(shù)量 plus: function (index) { model.goodsList[index].quantity = parseInt(model.goodsList[index].quantity) + 1; // 計(jì)算總數(shù)量 和 總金額 count(); }, // 遞減數(shù)量 minus: function (index) { if (model.goodsList[index].quantity <= 1) { return false; } model.goodsList[index].quantity = parseInt(model.goodsList[index].quantity) - 1; // 計(jì)算總數(shù)量 和 總金額 count(); }, // 移除當(dāng)前 remove: function (index, perish) { perish(); // 移除 }, // 移除所有 removeAll: function () { avalon.vmodels.cart.goodsList.clear(); // 計(jì)算總數(shù)量 和 總金額 count(); } }); // 獲取數(shù)據(jù) var getData = function () { if (avalonAjax) { avalon.getJSON("", {method: "ecoupon.cart.list"}, function (data) { model.price = data.totalAmount; model.goodsList = data.cartList; }) } }(); // 計(jì)算總數(shù)量 和 總金額 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); }; // 購物車數(shù)量監(jiān)聽(目前只能監(jiān)聽商品種類變化, 不能監(jiān)聽商品數(shù)量變化) model.goodsList.$watch("length", function () { count(); }); return model; });
zepto 版本中,js 業(yè)務(wù)代碼大量使用了 選擇器 來 操作DOM,導(dǎo)致 js 與 view 極度耦合。
優(yōu)點(diǎn)avalon版本,利用avalon可以大大加快我們項(xiàng)目的開發(fā)速度,可以使我們遠(yuǎn)離 DOM的世界,我們的編程變成了只圍繞 model層而不圍繞 DOM,即操作 model就是操作 DOM,同時(shí)能讓我們開發(fā)人員離開 DOM都能輕松進(jìn)行前端開發(fā)。avalon中定義的 VM處理業(yè)務(wù)邏輯與提供數(shù)據(jù)源,HTML中的綁定負(fù)責(zé)渲染與響應(yīng)用戶點(diǎn)擊拖拽等行為,這樣就最大保證了視圖邏輯相分離。
JS 與 view 解耦。遠(yuǎn)離 DOM的世界,圍繞 model層
控制器、路由從后端放到前端,更加適合 Web APP開發(fā)。SPA應(yīng)用可以提供更好的用戶體驗(yàn)
業(yè)務(wù)實(shí)現(xiàn)的方式轉(zhuǎn)變(由直接操作 DOM變?yōu)?操作 VM,更加適合后端童鞋思維方式)
更容易實(shí)現(xiàn)前后端分離
官方講代碼量比 jQuery減少50%
....
缺點(diǎn)MV* 框架學(xué)習(xí)成本高,概念多(控制器、路由、指令、過濾器、服務(wù)、依賴注入...)[哈哈、后端同學(xué)最喜歡這種了,學(xué)習(xí)起來無壓力]
發(fā)展時(shí)間沒有 jQuery這種時(shí)間長,組件相比 jQuery相差比較大(大多數(shù)需要自己實(shí)現(xiàn))
動(dòng)畫
SEO(貌似有解決方案了)
...
具體選擇就看場景了吧,動(dòng)畫效果、特效多用 jQuery這種,業(yè)務(wù)復(fù)雜用 MV* 這種
原文發(fā)在:http://www.webdevs.cn/article/93.html
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85506.html
摘要:從協(xié)作關(guān)系上講,很多前端開發(fā)團(tuán)隊(duì)每個(gè)成員的職責(zé)不是很清晰,有了前端的框架,這個(gè)狀況會(huì)大有改觀??蚣艿睦砟钍前亚岸税凑章氊?zé)分層,每一層都相對比較獨(dú)立,有自己的價(jià)值,也有各自發(fā)揮的余地。 簡介: MV框架又是為什么興起的呢?它的出現(xiàn),伴隨著一些 Web 產(chǎn)品逐漸往應(yīng)用方向發(fā)展,遇到了在 C/S 領(lǐng)域相同的問題:由于前端功能的增強(qiáng)、代碼的膨脹,導(dǎo)致不得不做前端的架構(gòu)這個(gè)事情了。經(jīng)常有人質(zhì)疑...
摘要:前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。背后的故事本文是對于年之間世界發(fā)生的大事件的詳細(xì)介紹,闡述了從提出到角力到流產(chǎn)的前世今生。 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡迎...
摘要:就是一個(gè)用于搭建類似于網(wǎng)頁版知乎這種表單項(xiàng)繁多,且內(nèi)容需要根據(jù)用戶的操作進(jìn)行修改的網(wǎng)頁版應(yīng)用。單頁應(yīng)用程序顧名思義,單頁應(yīng)用一般指的就是一個(gè)頁面就是應(yīng)用,當(dāng)然也可以是一個(gè)子應(yīng)用,比如說知乎的一個(gè)頁面就可以視為一個(gè)子應(yīng)用。 最近在逛各大網(wǎng)站,論壇,以及像SegmentFault等編程問答社區(qū),發(fā)現(xiàn)Vue.js異?;鸨貜?fù)性的提問和內(nèi)容也很多,樓主自己也趁著這個(gè)大前端的熱潮,著手學(xué)習(xí)了一...
摘要:前言終于要做這個(gè)計(jì)劃了,前端框架千千萬,絕不能一頭扎進(jìn)去盲目開始,本片文章總結(jié)一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學(xué)習(xí)計(jì)劃。希望入了前端坑的同學(xué)們可以有所幫助。但是庫與框架很難嚴(yán)格區(qū)分,所以統(tǒng)一稱為解決方案。 前言:終于要做這個(gè)計(jì)劃了,前端框架千千萬,絕不能一頭扎進(jìn)去盲目開始,本片文章總結(jié)一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學(xué)...
摘要:因?yàn)槠浣M件只是根據(jù)提供的及屬性,生成動(dòng)畫的數(shù)據(jù),業(yè)務(wù)應(yīng)用中拿到生成的數(shù)據(jù)后根據(jù)需要添加需要?jiǎng)赢嫷慕M件樣式。除了上述簡單的動(dòng)畫應(yīng)用,在復(fù)雜動(dòng)畫的實(shí)現(xiàn)方面,表現(xiàn)非常優(yōu)越。 WEB應(yīng)用中動(dòng)畫很重要 不管是web應(yīng)用還是原生應(yīng)用,也不論是PC端應(yīng)用還是移動(dòng)端應(yīng)用,動(dòng)畫都扮演了一個(gè)重要的角色。 盡管動(dòng)畫并不會(huì)添加應(yīng)用的實(shí)際動(dòng)能,但一個(gè)好的動(dòng)畫,一個(gè)流暢且優(yōu)雅,選擇在恰當(dāng)時(shí)機(jī)出現(xiàn)的動(dòng)畫,能為應(yīng)用增...
閱讀 3061·2021-11-25 09:43
閱讀 1038·2021-11-24 10:22
閱讀 1367·2021-09-22 15:26
閱讀 694·2019-08-30 15:44
閱讀 2471·2019-08-29 16:33
閱讀 3709·2019-08-26 18:42
閱讀 921·2019-08-23 18:07
閱讀 1841·2019-08-23 17:55