(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
<div id="app">
<div v-for="(value, key, index) in age">
{{ index }}. {{ key }} : {{ value }}
</div>
</div>
第一個參數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
<div class="quentity">
<a href="javascript:;" v-on:click="changeMoney(product,-1)">-</a>
<input type="text" v-model="product.productQuentity" disabled>
<a href="javascript:;" v-on:click="changeMoney(product,1)">+</a>
</div>
----------------------------------
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 偵聽器。
購物車中的例子:

<div id="showOverLay" v-bind:class="{ 'md-overlay': showModal }"></div>
官網的例子:
<!-- 綁定一個屬性 -->

<!-- 縮寫 -->

<!-- 內聯字符串拼接 -->

<!-- class 綁定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 綁定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 綁定一個有屬性的對象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- 通過 prop 修飾符綁定 DOM 屬性 -->
<div v-bind:text-content.prop="text"></div>
<!-- prop 綁定。“prop”必須在 my-component 中聲明。-->
<my-component :prop="someThing"></my-component>
<!-- 通過 $props 將父組件的 props 一起傳給子組件 -->
<child-component v-bind="$props"></child-component>
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
.camel 修飾符允許在使用 DOM 模板時將 v-bind 屬性名稱駝峰化,例如 SVG 的 viewBox 屬性:
<svg :view-box.camel="viewBox"></svg>
(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: '<span>{{ message }}</span>',
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
<div class="item-price" >{{ product.productPrice | formatMoney('') }}</div>
<div class="item-price-total">
{{product.productPrice*product.productQuentity | formatMoney('元') }}
</div>
----------
輸出結果:¥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
<div class="cart-item-check">
<a href="javascipt:;" class="item-check-btn"
v-bind:class="{ 'check': product.checked }" //控制ui顯示隱藏的狀態
v-on:click="selectedProduct(product)" //單選功能函數
>
<svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
</a>
</div>
------------------------------------------
js
selectedProduct: function(product) {
if(typeof product.checked == 'undefined') {
Vue.set(product,'checked',true)
} else {
product.checked = !product.checked
}
this.calculateTotalMoney(); //計算總金額
}
(8)全選功能和全部刪除功能
html
<div class="cart-foot-l">
<div class="item-all-check">
<a href="javascipt:;" v-on:click="checkAll(true)">
<span class="item-check-btn" v-bind:class="{ 'check': checkedAll }">
<svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
</span>
<span>全選</span>
</a>
</div>
<div class="item-all-del">
<a href="javascipt:;" class="item-del-btn" v-on:click="checkAll(false)">
取消全選
</a>
</div>
</div>
----------------------------------------------
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。
例子:
<script type="text/javascript">
var str="Hello world!"
document.write(str.indexOf("Hello") + "<br />")
document.write(str.indexOf("World") + "<br />") //沒有出現 world+空格
document.write(str.indexOf("world"))
</script>
輸出結果:
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
<div class="md-modal modal-msg md-modal-transition"
id="showModal"
v-bind:class="{ 'md-show': showModal }"
>
<div class="md-modal-inner">
<div class="md-top">
<button class="md-close" v-on:click="showModal=false">關閉</button>
</div>
<div class="md-content">
<div class="confirm-tips">
<p id="cusLanInfo" lan="Cart.Del.Confirm">你確認刪除此訂單信息嗎?</p>
</div>
<div class="btn-wrap col-2">
<button class="btn btn--m" id="btnModalConfirm" v-on:click="delProduct()">Yes</button>
<button class="btn btn--m btn--red" id="btnModalCancel"v-on:click="showModal=false">No</button>
</div>
</div>
</div>
</div>
(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
<li v-for=" (item,index) in filteAddress ">
(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部分
<div class="shipping-addr-more" v-on:click="showAllAddresss()">
...
</div>
--------------------
也可以在click中直接寫表達式,如下面這樣:
<div class="shipping-addr-more" v-on:click="addressLength = addressList.length">
...
</div>
注意:在指令里面( v-xxx ),在視圖view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在視圖view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在視圖view中 ( html )中都不要使用this
(12) 點擊選中某一個卡片
<li v-for=" (item,index) in filteAddress "
v-bind:class="{ 'check' : index == currentCard }"
v-on:click=" currentCard = index"
>
解析:
當點擊某個卡片的時候,讓該卡片的 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部分
<div class="addr-opration addr-set-default"
v-if="!item.isDefault"
v-on:click="setDefaultAddress(item.addressId)"
>
<a href="javascript:;" class="addr-set-default-btn" ><i>設為默認</i></a>
</div>
<div class="addr-opration addr-default" v-if="item.isDefault">默認地址</div>
解析:
如果點擊的是第三個卡片,傳過來的卡片的id=3,
而在循環addressList中,假如正在循環的是第一個卡片,那么卡片id是1,
1 != 3,
所以執行:item.isDefault = false,所以第一個卡片不顯示(默認地址)
(13) 只切換兩張選項卡
<ul>
<li v-bind:class="{'check': switchPeisong == 1 }" v-on:click=" switchPeisong = 1">
<div class="name" >標準配送</div>
<div class="price">Free</div>
</li>
<li v-bind:class="{'check': switchPeisong == 2 }" v-on:click=" switchPeisong = 2">
<div class="name">高級配送</div>
<div class="price">180</div>
</li>
</ul>
購物車
購物車地址