视频学习网址: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

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

  1. VUE2.0实现购物车和地址选配功能学习第一节(来源--慕课网河畔一角)

    第一节  vue知识 vue-resource:和后台交互的一个插件,实现get.post和jsonp等功能.(替代jQuery) vue特点: 1.易用:通过创建vue实例,{{}}绑定数据十分方便 ...

  2. VUE2.0实现购物车和地址选配功能学习第七节

    第七节 卡片选中,设置默认 1.卡片选中html:<li v-for="(item,index) in filterAddress" v-bind:class="{ ...

  3. VUE2.0实现购物车和地址选配功能学习第六节

    第六节 地址列表过滤和展开所有的地址 html:<li v-for="(item,index) in filterAddress">js: new Vue({ el:' ...

  4. VUE2.0实现购物车和地址选配功能学习第五节

    第五节 单件商品金额计算和单选全选功能 1.vue精髓在于操作data模型来改变dom,渲染页面,而不是直接去改变dom 2.加减改变总金额功能: html:<div class="c ...

  5. VUE2.0实现购物车和地址选配功能学习第四节

    第四节 v-on实现金额动态计算 用¥金额 进行格式处理,可以使用原生js进行转换,但是在vuei,使用filter过滤器更加方便 注: 1.es6语法=>和import等 好处在于res参数后 ...

  6. VUE2.0实现购物车和地址选配功能学习第三节

    第三节 使用v-for渲染商品列表 1.使用vue-resource插件引入json数据 (注:在谷歌中调试打断点-- ,console还可以输出vm,res等属性列表,或者productList等一 ...

  7. VUE2.0实现购物车和地址选配功能学习第二节

    第二节 创建VUE实例 购物车项目计划: 1.创建一个vue实例 2.通过v-for指令渲染产品数据 3.使用filter对金额和图片进行格式化 4.使用v-on实现产品金额动态计算 5.综合演示 ① ...

  8. vue2.0实现购物车功能

    购物车功能是一件比较繁琐的事情,逻辑功能太多,今天就用vue2.0实现一个简单的购物车功能,数据都本地自己写的假数据 功能列表: 1.全选和单选结算 2.减少和增加数量 3.商品的删除 界面搭建以及布 ...

  9. vue购物车和地址选配(三)

    参考资料:vue.js官网 项目演示: 项目源代码: 核心代码及踩坑 删除: new Vue({ el:'#app', data:{ productlist:[], totalMoney:0, che ...

随机推荐

  1. python+minicap的使用

    说起Minicap,不得不提到STF,STF (Smartphone Test Farm) 是一个开源的web架构应用,用户可通过浏览器远程操作Android设备.调试Android应用.在设备上进行 ...

  2. hive报错java.sql.SQLException: null, message from server: "Host '192.168.126.100' is not allowed to connect to this MySQL server"

  3. ubuntu终端安装最新ss

    有时候因为加密方式比较新,比如aes-256-gcm,导致旧版本的不能用 一句命令安装ss最新版本 aes-256-gcm加密方式可以用,没毛病

  4. Linux服务之httpd基本配置详解

    一.基本介绍 1.版本 httpd-1.3 httpd-2.0 httpd-2.2 httpd-2.4 目前为止最新的版本是httpd-2.4.6,但是这里我用的是系统自带的RPM包安装的httpd- ...

  5. 为你的docker容器增加一个健康检查机制

    1.健康检查 在分布式系统中,经常需要利用健康检查机制来检查服务的可用性,防止其他服务调用时出现异常.自 1.12 版本之后,Docker 引入了原生的健康检查实现. 如何给Docke配置原生健康检查 ...

  6. Inception网络模型

    最近在研究inception模型,将v1到v4版本的论文都研读了一下,这里做一下总结. 这里推荐一下这个GitHub,博主将常见的论文都做了翻译,大家可以参考中文来加深理解. 1.Inception ...

  7. 英国电信选择由 Canonical 开发的 Ubuntu OpenStack 作为云平台

    英国电信(简称 BT,British Telecom)宣布,选择由 Canonical 开发的 Ubuntu OpenStack 作为云平台,该平台将有助于支持引入 5G 和光纤到户的连接. 作为 U ...

  8. 基于Redis实现分布式锁(转载)

    原文地址:http://blog.csdn.net/ugg/article/details/41894947 Redis命令介绍使用Redis实现分布式锁,有两个重要函数需要介绍 SETNX命令(SE ...

  9. Class.forName()方法抛出异常

    在测试static块时间,想要调用Class.forName()来加载类,需要注意此方法要求必须要抛出异常,否则报错. 但在之后却一直抛出java.lang.ClassNotFoundExceptio ...

  10. 写一个基于TCP协议套接字,服务端实现接收客户端的连接并发

    ''' 写一个基于TCP协议套接字,服务端实现接收客户端的连接并发 ''' client import socket import time client = socket.socket() clie ...