關於慕課網《使用vue2.0實現購物車和地址選配功能》的總結

視頻學習網址:http://www.imooc.com/learn/796javascript

源碼打包:https://codeload.github.com/fachaoshao/Vue-ShoppingCart/zip/master(before爲老師未寫功能的源碼,after爲實現功能後的源碼);html

注意:以上源碼請在 Apache 打開狀態打開瀏覽;前端

該教程在功能上實現了:vue

1)將  .json文件數據發送http請求,經過遍歷數組將數據渲染到頁面;java

2)建立過濾器實現了價格加「¥」和保留2位小數,分局部過濾器和全局過濾器;
3)實現了全選和取消全選的功能,經過v-bind:class
4)實現商品金額的計算和刪除功能;
5)收貨地址的卡片選擇和設置默認地址;react



下面說說我在該課程中get到的知識jquery

在近期對 Vue 2.0 輪番轟炸般的學習以後,瞭解到 vue 這個框架是一個輕量級、高性能的js框架,在處理高併發的事件時vue較原生js或者jquery具備很是好的優點,由於他是一個MVVM模式(Model-View-ViewModel)的一個設計模式,以數據驅動爲爲核心思想,當數據發生變化的時候,用戶界面發生相應的變化,開發者不須要手動的去修改dom.也就是說,vuejs幫咱們封裝了數據和dom對象操做的映射,咱們只須要關心數據的邏輯處理,數據的變化就可以天然的通知頁面進行頁面的從新渲染。git

MVVM框架angularjs

Vuejs的數據驅動是經過MVVM這種框架來實現的。MVVM框架主要包含3個部分:model、view和 viewmodel。es6

Model:指的是數據部分,對應到前端就是javascript對象

View:指的是視圖部分,對應前端就是dom

Viewmodel:就是鏈接視圖與數據的中間件


數據(Model)和視圖(View)是不能直接通信的,而是須要經過ViewModel來實現雙方的通信。當數據變化的時候,viewModel可以監聽到這種變化,並及時的通知view作出修改。一樣的,當頁面有事件觸發時,viewMOdel也可以監聽到事件,並通知model進行響應。Viewmodel就至關於一個觀察者,監控着雙方的動做,並及時通知對方進行相應的操做,這樣就造成了以數據的雙向綁定。

數據響應原理

數據(model)改變 驅動 視圖(view)自動更新

首先,vuejs在實例化的過程當中,會對遍歷傳給實例化對象選項中的data 選項,遍歷其全部屬性並使用 Object.defineProperty 把這些屬性所有轉爲 getter/setter

同時每個實例對象都有一個watcher實例對象,他會在模板編譯的過程當中,用getter去訪問data的屬性,watcher此時就會把用到的data屬性記爲依賴,這樣就創建了視圖與數據之間的聯繫。當以後咱們渲染視圖的數據依賴發生改變(即數據的setter被調用)的時候,watcher會對比先後兩個的數值是否發生變化,而後肯定是否通知視圖進行從新渲染。

這樣就實現了所謂的數據對於視圖的驅動。




下面詳細說下慕課網《使用vue2.0實現購物車和地址選配功能》功能實現的總結

1)將  .json文件數據發送http請求,經過遍歷數組將數據渲染到頁面;

在methods:裏面定義方法:發送http請求,得到json數據

cartView: function () {
        	// var _this = this;
        	this.$http.get('data/cartData.json').then(res=>{
        		//此處使用了箭頭函數,使得內部的this與外部this保持一致,能夠不用上面聲明的
        		//_this了
        		this.productList = res.data.result.list;
        		// this.totalMoney = res.data.result.totalMoney;
        	})
        },

使用了v-for,v-model,v-bind(:),v-if,v-on(@click)等基本api指令,將數據渲染到頁面

2)建立過濾器實現了價格加「¥」和保留2位小數,分局部過濾器和全局過濾器;

局部過濾器,寫在new Vue({})的 選項 裏面

