日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

Vue.js 学习笔记 第5章 内置指令

發布時間:2025/7/14 vue 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Vue.js 学习笔记 第5章 内置指令 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

本篇目錄:

5.1 基本指令

5.2 條件渲染指令

5.3 列表渲染指令 v-for

5.4 方法與事件

5.5 實戰:利用計算屬性、指令等知識開發購物車

?

回顧一下第2.2節,我們己經介紹過指令(Directive)的概念了,Vue.js的指令是帶有特殊前綴v-的HTML特性,它綁定一個表達式,并將一些特性應用到DOM上。
其實我們已經用到過很多Vue內置的指令,比如v-html、v-pre,還有上一章的v-bind。
本章將繼續介紹Vue.js中更多常用的內置指令。

5.1 基本指令

5.1.1 v-cloak

v-cloak不需要表達式,它會在Vue實例結束編譯時從綁定的HTML元素上移除,經常和CSS的display:none;配合使用:

1 <div id="app" v-cloak> 2 {{message}} 3 </div> 4 5 <script> 6 var app = new Vue({ 7 el: "#app", 8 data: { 9 message: "這是一段文本" 10 } 11 }); 12 </script>

?

這時雖然已經加了指令v-cloak,但其實并沒有起到任何作用。
當網速較慢、Vue.js文件還沒加載完時,在頁面上會顯示{{message}}的字樣。
直到Vue創建實例、編譯模板時,DOM才會被替換,所以這個過程屏幕是有閃動的。
只要加一句CSS就可以解決這個問題了:

1 <style> 2 [v-cloak] { 3 display: none; 4 } 5 </style>

?

在一般情況下,v-cloak是一個解決初始化慢導致頁面閃動的最佳實踐,對于簡單的項目很實用,但是在具有工程化的項目里,比如后面進階篇將介紹webpack和vue-router時,項目的HTML結構只有一個空的div元素,剩余的內容都是由路由去掛載不同組件完成的,所以不再需要v-cloak。

5.1.2 v-once

v-once也是一個不需要表達式的指令,作用是定義它的元素或組件只渲染一次,包括元素或組件的所有子節點。
首次渲染后,不再隨數據的變化重新渲染,將被視為靜態內容,例如:

1 <div id="app"> 2 <span v-once>{{message}}</span> 3 <div v-once> 4 <span>{{message}}</span> 5 </div> 6 </div> 7 8 <script> 9 var app = new Vue({ 10 el: "#app", 11 data: { 12 message: "這是一段文本" 13 } 14 }); 15 </script>

?

v-once在業務中也很少使用,當你需要進一步優化性能時,可能會用到。

5.2 條件渲染指令

5.2.1 v-if、v-else-of、v-else

與JavaScript的條件語句if、else、else if類似,Vue.js的條件指令可以根據表達式的值在DOM中渲染或銷毀元素/組件。
例如:

1 <div id="app"> 2 <p v-if="status===1">當status為1時顯示此行</p> 3 <p v-else-if="status===2">當status為2時顯示此行</p> 4 <p v-else>否則顯示此行</p> 5 </div> 6 7 <script> 8 var app = new Vue({ 9 el: "#app", 10 data: { 11 status: 1 12 } 13 }); 14 </script>

?

v-else-if要緊跟v-if,v-else要緊跟v-else-if或v-if。
表達式的值為true時,當前元素/組件及所有子節點將被渲染,為false時被移除。
如果一次判斷的是多個元素,可以在Vue.js內置的<template>元素上使用條件指令,最終渲染的結果不包含鈣元素。
例如:

1 <div id="app"> 2 <template v-if="status===1"> 3 <p>這是一段文本</p> 4 <p>這是一段文本</p> 5 <p>這是一段文本</p> 6 </template> 7 </div> 8 9 <script> 10 var app = new Vue({ 11 el: "#app", 12 data: { 13 status: 1 14 } 15 }); 16 </script>

?

Vue在渲染元素時,出于效率考慮,會盡可能地復用已有的元素而非重新渲染。
比如下面的示例:

