(1) 构建VUE实例
cart.js
--------
var vm = new Vue({ //实例对象,注意Vue首字母要大写。一般用vm (ViewModel 的简称) 这个变量名表示 Vue 实例
el:"#app", //dom挂载点
data: { }, //data对象中放初始化的数据,相当于react中的state中的数据
filters:{ }, //局部过滤器
mounted: function() { } //钩子函数,相当于react中的componentDidMount,数据渲染完成时,将做的事情
methods: { }, //方法函数
})
(2) v-for指令
v-for
-------
语法:(item, index) in items //这里的in也可以写成of 即( item of items )
item:item是数组元素迭代的别名。
index: index是数组元素的索引值。
items:items 是源数据数组
v-for 对象迭代
-------
你也可以用 v-for 通过一个对象的属性来迭代
html
{{ index }}. {{ key }} : {{ value }}
第一个参数value:键值
第二个参数key:键名
第三个参数index:索引
以上的输出结果为:
0. firstName : John
1. lastName : Doe
2. ages : 30
---------------------------------------------------------
js
var vm = new Vue({
el:'#app',
data:{
age:{
firstName: 'John',
lastName: 'Doe',
ages: 30
}
},
});
(3) 用axios.get() 发送get请求
var vm = new Vue({
el:'#app',
data:{
porductList: []
},
filters: {
},
mounted: function() {
this.cartView();
},
methods: {
cartView: function() {
axios.get('data/cartData.json')
// .get('http://api.tianapi.com/meinv/?key=510b4ed16cb0b11b6ccfb7f3236fa8a6&num=10')
.then( response => {
// console.log(response);
this.porductList = response.data.result.list;
// console.log(this.porductList)
})
.catch( err => { console.log(err) })
}
}
});
(4)点击+-号实现购买数量的+-,input输入框的数据双向绑定
html
----------------------------------
js
changeMoney: function(product,choose) {
if( choose == 1){
product.productQuentity++;
}else if( choose == -1){
product.productQuentity--;
if(product.productQuentity < 1) {
product.productQuentity = 1;
}
}
}
(5) v-bind指令
( prop: 给img绑定src属性,给元素绑定class,style属性等 )
.prop - 被用于绑定 DOM 属性。(what’s the difference?)
.camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase. (从 2.1.0 开始支持)
.sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
购物车中的例子:
![](product.productImage)
官网的例子:
![](imageSrc)
![](imageSrc)
![]('/path/to/images/' + fileName)
.camel 修饰符允许在使用 DOM 模板时将 v-bind 属性名称驼峰化,例如 SVG 的 viewBox 属性:
(6)mounted钩子函和this.$nextTick(vue.nextTick)的关系
- 当数据修改之后,DOM没有立即更新,这个之后执行函数将是异步的,所以要想在DOM更新后立即执行函数的话,需要用到Vue.nextTick(),在组件内部一般使用this.$nextTick()
mounted: function() {
this.$nextTick(function() {
// 代码保证 this.$el 在 document 中
// this.cartView();
vm.cartView();
});
}
使用 mounted 并不能保证钩子函数中的 this.$el 在 document 中。
为此还应该引入 Vue.nextTick/vm.$nextTick
Vue.nextTick( [callback, context] )
作用:在下次 DOM 更新循环结束之后执行延迟回调。
用法:在修改数据之后立即使用这个方法,获取更新后的 DOM。
// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
// DOM 更新了
})
---------------------------------------------
在组件内部一般使用this.$nextTick()
Vue.component('example', {
template: '{{ message }}',
data: function () {
return {
message: '没有更新'
}
},
methods: {
updateMessage: function () {
this.message = '更新完成'
console.log(this.$el.textContent) // => '没有更新'
this.$nextTick(function () {
console.log(this.$el.textContent) // => '更新完成'
})
}
}
})
(6) 用filter过滤器对金额做(单位,小数)等处理
- 全局过滤器vue.filter():所有页面都能使用
- 局部过滤器filters: { } :只能在当前实例使用
局部过滤器:
js
filters: {
formatMoney: function(value, params) { //value是默认参数,params是需要传入的参数
return "¥" + value.toFixed(2) + params;
}
}
------------------------------
html
{{ product.productPrice | formatMoney('') }}
{{product.productPrice*product.productQuentity | formatMoney('元') }}
----------
输出结果:¥xx.00
输出结果:¥xx.00元
全局过滤器:
Vue.filter( id, [definition] )
--------------------------------------
参数:
- {string} id
- {Function} [definition]
--------------------------------------
用法:
// 注册
Vue.filter('my-filter', function (value) {
// 返回处理后的值
})
// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')
-------------------------------------------
例子:
Vue.filter('formatMoney', function(value,type) {
return "¥ "+value.toFixed(2) + type;
} )
(7)单选功能
- 注意:因为单选是在循环列表中,所以不能直接在data里面加状态变量,需要在data中的productList数组中添加checked状态变量
html
------------------------------------------
js
selectedProduct: function(product) {
if(typeof product.checked == 'undefined') {
Vue.set(product,'checked',true)
} else {
product.checked = !product.checked
}
this.calculateTotalMoney(); //计算总金额
}
(8)全选功能和全部删除功能
html
----------------------------------------------
js
data:{
productList: [],
showModal: false,
checkedAll: false, //循环列表中的class状态不能在data中定义,因为是个循环
totalMoneys:10
},
checkAll: function(bool) {
this.checkedAll = bool;
this.productList.forEach( ( porduct,index ) => {
if(typeof porduct.checked == 'undefined'){
Vue.set(porduct,'checked',this.checkedAll)
}else{
porduct.checked = this.checkedAll;
}
});
this.calculateTotalMoney();
},
calculateTotalMoney:function() {
this.totalMoneys = 0 ; //必须先清零,防止重复点击的情况
this.productList.forEach( (item,index) => {
if(item.checked){ //这里必须筛选出选中状态,切记记记记记记记记记记记
this.totalMoneys += item.productPrice * item.productQuentity;
}
} )
}
(9)删除功能
- (1) indexOf()
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
stringObject.indexOf(searchvalue,fromindex)
- searchvalue:必需。规定需检索的字符串值。
- fromindex:可选的整数参数。规定在字符串中开始检索的位置。
它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。
注释:indexOf() 方法对大小写敏感!
注释:如果要检索的字符串值没有出现,则该方法返回 -1。
例子:
输出结果:
0
-1
6
- (2) splice()
splice():
arrayObject.splice(index,howmany,item1,.....,itemX)
- index :必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
- howmany:必需。要删除的项目数量。如果设置为 0,则不会删除项目。
- item1, ..., itemX:可选。向数组添加的新项目
购物车删除案列:
js部分
delateConfirm: function(product) {
this.showModal = true;
this.currentItem = product;
},
delProduct: function() {
this.showModal = false;
var index = this.productList.indexOf(this.currentItem);
//在productList中检索this.currentItem第一次出现的位置
this.productList.splice(index,1); //删除的位置是index,数量是1,返回被删除的项目
this.calculateTotalMoney(); //删除后,重新计算总价格
}
-------------------
html
你确认删除此订单信息吗?
(10) v-for循环列表的item数量控制
( computed计算属性 ) ( slice分割数组 )
- slice() 方法可从已有的数组中返回选定的元素。
arrayObject.slice(start,end) //分割数组,对比: ( splice() 删除数组 )
返回值
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
说明
请注意,该方法并不会修改数组,而是返回一个子数组。
如果想删除数组中的一段元素,应该使用方法 Array.splice()。
(1) start:必需。
规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。
也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
(2) end:可选。
规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,
那么切分的数组包含从 start 到数组结束的所有元素。
如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
下面是购物车选址实例:
js
computed: {
filteAddress:function (){
return this.addressList.slice(0,3) }
},
//addressList是请求的json数据,存放在data中
//这里需要注意:
// slice() 返回的是全新的数组,不会破坏原数组addressList。
// splice() 会对addressList直接进行删除操作。
--------------------------------------
html
(11) 点击more加载所有的地址列表
js部分
var vm = new Vue({
el:".container",
data: {
addressList: [],
addressLength:3
},
computed: {
filteAddress:function (){
return this.addressList.slice(0,this.addressLength)
}
},
methods: {
showAllAddresss: function() {
// return this.addressList; 这里不能直接返回addressList,因为循环的是filteAddress
this.addressLength = this.addressList.length; //改变data从而改变computed
}
}
});
----------------------------------------------------
html部分
...
--------------------
也可以在click中直接写表达式,如下面这样:
...
注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this
(12) 点击选中某一个卡片
解析:
当点击某个卡片的时候,让该卡片的 index 赋值给currentCard 变量,
而当index==currentCard ,就出现check的ui状态
(12) 设为默认卡片
js部分:
setDefaultAddress: function(addressId) {
this.addressList.forEach( (item,index) => {
if( item.addressId == addressId ){
item.isDefault = true
}else{
item.isDefault = false
}
})
}
-----------------------------------------------
html部分
默认地址
解析:
如果点击的是第三个卡片,传过来的卡片的id=3,
而在循环addressList中,假如正在循环的是第一个卡片,那么卡片id是1,
1 != 3,
所以执行:item.isDefault = false,所以第一个卡片不显示(默认地址)
(13) 只切换两张选项卡
-
标准配送
Free
-
高级配送
180