第十三章 Vue框架
13.1 ES6
ES6 是 ECMAScript 6.0 的簡寫,即 JavaScript 語言的下一代標准,已經在 2015年6月正式發布了,它的目標是讓JS能夠方便的開發企業級大型應用程序,因此,ES6的一些規范正在逐漸向Java、C# 等后端語言標准靠近。在 ES6 規范中,比較重大的變化有以下幾個方面:
-
新增 let、const 命令 來聲明變量,和var 相比,let 聲明的變量不存在變量提升問題,不允許在相同的作用域內重復聲明同一個變量,但沒有改變JS弱類型的特點,依然可以接受任意類型變量的聲明;const 聲明的變量不允許在后續邏輯中改變,提高了JS語法的嚴謹性。
-
新增解構賦值、rest 語法、箭頭函數等,這些都是為了讓代碼看起來更簡潔,而包裝的語法糖。
-
新增模塊化機制,這是 JavaScript 走向規范比較重要的一步,讓前端更方便的實現工程化。
-
新增類和繼承的概念,配合模塊化,JavaScript 也可以實現高復用、高擴展的系統架構。
-
新增模板字符串功能,高效簡潔,結束拼接字符串的時代。
-
新增 Promise 機制,解決異步回調多層嵌套的問題。
-
ES5中只有全局作用域和函數作用域,並沒有塊級作用域,而ES6中使用let設置塊級作用域,外層代碼塊就不再受內層代碼塊的影響
-
const用來聲明常量。const聲明常量必須立即初始化,並且其值不能再改變。const聲明常量的作用域與let相同,只在聲明所在的塊級作用域內有效。
const PI = 3.14;
-
ES6規定:var命令和function命令聲明的全局變量依舊是全局對象的屬性;let命令、const命令和class命令聲明的全局變量不屬於全局對象的屬性
var x = 10; let y = 20; window.x // 10 window.y // undefined
-
ES6允許按照一定的模式,從數組或對象中提取值,對變量進行賦值,這種方式被稱為變量的解構賦值。
數組的解構賦值: var [x, y, z] = [10, 20, 30] x // 10 y // 20 z // 30 對象的解構賦值: var {x, y} = {x: 10, y: 20} x // 10 y // 20
-
在此之前,JavaScript中只有indexOf方法(存在返回0,不存在返回-1)可用來確定一個字符串是否包含在另一個字符串中。ES6中又提供了3種新方法:
includes():返回布爾值,表示是否找到了參數字符串。 stratsWith():返回布爾值,表示參數字符串是否在源字符串的開始位置。 endsWith():返回布爾值,表示參數字符串是否在源字符串的結尾位置 var s = "Hello world!"; s.includes("o") // true s.startsWith("Hello") // true s.endsWith("!") // true 這三個方法都支持第2個參數,表示開始匹配的位置。 s.includes("o", 8) // false s.startsWith("world", 6) // true s.endsWith("Hello", 5) // true
-
模板字符串(template string)是增強版的字符串,用反引號(`)標識。它可以當做普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。在模板字符串中嵌入變量,需要將變量名寫入${}中。
var name = 'Q1mi', age = 18; `My name is ${name}, I’m ${age} years old.`
-
箭頭函數有個特點:如果參數只有一個,可以省略小括號、如果不寫return,可以不寫大括號、沒有arguments變量、不改變this指向(其中箭頭函數中this指向被固定化,不是因為箭頭函數內部有綁定this的機制。實際原因是箭頭函數根本沒有自己的this,導致內部的this就是外層代碼塊的this)
-
Object.assign方法用來將源對象(source)的所有可枚舉屬性復制到目標對象(target)。它至少需要兩個對象作為參數,第一個參數是目標對象,第二個參數是源對象。參數必須都是對象,否則拋出TypeError錯誤。
Object.assjgn只復制自身屬性,不可枚舉屬性(enumerable為false)和繼承的屬性不會被復制。
var x = {name: "Q1mi", age: 18}; var y = x; var z = Object.assign({}, x); x.age = 20; x.age // 20 y.age // 20 z.age // 18
-
ES5的構造對象的方式 使用構造函數來創造。構造函數唯一的不同是函數名首字母要大寫。
function Point(x, y){ this.x = x; this.y = y; } // 給父級綁定方法 Point.prototype.toSting = function(){ return '(' + this.x + ',' + this.y + ')'; } var p = new Point(10, 20); console.log(p.x) p.toSting(); // 繼承 function ColorPoint(x, y, color){ Point.call(this, x, y); this.color = color; } // 繼承父類的方法 ColorPoint.prototype = Object.create(Point.prototype); // 修復 constructor ColorPoint.prototype.constructor = Point; // 擴展方法 ColorPoint.prototype.showColor = function(){ console.log('My color is ' + this.color); } var cp = new ColorPoint(10, 20, "red"); console.log(cp.x); console.log(cp.toSting()); cp.showColor()
-
ES6 使用Class構造對象的方式:
class Point{ constructor(x, y){ this.x = x; this.y = y; } // 不要加逗號 toSting(){ return `(${this.x}, ${this.y})`;} } var p = new Point(10, 20); console.log(p.x) p.toSting(); class ColorPoint extends Point{ constructor(x, y, color){ super(x, y); // 調用父類的constructor(x, y) this.color = color; } // 不要加逗號 showColor(){ console.log('My color is ' + this.color); } } var cp = new ColorPoint(10, 20, "red"); console.log(cp.x); cp.toSting(); cp.showColor()
13.2 Vue指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue示例</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="d1"> {{ message }} // Hello Vue! <h1 v-html="name"></h1> //顯示p標簽渲染的Hello Vue! <p v-if="ok">哈哈哈</p> //如果data中OK:(true),則p標簽顯示,不存在或者(false),則標簽消失 <p v-show="ok">哈哈哈</p> //如果data中OK:(true),則p標簽顯示,不存在或者(false),display:none //注意,v-show 不支持 <template> 元素,也不支持 v-else <a v-bind:href="url">點我</a> //給a標簽綁定href='https://www.sogo.com' <div v-on:click="foo">點我彈出123</div> //v-on監聽,給div標簽綁定事件 <form action=""> <input type="text" name="username"> <input v-on:click.prevent='foo' type="submit" value="點我"> //終止submit提交特性,執行foo </form> <form v-on:submit.prevent="foo">...</form> //終止submit提交特性,執行foo </div> <script src="./vue.js"></script> <!--<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>--> <script> var data = { message: 'Hello Vue!' name: "<p>Hello Vue!</p>", age: 16, ok: true, url: 'https://www.sogo.com' }; var vm = new Vue({ el: "#d1", data: data, methods:{ /* foo:function(){ alert(123) } */ foo() { alert(123) }, remove(index){ this.todoList.splice(index,1) }, add(){ if (!this.current.title){ return } // 把當前的這個待辦事項 追加到todoList var obj = Object.assign({}, this.current) this.todoList.push(obj) // 清空輸入框 this.current.title = '' } } }) </script> </body> </html>
13.3 計算屬性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="d1"> <p>lastName: {{lastName}}</p> <p>firstName: {{firstName}}</p> <p>全名: {{ fullName }}</p> </div> <script src="./vue.js"></script> <script> var vm = new Vue({ el: "#d1", data: { firstName: "三", lastName: "張", }, // 計算屬性 computed: { // fullName:function () { // return this.lastName + this.firstName // } fullName: { // getter get: function () { console.log("你要和我要全名了。。。"); return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { console.log("你要給我設置新的全名...") var names = newValue.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1] } } } }) </script> </body> </html>
13.4 綁定Class和Style
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .c { height: 100px; width: 100px; border-radius: 50%; background-color: green; } .c1 { color: red; background-color: red; } </style> </head> <body> <div id="d1"> <div v-on:click="changeRed" //div標簽被點擊時執行method中的changeRed函數 class="c" v-bind:class="{ c1: isActive }" //在isActive返回true時,class="c1" > </div> <div v-bind:class="[a, b]"></div> //給div標簽綁定class="c1 c2" //根據條件切換列表中的 class,可以用三元表達式: <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div> //當有多個條件 class 時這樣寫有些繁瑣。所以在數組語法中也可以使用對象語法: <div v-bind:class="[{ active: isActive }, errorClass]"></div> <!--直接綁定CSS樣式--> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">還有人在聽</div> //直接綁定到一個樣式對象通常更好,這會讓模板更清晰: <div v-bind:style="styleObject">還有人在聽</div> //數組語法可以將多個樣式對象應用到同一個元素上: <div v-bind:style="[baseStyles, overridingStyles]"></div> </div> <script src="./vue.js"></script> <script> var vm = new Vue({ el: "#d1", data: { isActive:false, a: "c1", b: "c2", activeColor: "yellow", fontSize: 24 styleObject: { color: 'red', fontSize: '13px' } }, methods:{ changeRed(){ this.isActive = true } } }) </script> </body> </html>
13.5 條件渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="d1"> <template v-if="show"> //添加成模板,為所有div設置條件 <div>還有人在聽</div> <div>哈哈哈</div> <div>嘿嘿嘿</div> </template> <div v-if="show">還有人在聽嗎?</div> //data中show:true 時內容顯示 <div v-else>根本沒人在聽</div> //data中show:false 時內容顯示 <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> //添加key表示不復用標簽 </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template> //注意:<label> 元素仍然會被高效地復用,因為它們沒有添加 key 屬性 </div> <script src="./vue.js"></script> <script> var vm = new Vue({ el: "#d1", data: { show: true, loginType: 'username' } }) </script> </body> </html>
13.6 列表渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> </style> </head> <body> <div id="d1"> <ul> <li v-for="food in foods">{{food}}</li> </ul> <ol> <li v-for="(v, k, index) in obj">{{index}}:{{k}}:{{v}}</li> </ol> //類似於 v-if,也可以利用帶有 v-for 的 <template> 來循環渲染一段包含多個元素的內容: <ul> <template v-for="item in items"> <li>{{ item.msg }}</li> <li class="divider" role="presentation"></li> </template> </ul> </div> <script src="./vue.js"></script> <script> var vm = new Vue({ el: "#d1", data: { foods: [ "紅燒牛肉", "腰子湯", "小龍蝦", "豇豆炒蛋", "宮保雞丁" ], obj: { name: "張三", age: 16, gender: "哈哈哈" } } }) </script> </body> </html>
13.7 表單輸入綁定(雙向數據綁定)
<body> <div id="d1"> <input type="text" v-model="name.title"> //v-model負責監聽用戶的輸入事件以更新數據 <p>{{name.title}}</p> <hr> //單個復選框,綁定到布爾值:<!-- `checked` 為 true 或 false --> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> //多個復選框,綁定到同一個數組:往列表里加對應的value值 <hr> <input type="checkbox" id="jack" value="basketball" v-model="checkedNames"> <label for="jack">籃球</label> <input type="checkbox" id="john" value="football" v-model="checkedNames"> <label for="john">足球</label> <input type="checkbox" id="mike" value="doublecolorball" v-model="checkedNames"> <label for="mike">雙色球</label> <br> <span>Checked names: {{ checkedNames }}</span> <hr> //單選按鈕(value) <div id="example-4"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <br> <span>Picked: {{ picked }}</span> </div> //單選時(顯示option標簽內的值) <div id="example-5"> <select v-model="selected"> <option disabled value="">請選擇</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> //多選時 (綁定到一個數組):往數組里添加option標簽內的值 <div id="example-6"> <select v-model="selected" multiple style="width: 50px;"> <option>A</option> <option>B</option> <option>C</option> </select> <br> <span>Selected: {{ selected }}</span> </div> //用 v-for 渲染的動態選項: <select v-model="selected"> <option v-for="option in options" v-bind:value="option.value"> {{ option.text }} </option> </select> <span>Selected: {{ selected }}</span> //默認顯示A,根據option.value的值變化 //下拉選擇框 <select v-model="selected"> <!-- 內聯對象字面量 --> <option v-bind:value="123">123</option> <option v-bind:value="{ number: 123 }">123</option> </select> <p>{{ selected }}</p> <hr> //復選框,選中顯示"吳大",未選中顯示"梁二" <input type="checkbox" v-model="zhangzhao" true-value="吳大" false-value="梁二" > <p>{{zz}}</p> <hr> //修飾符,如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符: <input v-model.trim="msg"> <p>{{msg}}</p> </div> <script src="./vue.js"></script> <script> var vm = new Vue({ el: "#d1", data: { name: { //對象 title: '' }, checked:false, checkedNames: [], zhangzhao: null, selected: null, msg: '' picked: '' selected: '' //selected: [] selected: 'A', options: [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ] } }) </script> </body>
注意:v-model會忽略所有表單元素的
value、
checked、
selected特性的初始值而總是將Vue 例的數據作為數據來源。應該通過 JavaScript 在組件的
data` 選項中聲明初始值。
v-model
在內部為不同的輸入元素使用不同的屬性並拋出不同的事件:
-
text 和 textarea 元素使用
value
屬性和input
事件; -
checkbox 和 radio 使用
checked
屬性和change
事件; -
select 字段將
value
作為 prop 並將change
作為事件