1 <div id="app"> 2 <template v-if="type==='name'"> 3 <label for="name">用戶名:</label> 4 <input type="text" id="name" name="name" placeholder="請輸入用戶名"> 5 </template> 6 <template v-else> 7 <label for="mail">郵箱:</label> 8 <input type="text" id="mail" name="mail" placeholder="請輸入郵箱"> 9 </template> 10 <button type="button" @click="handleToggleClick">切換輸入類型</button> 11 </div> 12 13 <script> 14 var app = new Vue({ 15 el: "#app", 16 data: { 17 type: "name" 18 }, 19 methods: { 20 handleToggleClick: function() { 21 this.type = this.type === "name" ? "mail" : "name"; 22 } 23 } 24 }); 25 </script>

?

如圖5-1和圖5-2所示,鍵入內容后,點擊切換按鈕,雖然DOM變了,但是之前在輸入框鍵入的內容并沒有改變,只是替換了placeholder的內容,說明<input>元素被復用了。

如果你不希望這樣做,可以使用Vue.js提供的key屬性,它可以讓你自己決定是否要復用元素,key的值必須是唯一的。
例如:

1 <div id="app"> 2 <template v-if="type==='name'"> 3 <label for="name">用戶名:</label> 4 <input type="text" id="name" name="name" key="name-input" placeholder="請輸入用戶名"> 5 </template> 6 <template v-else> 7 <label for="mail">郵箱:</label> 8 <input type="text" id="mail" name="mail" key="mail-input" placeholder="請輸入郵箱"> 9 </template> 10 <button type="button" @click="handleToggleClick">切換輸入類型</button> 11 </div> 12 13 <script> 14 var app = new Vue({ 15 el: "#app", 16 data: { 17 type: "name" 18 }, 19 methods: { 20 handleToggleClick: function() { 21 this.type = this.type === "name" ? "mail" : "name"; 22 } 23 } 24 }); 25 </script>

?

給兩個<input>元素都增加key后,就不會復用了,切換類型時鍵入的內容也會被刪除,不過<label>元素仍然是被復用的,因為沒有添加key屬性。

5.2.2 v-show

v-show的用法與v-if基本一致,只不過v-show是改變元素的CSS屬性display。
當v-show表達式的值為false時,元素會隱藏,查看DOM結構會看到元素上加載了內聯樣式display:none。
例如:

1 <div id="app"> 2 <p v-show="status===1">當status為1時顯示此行</p> 3 </div> 4 5 <script> 6 var app = new Vue({ 7 el: "#app", 8 data: { 9 status: 2 10 } 11 }); 12 </script>

?

渲染后的結果為:

1 <div id="app"> 2 <p style="display: none;">當status為1時顯示此行</p> 3 </div>

?

提示:
v-show不能在<template>上使用。

5.2.3 v-if與v-show的選擇

v-if和v-show具有類似的功能,不過v-if才是真正的條件渲染,它會根據表達式適當地銷毀或重建元素及綁定的事件或子組件。
若表達式初始值為false,則一開始元素/組件并不會渲染,只有當條件第一次變為true時才開始編譯。

而v-show只是簡單的CSS屬性切換,無論條件真與否,都會被編譯。
相比之下,v-if更適合條件不經常改變的場景,因為它切換開銷相對較大,而v-show適用于頻繁切換條件。

5.3 列表渲染指令 v-for

5.3.1 基本用法

當需要將一個數組遍歷或枚舉一個對象循環顯示時,就會用到列表渲染指令v-for。
它的表達式需結合in來使用,類似item in items的形式。
看下面的代碼:

1 <div id="app"> 2 <ul> 3 <li v-for="book in books">{{book.name}}</li> 4 </ul> 5 </div> 6 7 <script> 8 var app = new Vue({ 9 el: "#app", 10 data: { 11 books: [ 12 { name: "《Vue.js實戰》" }, 13 { name: "《JavaScript語言精粹》" }, 14 { name: "《JavaScript高級程序設計》" } 15 ] 16 } 17 }); 18 </script>

?

我們定義一個數組類型的數據books,用v-for將<li>標簽循環渲染。
效果如圖5-3所示:

在表達式中,books是數據,book是當前數組元素的別名,循環出的每個<li>內的元素都可以訪問到對應的當前數據book。
列表渲染也支持用of來代替in作為分隔符,它更接近JavaScript迭代器的語法:

1 <li v-for="book of books">{{book.name}}</li>

?

v-for的表達式支持一個可選參數作為當前項的索引,例如:

1 <div id="app"> 2 <ul> 3 <li v-for="(book, index) in books">{{index}} - {{book.name}}</li> 4 </ul> 5 </div> 6 7 <script> 8 var app = new Vue({ 9 el: "#app", 10 data: { 11 books: [ 12 { name: "《Vue.js實戰》" }, 13 { name: "《JavaScript語言精粹》" }, 14 { name: "《JavaScript高級程序設計》" } 15 ] 16 } 17 }); 18 </script>

