ES6新增了let命令,用於聲明變量。其用法相似var,可是聲明的變量只在let命令所在的代碼塊內有效。html
{
let x = 10;
var y = 20;
}
x // ReferenceError: x is not defined
y // 20
效果以下:前端
var聲明變量存在變量提高。也就是在聲明變量以前就可使用該變量。vue
console.log(x) // undefined,var聲明變量以前可使用該變量
var x = 10;
刷新頁面,粘貼代碼,效果以下:react
而let不會這樣,let聲明的變量不能在聲明以前使用。jquery
刷新頁面,粘貼代碼,效果以下:git
好比:es6
function foo(){
let x = 10;
var x = 20;
}
foo(); // 報錯
刷新頁面,粘貼代碼,效果以下:github
再好比:ajax
function foo(){
let y = 10;
let y = 20;
}
foo(); // 報錯
刷新頁面,粘貼代碼,效果以下:算法
var name = 'Q1mi'
function foo(){
console.log(name)
if (false){
var name = 'Bob'
}
}
foo() // undefined
刷新頁面,粘貼代碼,效果以下:
for (var i=0;i<5;i++){ console.log('哈哈'); } console.log(i); // 5
刷新頁面,粘貼代碼,效果以下:
var聲明的變量會污染全局,因此在for循環外部能夠打印i的值。for循環中的i最好使用let聲明
ES6中的let聲明變量的方式實際上就爲JavaScript新增了塊級做用域。
var name = 'Q1mi'
function foo(){
console.log(name)
if (false){
let name = 'Bob'
}
}
foo() // Q1mi
刷新頁面,粘貼代碼,效果以下:
此時,在foo函數內容,外層代碼塊就再也不受內層代碼塊的影響。因此相似for循環的計數變量咱們最好都是用let來聲明。
let聲明可以將變量限制在當前的塊級做用域中
const用來聲明常量。const聲明變量必須當即初始化,而且其值不能改變。
const聲明常量的做用域與let相同,只在生命所在的塊級做用於內有效
const PI = 3.14;
舉例:
const 用來聲明一個常量,不能修改
全局對象的屬性:
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
刷新頁面,粘貼代碼,效果以下:
var和function聲明的變量,默認會在windows對象上
let聲明的變量默認不會出如今windows對象上
舉例:
window.name1輸出undefined
箭頭函數特色:
1.若是參數只有一個,能夠省略小括號
2.若是不寫return,能夠不屑大括號
3.沒有arguments
4.不改變this指向
其中箭頭函數中this指向被固定化,不是由於箭頭函數內部有綁定this的機制。實際緣由是箭頭函數根本沒有本身的this,致使內部的this就是外層代碼塊的this
能夠查看下面兩段代碼輸出的區別:
var person = {
name: 'Q1mi',
age:18,
func:function(){
console.log(this);
}
}
person.func() // person對象
刷新頁面,粘貼代碼,效果以下:
和
var person = {
name: 'Q1mi',
age:18,
func:()=>{
console.log(this);
}
}
person.func() // window對象
刷新頁面,粘貼代碼,效果以下:
但凡用到箭頭函數,不要用this
ES6容許直接寫入變量和函數做爲對象的屬性和方法。
function f(x, y){
return {x, y}
}
上面的寫法等同於:
function f(x, y){
return {x: x, y: y}
}
對象的方法也可使用簡潔表示法:
var o = {
method(){
return "hello";
}
}
等同於:
var o = {
method: function(){
return "Hello";
}
}
刷新頁面,粘貼代碼,效果以下:
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
刷新頁面,粘貼代碼,效果以下:
注意:
Object.assign方法的其餘用處,可查看文末連接。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> <script> // 定義一個構造函數 function Point(x, y){ this.x = x; this.y = y; } // 給父級綁定方法 Point.prototype.toSting = function(){ return '(' + this.x + ',' + this.y + ')'; }; // 生成一個Point對象 var p = new Point(10, 20); console.log(p.x); console.log(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(); </script> </body> </html>
刷新頁面,效果以下:
ES6 使用Class構造對象的方式:
修改test.html,js代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> <script> 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(); </script> </body> </html>
刷新頁面,效果以下:
(能夠去github查看三個框架的 star星):
vue 尤雨溪,漸進式的JavaScript框架
react Facebook公司,裏面的(高階函數 es6)很是多,對初學者不友好
angular 谷歌公司,目前更新到6.0,學習angular得須要玩一下typescript
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script src='./vue.js'></script>
上面vue.js文件是一個庫,小而精;
框架是功能比較齊全,像Django,大而全,功能比較多;
示例代碼:
<script src="./vue.js"></script> <script> // 實例化對象 new Vue({ el:"#app", // 這裏data是一個對象,在後續學習中發現data中通常是一個函數 data:{ // 數據屬性 msg1:"黃瓜", person:{ name:"alex" }, msg2:'hello Vue', isShow:'True' }, methods:{ // 該組件中聲明的方法 }, watch:{ // 該組件中監聽的數據屬性 } }); </script>
注意:若是是咱們本身定義的屬性和方法,則所有暴露在外面,若是是vue實例對象本身屬性和方法,會在前邊加一個」$」進行區分。另外,data中有一個觀察者Observer,在觀察着一些數據是否發生了改變,若改變,則將改變後的值立馬渲染到DOM中對應的地方,控制檯查看data效果以下圖:
<div id="app"> <!--模板語法--> <h2>{{ msg1 }}</h2> <h3>{{ 'haha' }}</h3> <h3>{{ 1+1 }}</h3> <h4>{{ {'name':'alex'} }}</h4> <h5>{{ person.name }}</h5> <h2>{{ 1>2?'真的':'假的' }}</h2> <p>{{ msg2.split('').reverse().join('') }}</p> </div>
數據驅動視圖,設計模式MVVM(model view viewmodel)
(使用指令系統後邊必定是字符串,且字符串中的變量必定是數據屬性中已有的變量)
<div id="content"> {{ msg }} <div v-text="msg"></div> <!-- v-text至關於innerText --> <div v-html="msg"></div> <!-- v-html至關於innerHTML --> </div> <script src="./vue.js"></script> <script> // 實例化對象 new Vue({ el:"#content", // data中是一個函數 函數中return一個對象,能夠是空對象,但不能不return data(){ // 函數的單體模式 return{ msg:"<h2>alex</h2>" } } }); </script>
效果以下圖:
<div class="box1" v-show="isShow">hello</div> <div class="box2" v-if="isShow">hello</div>
分析:isShow爲真則顯示div,爲假則不顯示;
區別:v-show爲假時至關於display:none;v-if爲假時至關於移除該div,可是有一個佔位的註釋」<!-- -->」;
官網對v-if和v-show的區別:
1)v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
2)v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。
3)相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。
4)通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用 v-if 較好。
v-if與v-else:可使用 v-else 指令來表示 v-if 的「else 塊」:
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div> // 注意:v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,不然它將不會被識別。
v-bind:標籤中全部屬性,如img標籤的src alt,a標籤的href title id class等,以下:
<img v-bind:src="imgSrc" v-bind:alt="msg">
v-bind:class='{active:isActive}'表示若isActive(數據屬性中定義的變量)爲真,則對應div增長active類,不然不增長,以下:
<div class="box" v-bind:class='{active:isActive}'></div>
v-on:監聽js中的全部事件,如click,mouseover,mouseout等,以下:
<button v-on:click="clickHandler">切換顏色</button>
v-bind的簡便寫法是":",如:<div class="box" :class='{active:isActive}'></div>
v-on的簡便寫法是"@",如:<button @click="clickHandler">切換顏色</button>
<div id="app"> <ul v-if="res.status === 'ok'"> <!-- v-for的優先級是最高的 diff算法 --> <li v-for='(item,index) in res.users' :key="item.id"> <h3>{{ item.id }} -- {{ item.name }} -- {{ item.age }}</h3> </li> </ul> <div v-for='(value,key) in person'> {{ key }}-----{{ value }} </div> </div> <script src="./vue.js"></script> <script> new Vue({ el:"#app", data(){ return { res: { status: 'ok', users: [ {id: 1, name: 'alex', age: 18}, {id: 2, name: 'wusir', age: 30}, {id: 3, name: 'yuan', age: 48} ] }, person: { name: 'tom' } } }, methods:{ // 該組件中聲明的方法 }, watch:{ // 該組件中監聽的數據屬性 } }); </script>
總結:遍歷數組時,一個參數是值,兩個參數是(值,索引);遍歷對象時,一個參數是值,兩個參數是(值,鍵)。
注意:必定要綁定一個標識(有id就綁定id,沒有id綁定index),則值改變會直接經過key查找,而不用再去遍歷查找,提高效率。
<div id="app"> <img :src="images[currentIndex].imgSrc" @click="imgHandler" alt=""> <br /> <button @click="prevHandler">上一張</button> <button @click="nextHandler">下一張</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> // Vue實例對象,能夠有返回值vm,官網中就是用vm表明Vue實例對象 let vm = new Vue({ el: '#app', data() { return { // 實際項目中images這個數據以及圖片是後端返回過來的 images:[ {id:1, imgSrc:'./images/1.jpg'}, {id:2, imgSrc:'./images/2.jpg'}, {id:3, imgSrc:'./images/3.jpg'}, {id:4, imgSrc:'./images/4.jpg'} ], currentIndex:0 } }, methods:{ nextHandler(){ this.currentIndex++; if(this.currentIndex == 4){ this.currentIndex = 0; } }, prevHandler(){ this.currentIndex--; if(this.currentIndex == -1){ this.currentIndex = 3; } }, imgHandler(e){ console.log(e); // e是當前事件對象 console.log(e.target); // 當前事件對象的目標對象 console.log(this); // this指當前Vue實例對象 } }, // 組件建立完成時調用created函數,可發送ajax created(){ // 注意:開定時器就要清定時器,後面會介紹在destroyed函數中清掉 setInterval(()=>{ // 定時器中若不用箭頭函數則this指則定時器對象 console.log(this); // 這時this指當前Vue實例對象 this.currentIndex++; if(this.currentIndex == 4){ this.currentIndex = 0; } },2000); // 若定時器中不用箭頭函數,也能夠用下面方式 let _this = this; setInterval(function () { console.log(_this); // _this指當前Vue實例對象 },2000) } }) </script> 示例代碼
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> span.active{color:red} </style> </head> <body> <div id="app"> <span @click="clickHandler(index, category.id)" v-for="(category,index) in categoryList" :key="category.id" :class="{active:index==currentIndex}"> {{ category.name }} </span> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="jquery.min.js"></script> <script> let vm = new Vue({ el: '#app', data() { return { categoryList:[], currentIndex:0 } }, methods:{ clickHandler(i, id){ this.currentIndex = i; // 發起請求 $.ajax({ url:`https://www.luffycity.com/api/v1/courses/?sub_category=${id}`, type:'get', success:function (res) { console.log(res); } }) } }, // 組件建立完成時調用created函數,可發送ajax created(){ $.ajax({ url:'https://www.luffycity.com/api/v1/course_sub/category/list/', type:'get', success:(res) => { // 若不用箭頭函數,則this指當前ajax對象 console.log(res); // res是請求接口收到的數據 // 根據響應數據的狀態字段判斷是否成功 if(res.error_no === 0){ var data = res.data; this.categoryList = data; // this指當前Vue實例對象 let obj = { id:0, name:'所有', category:0 }; // unshift方法表示在數組前插入一個元素 this.categoryList.unshift(obj) } }, error:function (err) { console.log(err); } }) } }) </script> </body> </html> 示例代碼
頁面運行效果以下圖:
依次點擊每一項,控制檯效果以下圖:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .active{color:blue} </style> </head> <body> <div id="music"> <!-- audio 是HTML5的新標籤 --> <!-- @ended 播放完成會自動調用該方法 --> <audio @ended="nextHandler" :src="musicList[currentIndex].songSrc" controls autoplay></audio> <ul> <li @click="songHandler(index)" v-for="(item,index) in musicList" :key="item.id" :class="{active:index==currentIndex}"> <h5>歌名:{{ item.name}}</h5> <p>歌手:{{ item.author}}</p> </li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> let musicList = [ { id:1, name:'於榮光 - 少林英雄', author:'於榮光', songSrc:'./static/於榮光 - 少林英雄.mp3' }, { id:2, name:'Joel Adams - Please Dont Go', author:'Joel Adams', songSrc:'./static/Joel Adams - Please Dont Go.mp3' }, { id:3, name:'MKJ - Time', author:'MKJ', songSrc:'./static/MKJ - Time.mp3' }, { id:4, name:'Russ - Psycho (Pt. 2)', author:'Russ', songSrc:'./static/Russ - Psycho (Pt. 2).mp3' } ]; new Vue({ el: '#music', data() { return { musicList:[], currentIndex:0 } }, methods:{ songHandler(i){ this.currentIndex = i }, nextHandler(){ this.currentIndex++; if(this.currentIndex == 4){ this.currentIndex = 0; } } }, created(){ // 實際項目中每每向後臺要數據,賦值給數據屬性 this.musicList = musicList } }) </script> </body> </html> 示例代碼
模板內的表達式很是便利,可是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板太重且難以維護。例如:
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在這個地方,模板再也不是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裏是想要顯示變量message 的翻轉字符串。當你想要在模板中屢次引用此處的翻轉字符串時,就會更加難以處理。因此,對於任何複雜邏輯,你都應當使用計算屬性。例如:
<div id="example"> <p>原數據: "{{ message }}"</p> <p>翻轉後的數據: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 計算屬性的 getter(計算屬性默認只有getter方法),計算屬性要有返回值 reversedMessage: function () { return this.message.split('').reverse().join('') // `this`指向vm實例 } } })
雖然計算屬性在大多數狀況下更合適,但有時也須要一個自定義的偵聽器。這就是爲何 Vue 經過 watch 選項提供了一個更通用的方法,來響應數據的變化。當須要在數據變化時執行異步或開銷較大的操做時,這個方式是最有用的。
watch能夠監聽單個屬性,若是想監聽多個屬性,則聲明多個屬性的監聽,以下:
<div id="app"> <p>{{ msg }}</p> <button @click='clickHandler'>修改</button> </div> <script src="vue.js"></script> <script> new Vue({ el:'#app', data(){ return { msg:"alex", age:18 } }, methods:{ clickHandler(){ this.msg = "wusir" } }, watch:{ // 監聽屬性'msg' 'msg':function (value) { console.log(value); if (value === 'wusir'){ this.msg = '大武sir'; } }, // 監聽屬性'age' 'age':function (value) { } } }) </script>
注意:計算屬性便可以監聽單個屬性,又能夠監聽多個屬性,以下示例:
<div id="app"> <p>{{ myMsg }}</p> <button @click='clickHandler'>修改</button> </div> <script src="vue.js"></script> <script> new Vue({ el:'#app', data(){ return { msg:"alex", age:18 } }, methods:{ clickHandler(){ this.msg = "wusir"; this.age = 20; } }, computed:{ myMsg: function () { // 即監聽msg屬性,又監聽age屬性 return `個人名字叫${this.msg},年齡是${this.age}`; } } }) </script>
修改audio標籤的src屬性值,以下:
computed:{ currentSong(){ // 既監聽了musicList,又監聽了currentIndex return this.musicList[this.currentIndex].songSrc } }
總結:計算屬性的方法便可以在模板語法中使用,又能夠在指令系統中使用。
Vue實例對象中,通常methods和computed中定義的函數中的this是指當前Vue實例對象,而created中的ajax和定時器中定義的函數中的this是指ajax或者定時器對象,這時,ajax和定時器中的函數改成箭頭函數,就能夠改變this的指向,即this指向當前Vue實例對象。