filters:{// 局部過濾器,在做用域內調用
    	formatMoney:function(value){
    		return "¥"+value.toFixed(2)+ '元'
    	}
    }

經過管道符號改變數據內容  {{ item.productPrice | formatMoney }}   ¥19.00元

全局過濾器

Vue.filter('money',function(value,type) {// 全局過濾器,在全局範圍內可用
	return "¥"+value.toFixed(2) + type;
});
經過管道符號改變數據內容   {{totalMoney | money('元')}}   ¥256.00元  區別於局部過濾器,在vue2.0中,定義的全局過濾器是一個函數,money中傳入的參數  「元」  是第二個參數 type,

參考(https://cn.vuejs.org/v2/guide/migration.html#過濾器參數符號-變動)

3)實現了全選和取消全選的功能,經過v-bind:class

單選按鈕:

<a href="javascript:;" class="item-check-btn" v-bind:class="{'check':item.checked}" 
v-on:click="selectedProduct(item)"
>
selectedProduct: function (item) {
        	if(typeof item.checked == "undefined"){
        		// Vue.set(item,'checked',true);  // 全局註冊
        		this.$set(item,'checked',true) 
        	}else{
        		item.checked = !item.checked;
        	};
            this.calcTotalPrice(); 
        	
        },
若是item裏面的checked不存在,就給他註冊一個變量(通常都是在data裏面註冊一個變量的),而且設置值爲true,這樣在頁面就能夠顯示被選中狀態;


全選/取消全選按鈕:

綁定一個點擊函數,傳值爲true,就全選,false就取消全選

注意到:var _this = this;是es5的語法。要是採用es6的箭頭函數,內部this就和外部this保持一致了

這裏的思路是:傳入的flag(true/false)保存在checkAllFlag中,遍歷productList   item.checked沒被建立,我建立一個,設置他們的值都爲checkAllFlag,若建立了,直接設置爲checkAllFlag。這個遍歷的過程就達到了一個 全選/取消全選 的目的。

<span class="item-check-btn" :class="{'check':checkAllFlag}" @click="checkAll(true)">全選按鈕
<a href="javascript:void 0" class="item-del-btn" @click="checkAll(false)">取消全選按鈕
checkAll: function (flag) {
        	this.checkAllFlag = flag;
        	var _this = this;
        	this.productList.forEach(function(item,index){
	        	if(typeof item.checked == "undefined"){
	        		// Vue.set(item,'checked',true);  // 全局註冊
	        		_this.$set(item,'checked',_this.checkAllFlag)
	        	}else{
	        		item.checked = _this.checkAllFlag
	        	}
    		});
            this.calcTotalPrice();
        },

4)實現商品金額的計算和刪除功能;

這裏有單個商品的金額計算和總金額的計算

單個商品的金額計算:{{ item.productPrice * item.productQuantity | money('元')}}

總金額的計算:{{totalMoney | money('元')}}

而後就是改變單個商品數量以及選中商品或者全選商品,要是的總金額動態改變

首先定義一個函數:calcTotalPrice,設置this.totalMoney = 0;爲何呢?由於你每次金額變動前都得把總金額設置爲0吧,否則在前面的基礎上運算,好比我前面點擊選中了,總金額變了,而後我取消了,總金額依然是以前的,因此得設置this.totalMoney = 0,每次計算前清0;

遍歷數組productList

_this.totalMoney += item.productPrice*item.productQuantity;  疊加數組紅全部商品金額就是總金額了

以後考慮選中與未選中以及全選和取消全選致使的總金額變化,因此他們都得調一次this.calcTotalPrice();實現總金額的計算;