?

分隔符in前的語句使用括號,第二項就是books當前項的索引。
渲染后的結果如圖5-4所示:

提示:
如果你使用過Vue.js 1.x的版本,這里的index也可以由內置的$index代替,不過在2.x里取消了該用法。

與v-if一樣,v-for也可以用在內置標簽<template>上,將多個元素進行渲染:

1 <div id="app"> 2 <ul> 3 <template v-for="book in books"> 4 <li>書名:{{book.name}}</li> 5 <li>作者:{{book.author}}</li> 6 </template> 7 </ul> 8 </div> 9 10 <script> 11 var app = new Vue({ 12 el: "#app", 13 data: { 14 books: [ 15 { name: "《Vue.js實戰》", author:"梁灝" }, 16 { name: "《JavaScript語言精粹》", author:"Douglas Crockford" }, 17 { name: "《JavaScript高級程序設計》", author:"Nicholas C.Zakas" } 18 ] 19 } 20 }); 21 </script>

?

除了數組外,對象的屬性也是可以遍歷的。
例如:

1 <div id="app"> 2 <span v-for="value in user">{{value}}</span> 3 </div> 4 5 <script> 6 var app = new Vue({ 7 el: "#app", 8 data: { 9 user: { 10 name: "Aresn", 11 gender: "", 12 age: 26 13 } 14 } 15 }); 16 </script>

?

渲染后的結果為:

1 <div id="app"> 2 <span>Aresn</span> 3 <span></span> 4 <span>26</span> 5 </div>

?

遍歷對象屬性時,有兩個可選參數,分別是鍵名和索引:

1 <div id="app"> 2 <ul> 3 <li v-for="(value, key, index) in user"> 4 {{index}} - {{key}} - {{value}} 5 </li> 6 </ul> 7 </div> 8 9 <script> 10 var app = new Vue({ 11 el: "#app", 12 data: { 13 user: { 14 name: "Aresn", 15 gender: "", 16 age: 26 17 } 18 } 19 }); 20 </script>

?

渲染后的結果如圖5-5所示:

v-for還可以迭代整數:

1 <div id="app"> 2 <span v-for="n in 10">{{n}} </span> 3 </div> 4 5 <script> 6 var app = new Vue({ 7 el: "#app" 8 }); 9 </script>

?

渲染后的結果為:

1 <div id="app"> 2 <span>1 </span> 3 <span>2 </span> 4 <span>3 </span> 5 <span>4 </span> 6 <span>5 </span> 7 <span>6 </span> 8 <span>7 </span> 9 <span>8 </span> 10 <span>9 </span> 11 <span>10 </span> 12 </div>

?

5.3.2 數組更新

Vue的核心是數據與視圖的雙向綁定,當我們修改數組時,Vue會檢測到數據變化,所以用v-for渲染的視圖也會立即更新。
Vue包含了一組觀察數組變異的方法,使用它們改變數組也會觸發視圖更新:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

例如,我們將之前一個示例的數據books添加一項:

1 app.books.push({ 2 name: "《CSS解密》", 3 author: "[希] Lea Verou" 4 });

?

可以嘗試編寫完整示例來查看效果。
使用以上方法會改變被這些方法調用的原始數組,有些方法不會改變原數組,例如:

  • filter()
  • concat()
  • slice()

它們返回的是一個新數組,在使用這些非變異方法時,可以用新數組來替換原數組。
還是之前展示節目的示例,我們找出含有JavaScript關鍵詞的書目,例如:

1 <div id="app"> 2 <ul> 3 <template v-for="book in books"> 4 <li>書名:{{book.name}}</li> 5 <li>作者:{{book.author}}</li> 6 </template> 7 </ul> 8 </div> 9 10 <script> 11 var app = new Vue({ 12 el: "#app", 13 data: { 14 books: [ 15 { name: "《Vue.js實戰》", author:"梁灝" }, 16 { name: "《JavaScript語言精粹》", author:"Douglas Crockford" }, 17 { name: "《JavaScript高級程序設計》", author:"Nicholas C.Zakas" } 18 ], 19 } 20 }); 21 22 app.books = app.books.filter(function(item) { 23 return item.name.match(/JavaScript/); 24 }); 25 </script>

