用Vue寫購物車後,對this的理解
阿新 • • 發佈:2019-01-26
最近在學習vue,其中對購物車的編寫有點感悟。先來看看簡單的業務程式碼
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <title></title> <style> h1 p { display: inline-block; font: 16px normal; } h1 p span { background: #eee; border-radius: 50%; } </style> <script type="text/javascript" src="vue.js"></script> </head> <body> <div id="myShoppingCart"> <h1>{{name}}的購物車 <p>清單總數<span>{{items.length}}</span></p> <p>未採購數<span>{{count}}</span></p> </h1> <div> <!--雙向繫結資料,對應data下的text--> <input type="text" v-model="text"> <!-- //新增操作 --> <button v-on:click="addList(text)">新增</button> </div> <table> <thead> <tr> <th>清單名稱</th> <th>已採購</th> <th>狀態</th> <th>刪除</th> </tr> </thead> <tbody> <!-- 遍歷items,讓其所有分別在td展示出來 --> <tr v-for="(item, index) in items"> <!--展示清單名稱,對應items下的action--> <td>{{item.action}}</td> <!--用checkbox顯示是否選中,邏輯對應items下的state(v-model),另外需要進行對count進行繫結,選中的未採購數相應變化(減少)--> <td ><input type="checkbox" v-model="item.state" v-on:click="myCount()"></td> <!--設定狀態,對應items.stated的值,可以再進行完善,如顯示為,'已新增'--> <td>{{item.state}}</td> <!--需要進行相應的採草--> <td><button v-on:click="del(index)">刪除</button></td> </tr> </tbody> </table> </div> <script> /* Vue.component('todo-item',{ props: ['todo'], template: '<li>{{todo.text}}</li>' })*/ //新建new Vue var app = new Vue({ //繫結#myShoppingCart el: '#myShoppingCart', //資料邏輯,購物車的對應操作都是通過data的資料操作進行 data: { //對應23行的{{name}} name: 'Desmond', //購物車的狀態,清單資料 items: [ { action: 'iPhone7', state: false }, { action: 'iPhone7 Plus', state: false }, { action: 'Samsung Note9', state: false }, { action: '一加6', state: false } ], //對應28行input的資料,v-model進行雙向繫結 text: '', //對應未採購數 count: 0 }, //生命週期特點,可以簡單理解為“頁面載入完後”。這裡‘當頁面載入完’後,進行計數統計 mounted: function() { this.myCount() }, methods: { //新增方法,傳input.value進去,因為雙向綁定了,即為text addList: function(text) { //當為空值時,不進行任何操作 if(this.text == '') return; //只進行資料操作,將資料新增進data內 this.items.push({action: text, state: true}); //每次執行完後,需要對input清空 this.text = ''; //並對count進行操作,當TRUE不變化,false時則+1 this.myCount(); }, myCount: function(){ var _this = this; _this.count = 0; //對當前所有items進行遍歷 this.items.forEach(function(el, index){ if(!el.state) _this.count++ }) }, del: function(index){ //僅進行資料操作,刪除當前的資料 this.items.splice(index,1) } } }) </script> </body> </html>
這裡我在程式碼已經進行基本的解釋。主要說說爬的坑,this的指向。
相信大部分的同學都瞭解過this指向的是new Vue這個物件,那麼我這裡就是指向app了。
這樣說起來,這是什麼鬼?指向app了?那麼像addList,myCount,del方法(函式)究竟是怎麼操作的呢?
就上面的addList的this.text為例子,這裡的this確實是app(#myShoppingCart)。因為 text 用v-model雙向繫結,而我們的this.text == '';能夠起到效果就是最好的證明.
正當我也是這麼認為的時候,大坑就來了。沒錯,myCount方法這樣寫的時候,未採購數 沒有任何變化。有興趣的同學可以將112~119行程式碼換成以下程式碼進行驗證。
myCount: function(){
this.count = 0;
//對當前所有items進行遍歷
this.items.forEach(function(el, index){
if(!el.state) this.count++
})
},
經過對比兩次程式碼是因為用了_this = this,那麼為什麼要這樣做呢?為什麼就是myCount方法這樣用,其他方法不這樣用。一開始我也實在爬不出這坑(原諒我是菜鳥,而且又不報錯,這就千言萬語說不出來了),還好就只有那麼幾句程式碼,聚句百度、Google,終於找到了forEach
forEach
迴圈體是以一個函式體的形式去迴圈的,this是會改變的’。根據前半句,我就完全懵逼了,但是,我知道是this指向發生了改變,那麼只要將之前的this儲存起來不就好了。所以就有了_this = this。
同時,這個forEach浪費了我那麼多時間,我也為了避免再次掉坑,就專門回去看一遍forEach的用法,然後百度了一下,發現一下這篇文章寫的不錯,專門說了下this的問題,詳情檢視以下文章。