关于慕课网《使用vue2.0实现购物车和地址选配功能》的总结

视频学习网址:http://www.imooc.com/learn/796

源码打包:https://codeload.github.com/fachaoshao/Vue-ShoppingCart/zip/master(before为老师未写功能的源码,after为实现功能后的源码);

注意:以上源码请在 Apache 打开状态打开浏览;

该教程在功能上实现了:

1)将  .json文件数据发送http请求,通过遍历数组将数据渲染到页面;

2)创建过滤器实现了价格加“¥”和保留2位小数,分局部过滤器和全局过滤器;
3)实现了全选和取消全选的功能,通过v-bind:class
4)实现商品金额的计算和删除功能;
5)收货地址的卡片选择和设置默认地址;



下面说说我在该课程中get到的知识

在近期对 Vue 2.0 轮番轰炸般的学习之后,了解到 vue 这个框架是一个轻量级、高性能的js框架,在处理高并发的事件时vue较原生js或者jquery具有非常好的优势,因为他是一个MVVM模式(Model-View-ViewModel)的一个设计模式,以数据驱动为为核心思想,当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom.也就是说,vuejs帮我们封装了数据和dom对象操作的映射,我们只需要关心数据的逻辑处理,数据的变化就能够自然的通知页面进行页面的重新渲染。

MVVM框架

Vuejs的数据驱动是通过MVVM这种框架来实现的。MVVM框架主要包含3个部分:model、view和 viewmodel。

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现购物车功能,需要以下步骤: 1. 创建一个商品列表,包含每个商品的名称,价格和数量。 2. 在页面上展示商品列表,每个商品都有一个加入购物车的按钮。 3. 点击加入购物车按钮时,将对应商品的信息加入购物车列表中。 4. 在页面上展示购物车列表,包含每个商品的名称,价格,数量和小计金额。 5. 可以对购物车中的商品进行删除或修改数量操作。 6. 计算购物车中所有商品的总价。 下面是一个简单的 Vue 2.0 实现购物车功能的示例代码: HTML: ``` <div id="app"> <h2>商品列表</h2> <ul> <li v-for="item in goods"> {{ item.name }} - {{ item.price }}元 <button @click="addToCart(item)">加入购物车</button> </li> </ul> <h2>购物车</h2> <table> <thead> <tr> <th>名称</th> <th>单价</th> <th>数量</th> <th>小计</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="(item, index) in cart"> <td>{{ item.name }}</td> <td>{{ item.price }}元</td> <td> <input type="number" v-model="item.quantity" min="1"> </td> <td>{{ item.price * item.quantity }}元</td> <td> <button @click="removeFromCart(index)">删除</button> </td> </tr> </tbody> </table> <p>总价:{{ totalPrice }}元</p> </div> ``` JavaScript: ``` new Vue({ el: '#app', data: { goods: [ { name: '商品1', price: 10, quantity: 1 }, { name: '商品2', price: 20, quantity: 1 }, { name: '商品3', price: 30, quantity: 1 } ], cart: [] }, methods: { addToCart(item) { let index = this.cart.findIndex(cartItem => cartItem.name === item.name) if (index !== -1) { this.cart[index].quantity++ } else { this.cart.push({ name: item.name, price: item.price, quantity: 1 }) } }, removeFromCart(index) { this.cart.splice(index, 1) } }, computed: { totalPrice() { return this.cart.reduce((total, item) => total + item.price * item.quantity, 0) } } }) ``` 在这个示例中,首先定义了一个商品列表和一个购物车列表,其中商品列表包含了每个商品的名称、价格和数量,购物车列表为空。在页面上展示商品列表时,为每个商品添加了一个加入购物车的按钮,并在点击按钮时调用 `addToCart` 方法将对应商品信息加入购物车列表中。在页面上展示购物车列表时,使用了一个表格来展示每个商品的名称、价格、数量和小计金额,并为每个商品添加了一个删除按钮,同时使用了一个计算属性来计算购物车中所有商品的总价。最后,在 `addToCart` 方法中还实现了判断购物车中是否已存在该商品的逻辑,如果存在则将对应商品的数量加 1,否则将该商品添加到购物车列表中。在 `removeFromCart` 方法中通过 `splice` 方法实现了删除购物车列表中的商品的逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值