?

渲染的結果中,第一項《Vue.js實戰》被過濾掉了,只顯示了書名中含有JavaScript的選項。

Vue在檢測到數組變化時,并不是直接重新渲染整個列表,而是最大化地復用DOM元素。
替換的數組中,含有相同元素的項不會被重新渲染,因此可以大膽地用新數組來替換就數組,不用擔心性能問題。

需要注意的是,以下變動的數組中,Vue是不能檢測到的,也不會觸發視圖更新:

  • 通過索引直接設置項,比如app.book[3] = {...}
  • 修改數組長度,比如app.books.length=1

解決第一個問題可以用兩種方法實現同樣的效果,第一種是使用Vue內置的set方法:

1 Vue.set(app.books, 2, { 2 name: "《CSS揭秘》", 3 author: "[希] Lea Verou" 4 });

?

如果是在webpack中使用組件化的方式(進階篇中將介紹),默認是沒有導入Vue的,這時可以使用$set。
例如:

1 this.$set(app.books, 2, { 2 name: "《CSS揭秘》", 3 author: "[希] Lea Verou" 4 });

?

這里的this指向的就是當前組件的實例,即app。
在非webpack模式下也可以用$set方法,例如app.$set(...)。

另一種方法:

1 app.books.splice(2, 1, { 2 name: "《CSS揭秘》", 3 author: "[希] Lea Verou" 4 });

?

第二個問題也可以直接用splice來解決:

1 app.books.splice(1);

?

5.3.3 過濾與排序

當你不想改變原數組,想通過一個數組的副本來做過濾或排序的顯示時,可以使用計算屬性來返回過濾或排序后的數組。
例如:

1 <div id="app"> 2 <ul> 3 <template v-for="book in filterBooks"> 4 <li>書名:{{book.name}}</li> 5 <li>作者:{{book.author}}</li> 6 </template> 7 </ul> 8 </div> 9 10 <script> 11 var app = new Vue({ 12 el: "#app", 13 data: { 14 books: [ 15 { name: "《Vue.js實戰》", author:"梁灝" }, 16 { name: "《JavaScript語言精粹》", author:"Douglas Crockford" }, 17 { name: "《JavaScript高級程序設計》", author:"Nicholas C.Zakas" } 18 ], 19 }, 20 computed: { 21 filterBooks: function () { 22 return this.books.filter(function (book) { 23 return book.name.match(/JavaScript/); 24 }); 25 } 26 } 27 }); 28 </script>

?

上例是把書名中包含"JavaScript"關鍵詞的數據過濾出來,計算屬性filterBooks依賴books,但是不會修改books。
實現排序也是類似的,比如在此基礎上新加一個計算屬性sortedBooks,按照書名的長度由長到短進行排序:

1 computed: { 2 sortedBooks: function () { 3 return this.books.sort(function (a, b) { 4 return a.name.length < b.name.length; 5 }); 6 } 7 }

?

提示:
在Vue.js 2.x中廢棄了1.x中內置的limitBy、filterBy和orderBy過濾器,統一改用計算屬性來實現。

5.4 方法與事件

5.4.1 基本用法

在第2.2節,我們已經引入了Vue事件處理的概念v-on。
在事件綁定上,類似原生JavaScript的onclick等寫法,也是在HTML上進行監昕的。
例如,我們監昕一個按鈕的點擊事件,設置一個計數器,每次點擊都加1:

1 <div id="app"> 2 點擊次數: {{counter}} 3 <button type="button" @click="counter++">累加1</button> 4 </div> 5 6 <script> 7 var app = new Vue({ 8 el: "#app", 9 data: { 10 counter: 0 11 } 12 }); 13 </script>

?

提示:
上面的@click等同于v-on:click,是一個語法糖,如不特殊說明,后面都將使用語法糖寫法,可以回顧第2.3章節。

@click的表達式可以直接使用JavaScript語句,也可以是一個在Vue實例中methods選項內的函數名。
比如對上例進行擴展,再增加一個按鈕,點擊一次,計數器累加10:

1 <div id="app"> 2 點擊次數: {{counter}} 3 <button type="button" @click="handleAdd()">累加1</button> 4 <button type="button" @click="handleAdd(10)">累加10</button> 5 </div> 6 7 <script> 8 var app = new Vue({ 9 el: "#app", 10 data: { 11 counter: 0 12 }, 13 methods: { 14 handleAdd: function(count) { 15 count = count || 1; 16 // this指向當前Vue實例app 17 this.counter += count; 18 } 19 } 20 }); 21 </script>

?

在methods中定義了我們需要的方法供@click調用,需要注意的是,@click調用的方法名后可以不跟括號()。
此時,如果該方法有參數,默認會將原生事件對象event傳入,可以嘗試修改為@click="handleAdd",然后在handleAdd內打印出count參數看看。
在大部分業務場景中,如果方法不需要傳入參數,為了漸變可以不寫括號。

這種在HTML元素上監聽事件的設計看似將DOM與JavaScript緊耦合,違背分離的原理,實則剛好相反。
因為通過HTML就可以知道調用的是哪個方法,講邏輯與DOM接口,便于維護。
最重要的是,當ViewModel銷毀時,所有的事件處理器都會自動刪除,無需自己清理。

Vue提供了一個特殊變量$event,用于訪問原生DOM事件,例如下面的實例可以阻止連接打開:

1 <div id="app"> 2 <a href="http://www.baidu.com" @click="handleClick('禁止打開', $event)">打開連接</a> 3 </div> 4 5 <script> 6 var app = new Vue({ 7 el: "#app", 8 methods: { 9 handleClick: function(message, event) { 10 event.preventDefault(); 11 alert(message); 12 } 13 } 14 }); 15 </script>

?

5.4.2 修飾符

在上例使用的event.preventDefault()也可以用Vue事件的修飾符來實現。
在@綁定的事件后加小圓點.,在跟一個后綴來使用修飾符。
Vue支持以下修飾符:

  • .stop
  • .prevent
  • .capture
  • .self
  • .once

具體用法如下:

1 <!-- 阻止事件冒泡 --> 2 <a @click.stop="handle"></a> 3 4 <!-- 提交事件不再重載頁面 --> 5 <form @submit.prevent="handle"></form> 6 7 <!-- 修飾符可以串聯 --> 8 <a @click.stop.prevent="handle"></a> 9 10 <!-- 只有修飾符 --> 11 <form @submit.prevent></form> 12 13 <!-- 添加事件偵聽器時使用事件捕獲模式 --> 14 <div @click.capture="handle">...</div> 15 16 <!-- 只當事件在該元素本身(而不是子元素)觸發時觸發回調 --> 17 <div @click.self="handle">...</div> 18 19 <!-- 只觸發一次,組件同樣適用 --> 20 <div @click.once="handle">...</div>

?

在表單元素上監聽鍵盤事件時,還可以使用按鍵修飾符。
比如按下具體某個鍵時才調用方法:

1 <!-- 只有在keyCode是13時調用 vm.submit() --> 2 <input @keyup.13="submit">

?

也可以自己配置具體按鍵:

1 Vue.config.keyCodes.f1 = 112; 2 // 全局定義后,就可以使用@keyup.f1

?

除了具體的某個keyCode外,Vue還提供了一些快捷名稱。
以下是全部的別名:

  • .enter
  • .tab
  • .delete(捕獲"刪除"和"退格"鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

這些按鍵修飾符也可以組合使用,或和鼠標一起使用:

  • .ctrl
  • .alt
  • .shift
  • .meta(Mac下是Command鍵,Windows下是窗口鍵)

例如:

1 <!-- Shift + S --> 2 <input @keyup.shift.83="handleSave"> 3 4 <!-- Ctrl + Click --> 5 <div @click.ctrl="doSomething">Do Smothing</div>

?

以上就是事件指令v-on的基本內容,在第7章的組件中,我們還將介紹用v-on來綁定自定義事件。

5.5 實戰:利用計算屬性、指令等知識開發購物車

前五章內容基本涵蓋了Vue.js最核心的常用的知識點,掌握這些內容已經可以上手開發一些小功能了。
本節則以Vue.js的計算屬性、內置指令、方法等內容為基礎,完成一個在業務中具有代表性的小功能:購物車。

在開始寫代碼前,要對需求進行分析,這樣有助于我們理清業務邏輯,盡可能還原設計產品交互。

購物車需要展示一個已加入購物車的商品列表,包含商品名稱、商品單價、購買數量和操作等信息,還需要實時顯示購買的總價。
其中購買數量可以增加或減少,每類商品還可以從購物車中移除。
最終實現的效果如圖5-6所示:

在明確需求后,我們就可以開始編程了。
因為業務代碼較多,這次我們將HTML、CSS、JavaScript分離為3個文件,便于閱讀和維護:

  • index.html (引入資源及模板)
  • index.js (Vue實例及業務代碼)
  • index.css (樣式)

現在index.html中引入Vue.js和相關資源,創建一個根元素來掛在Vue實例:

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>購物車示例</title> 8 <link rel="stylesheet" href="index.css"> 9 </head> 10 <body> 11 <div id="app" v-cloak></div> 12 13 <script src="https://unpkg.com/vue/dist/vue.min.js"></script> 14 <script src="index.js"></script> 15 </body> 16 </html>

?

注意,這里將vue.min.js和index.js文件寫在<body>的最底部,如果寫在<head>里,Vue實例將無法創建,因為此時DOM還沒有被解析完成,除非通過異步或在事件DOMContentLoaded(IE是onreadystatechange)觸發時再創建Vue實例,這有點像jQuery的$(document).ready()方法。

本例需要用到Vue.js的computed、methods等選項,在index.js中縣初始化實例:

1 var app = new Vue({ 2 el: "#app", 3 data: {}, 4 computed: {}, 5 methods: {} 6 });

?

我們需要的數據比較簡單,只有一個列表,里面包含了商品名稱、單價、購買數量。
在實際業務中,這個列表應該是通過Ajax從服務端動態獲取的,這里只做示例,所以直接寫入在data選項內,另外每個商品還應該有一個全局唯一的id。
我們在data內寫入列表list:

1 data: { 2 list: [ 3 {id: 1, name: "iPhone 7", price: 6188, count: 1}, 4 {id: 2, name: "iPad Pro", price: 5888, count: 1}, 5 {id: 3, name: "McaBook Pro", price: 21488, count: 1} 6 ] 7 }

?

數據構建好后,可以在index.html中展示列表了,毫無疑問,肯定會用到v-for,不過在此之前,我們先做一些小的優化。
因為每個商品都是可以從購物車移除的,所以當列表為空時,在頁面中顯示一個”購物車為空“的提示更為友好,我們可以通過判斷數組list的長度來實現該功能:

1 <div id="app" v-cloak> 2 <template v-if="list.length"></template> 3 <div v-else>購物車為空</div> 4 </div>

?

<template>里的代碼分兩部分,一部分是商品列表信息,我們用表格<table>來展現;
另一部分就是帶有千位分隔符的商品總價(每隔三位數加一個逗號)。
這部分代碼如下:

1 <template v-if="list.length"> 2 <table> 3 <thead> 4 <tr> 5 <th></th> 6 <th>商品名稱</th> 7 <th>商品單價</th> 8 <th>購買數量</th> 9 <th>操作</th> 10 </tr> 11 </thead> 12 <tbody> 13 </tbody> 14 </table> 15 <div>總價:¥ {{totalPrice}}</div> 16 </template>

?

總價totalPrice是依賴于商品列表而動態變化的,所以我們用計算屬性來實現,順便將結果轉換為帶有"千位分隔符"的數字。
在index.js的computed選項內寫入:

1 computed: { 2 totalPrice: function () { 3 var total = 0; 4 for (var i = 0; i < this.list.length; i++) { 5 var item = this.list[i]; 6 total += item.price * item.count; 7 } 8 return total.toString().replace(/\B(?=(\d{3})+$)/g, ","); 9 } 10 }

?

這段代碼難點在于千位分隔符的轉換,大家可以查閱正則匹配的相關內容后嘗試了解replace()的正則含義。

最后就剩下商品列表的渲染和相關的幾個操作了。
現在<body>內把數組list用v-for指令循環出來:

1 <tbody> 2 <tr v-for="(item, index) in list"> 3 <td>{{index + 1}}</td> 4 <td>{{item.name}}</td> 5 <td>{{item.price}}</td> 6 <td> 7 <button @click="handleReduce(index)" :disabled="item.count===1">-</button> 8 {{item.count}} 9 <button @click="handleAdd(index)">+</button> 10 </td> 11 <td> 12 <button @click="handleRemove(index)">移除</button> 13 </td> 14 </tr> 15 </tbody>

?

商品序號、名稱、單價、數量都是直接使用插值來完成的,在第4列的兩個按鈕<button>用于增/減購買數量,分別綁定了兩個方法handleReduce和handleAdd,參數都是當前商品在數組list中的索引。
很多時候,一個元素上會同時使用多個特性(尤其是在組件中使用props傳遞數據時),寫在一行代碼較長,不便閱讀,所以建議特性過多時,將每個特性都單獨寫為一行,比如第一個<button>中使用了v-bind和v-on兩個指令(這里都用的語法糖寫法)。
每件商品購買數量最少是1件,所以當count為1時,不允許再繼續減少,所以這里給<button>動態綁定了disabled特性來禁用按鈕。

在index.js中繼續完成剩余的3個方法:

1 methods: { 2 handleReduce: function (index) { 3 if (this.list[index].count === 1) return; 4 this.list[index].count--; 5 }, 6 handleAdd: function (index) { 7 this.list[index].count++; 8 }, 9 handleRemove: function (index) { 10 this.list.splice(index, 1); 11 } 12 }

?

這3個方法都是直接對數組list的操作,沒有太復雜的邏輯。
需要說明的是,雖然在<button>上已經綁定了disabled特性,但是在handleReduce方法內有判斷了以便,這是因為在某些時刻,可能不一定會用<button>元素,也可能是div、span等,給它們增加disabled是沒有任何作用的,所以安全起見,在業務邏輯中在判斷一次,避免因修改HTML模板后出現bug。

一下是購物車示例的完整代碼:
index.html:

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>購物車示例</title> 8 <link rel="stylesheet" href="index.css"> 9 </head> 10 <body> 11 <div id="app" v-cloak> 12 <template v-if="list.length"> 13 <table> 14 <thead> 15 <tr> 16 <th></th> 17 <th>商品名稱</th> 18 <th>商品單價</th> 19 <th>購買數量</th> 20 <th>操作</th> 21 </tr> 22 </thead> 23 <tbody> 24 <tr v-for="(item, index) in list"> 25 <td>{{index + 1}}</td> 26 <td>{{item.name}}</td> 27 <td>{{item.price}}</td> 28 <td> 29 <button @click="handleReduce(index)" :disabled="item.count===1">-</button> 30 {{item.count}} 31 <button @click="handleAdd(index)">+</button> 32 </td> 33 <td> 34 <button @click="handleRemove(index)">移除</button> 35 </td> 36 </tr> 37 </tbody> 38 </table> 39 <div>總價:¥ {{totalPrice}}</div> 40 </template> 41 <div v-else>購物車為空</div> 42 </div> 43 44 <script src="https://unpkg.com/vue/dist/vue.min.js"></script> 45 <script src="index.js"></script> 46 </body> 47 </html>

?

index.js:

1 var app = new Vue({ 2 el: "#app", 3 data: { 4 list: [ 5 {id: 1, name: "iPhone 7", price: 6188, count: 1}, 6 {id: 2, name: "iPad Pro", price: 5888, count: 1}, 7 {id: 3, name: "McaBook Pro", price: 21488, count: 1} 8 ] 9 }, 10 computed: { 11 totalPrice: function () { 12 var total = 0; 13 for (var i = 0; i < this.list.length; i++) { 14 var item = this.list[i]; 15 total += item.price * item.count; 16 } 17 return total.toString().replace(/\B(?=(\d{3})+$)/g, ","); 18 } 19 }, 20 methods: { 21 handleReduce: function (index) { 22 if (this.list[index].count === 1) return; 23 this.list[index].count--; 24 }, 25 handleAdd: function (index) { 26 this.list[index].count++; 27 }, 28 handleRemove: function (index) { 29 this.list.splice(index, 1); 30 } 31 } 32 });

?

index.css:

1 [v-cloak]{display:none;} 2 table{border:1px solid #E9E9E9; border-collapse:collapse; border-spacing:0; empty-cells:show;} 3 th, td{padding:8px 16px; border:1px solid #E9E9E9; text-align:left;} 4 th{background:#F7F7F7; color:#5C6B77; font-weight:600; white-space:nowrap;}

?

練習1:在當前示例基礎上擴展商品列表,新增一項是否選中該商品的功能,總價變為只計算選中商品的總價,同時提供一個全選的按鈕。
練習2:將商品列表list改為一個二維數組來實現商品的分類,比如可分為"電子產品"、"生活用品"和"果蔬",同類商品聚合在一起。提示,你可能會用到兩次v-for。

?

轉載于:https://www.cnblogs.com/geeksss/p/10776465.html

總結

以上是生活随笔為你收集整理的Vue.js 学习笔记 第5章 内置指令的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。