changeMoney:function (product,way) {
        	if(way>0){
        		product.productQuantity++;
        	}else{
        		product.productQuantity--;
        		if(product.productQuantity < 1){
        			product.productQuantity = 1
        		}
        	};
        	this.calcTotalPrice();
        },
        selectedProduct: function (item) {
        	if(typeof item.checked == "undefined"){
        		// Vue.set(item,'checked',true);  // 全局註冊
        		this.$set(item,'checked',true)
        	}else{
        		item.checked = !item.checked;
        	};
            this.calcTotalPrice();
        	
        },
        checkAll: function (flag) {
        	this.checkAllFlag = flag;
        	var _this = this;
        	this.productList.forEach(function(item,index){
	        	if(typeof item.checked == "undefined"){
	        		// Vue.set(item,'checked',true);  // 全局註冊
	        		_this.$set(item,'checked',_this.checkAllFlag)
	        	}else{
	        		item.checked = _this.checkAllFlag
	        	}
    		});
            this.calcTotalPrice();
        },
        calcTotalPrice:function(){
            var _this = this;
            this.totalMoney = 0;
            this.productList.forEach(function(item,index){
                if(item.checked){
                    _this.totalMoney += item.productPrice*item.productQuantity;
                }
            });
        },

5)收貨地址的卡片選擇和設置默認地址;

首先依然是遍歷出  .json裏面的地址,注意到這裏的 v-for="(address,index) in filterAddress",相比angular中的ng-repeat = "(index,address) in filterAddress" ,   angularjs是先寫下標,再寫值,注意啊,正好相反。vue 1.0中也是(index,address)與angualr相同;

這裏我就把js代碼都放上來了,不分段截取了

能夠看到也是先發送$http請求,獲取數據,注意獲取的數據保存在response.data中,而不是子response中,作項目是能夠查看下;

爲了作加載更多,咱們先讓它顯示3條數據,因此咱們設置limitNum:3, 在computed中  return this.addressList.slice(0,this.limitNum),全部咱們得遍歷filterAddress 的數據,當咱們點擊more時,@click="loadMore",觸發loadMore函數,this.limitNum = this.addressList.length,就能夠加載addressList中全部的地址了

卡片地址選擇:把點擊的index賦值給currentIndex,當index==currentIndex時,顯示被選中,這個挺重要的

<li v-for="(address,index) in filterAddress" :class="{'check':index == currentIndex}" 
@click="currentIndex = index">
new Vue({
	el:'.container',
	data:{
		addressList:[],
		limitNum:3,
		currentIndex:0,
		shippingMethods:1
	},
	mounted: function () {
	  this.$nextTick(function () {
	  	this.getAddressList()
	  })
	},
	methods:{
		getAddressList:function(){
			this.$http.get("data/address.json").then(response=>{
				console.log(response)
				var res = response.data;
				this.addressList = res.result;
			})
		},
		loadMore:function(){
			this.limitNum = this.addressList.length
		},
		setDefault:function(addressId){
			this.addressList.forEach(function(address,index){
				if(address.addressId == addressId){
					address.isDefault = true;
				}else{
					address.isDefault = false;
				}
			})
		}
	},
	computed:{
		filterAddress:function(){
			return this.addressList.slice(0,this.limitNum)
		}
	}
})
設置默認地址:
v-if="!address.isDefault" @click="setDefault(address.addressId)">設爲默認
<div class="addr-opration addr-default" v-if="address.isDefault">默認地址
v-if控制顯示與隱藏,當點擊設爲默認觸發setDefault,傳的addressId值,設置當前點擊的addressId爲默認地址

最後就是配送方式了

<li v-bind:class="{'check':shippingMethods == 1}" @click="shippingMethods=1">標準配送
<li class="name" v-bind:class="{'check':shippingMethods == 2}" @click="shippingMethods=2">高級配送
選中狀態爲check,標準配送 shippingMethods == 1決定check顯示選中,當點擊標準配送時 shippingMethods == 1,

當點擊高級配送時shippingMethods == 2,經過修改shippingMethods值決定顯示誰!


上述文字都是我的看法,不當之處,還請各位指正!


參考文獻:

https://cn.vuejs.org/v2/guide/reactivity.html

http://www.cnblogs.com/caizhenbo/p/6418284.html

http://www.cnblogs.com/caizhenbo/p/6710174.html

相關文章
相關標籤/搜索