1. 程式人生 > >用Vue寫購物車後,對this的理解

用Vue寫購物車後,對this的理解

    最近在學習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方法(函式)究竟是怎麼操作的呢?

    就上面的addListthis.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的問題,詳情檢視以下文章