Vue筆記

## 框架和庫的區(qū)別?> 框架(framework):一套完整的軟件設(shè)計架構(gòu)和**解決方案**。> > 庫(library):對常用功能性函數(shù)的**封裝**。> > 一般也可以認為框架大而全,庫小而精。一個框架中可以包含或者集成多個庫。 + 框架:是一套完整的解決方案;對項目的侵入性較大,項目如果需要更換框架,則需要重新架構(gòu)整個項目。 + 庫(插件):提供某一個小功能,對項目的侵入性較小,如果某個庫無法完成某些需求,可以很容易切換到其它庫實現(xiàn)需求。## 數(shù)組方法擴展- `Array.prototype.forEach`:替代for循環(huán)對數(shù)組進行循環(huán)遍歷```JavaScriptvar list = [1,2,3,4,5]list.forEach(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i)})```- `Array.prototype.map`:對數(shù)組進行遍歷,同時會返回一個新數(shù)組,新數(shù)組中的每一項都是回調(diào)函數(shù)中的返回值```JavaScriptvar list = [1,2,3,4,5]var newArr = list.map(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i) return v * 2})console.log(newArr) // [2,4,6,8,10]```- `Array.prototype.findIndex`:對數(shù)組進行遍歷,會返回一個滿足回調(diào)函數(shù)條件的元素的索引```JavaScriptvar list = [1,2,3,4,5]var index = list.findIndex(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i) if(v == 4){ // 當(dāng)return true時終止循環(huán) 同時將該元素的索引返回給findIndex函數(shù) return true } // 簡寫成 // return v == 4})console.log(index) // 3```- `Array.prototype.filter`:對數(shù)組進行遍歷,返回一個新數(shù)組,新數(shù)組中的每一項都是滿足回調(diào)函數(shù)中條件的元素,當(dāng)滿足條件時需要`return true````JavaScriptvar list = [1,2,3,4,5]var newArr = list.filter(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i) if(v%2 == 0){ return true } // 簡寫成 // return v%2 == 0})console.log(newArr) // [2,4] ```- `Array.prototype.some`:對數(shù)組進行遍歷,返回一個布爾值,判斷當(dāng)前數(shù)組中是否有一個元素符合回調(diào)函數(shù)中的條件(特點:只要一個元素滿足條件,最終返回結(jié)果就是true)```JavaScriptvar list = [1,2,3,4,5]var flag = list.some(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i) if(v % 2 == 0){ // return true時則終止繼續(xù)循環(huán) return true }})console.log(flag) // true// 注意: 由于遍歷的數(shù)組第二個元素就滿足了條件 所以循環(huán)到第二個元素時 就停止循環(huán)了```- `Array.prototype.every`:對數(shù)組進行遍歷,返回一個布爾值,判斷當(dāng)前數(shù)組中是否每一個元素都符合回調(diào)函數(shù)中的條件(特點:只要一個元素不滿足條件,最終返回結(jié)果就是false)```JavaScriptvar list = [1,2,4,6,8]var flag = list.every(function(v,i){ // v是當(dāng)前遍歷的這一個元素 i是這個元素的索引 console.log('當(dāng)前元素是' + v,'當(dāng)前元素的索引是' + i) if(v % 2 == 0){ // return true時則終止繼續(xù)循環(huán) return true }})console.log(flag) // false// 注意: 由于遍歷的數(shù)組第一個元素就不滿足條件 實際上循環(huán)一次就停止了```## Vue基礎(chǔ)> MVC:對項目的整體把控,M代表的是數(shù)據(jù)庫中的數(shù)據(jù),V代表的是前端的視圖層,C用于處理M和V之間進行交互的業(yè)務(wù)邏輯(業(yè)務(wù)邏輯需要程序員自己控制,自己編寫)> MVVM:主要用于一些前端的框架,對MVC三層架構(gòu)中的視圖層再次進行層次劃分,M是當(dāng)前一個視圖中需要用到的數(shù)據(jù),V就是當(dāng)前視圖,VM負責(zé)M和V之間的數(shù)據(jù)調(diào)度,內(nèi)部已經(jīng)幫你完成了數(shù)據(jù)的綁定和交互> MVC和MVVM之間的區(qū)別:MVC數(shù)據(jù)流通是單向的,MVVM是雙向數(shù)據(jù)綁定> 雙向數(shù)據(jù)綁定的意思就是模型中的數(shù)據(jù)可以之間更新到視圖上,視圖中的數(shù)據(jù)發(fā)生改變也可以直接更新到模型中能夠做到雙向數(shù)據(jù)綁定(通信)的原因:就是因為有VM的存在,VM內(nèi)部的實現(xiàn)一般是框架已經(jīng)處理完成,不需要程序員進行控制- 雙向數(shù)據(jù)綁定原理: `Object.defineProperty`存取器> 使用`Object.defineProperty`提供的set方法可以在給對象賦值時,觸發(fā)額外操作,即在set函數(shù)內(nèi)部去處理視圖的更新```JavaScript// 使用 Object.defineProperty 可以給對象賦值var obj = {};Object.defineProperty(obj,'name',{ value:'zxx'})console.log(obj.name)var obj = {};var initValue = 'zxx'Object.defineProperty(obj,'name',{ get:function(){ console.log('我被讀取了') return initValue }, set:function(v){ console.log('我被賦值了') initValue = v }})obj.name = 'lxy'console.log(obj.name)```### Vue基本編碼步驟1. 引入vue.js文件2. 定義一個vue的管理范圍



vue1.0里面vue的管理區(qū)域的id可以定義在HTML以及body標簽上? ? ? ? vue2.0里面不允許這樣來做3. 定義一個vue的對象? ? ? ? var vm = new Vue({? ? ? ? ? ? el:'#app',? ? ? ? ? ? // data定義vue實例的所有屬性? ? ? ? ? ? data:{? ? ? ? ? ? ? ? // 定義將來要在vue管理區(qū)域中使用的數(shù)據(jù)? ? ? ? ? ? ? ? name:"zs"? ? ? ? ? ? },? ? ? ? ? ? // methods定義vue實例所有的方法? ? ? ? ? ? methods:{? ? ? ? ? ? ? ? fn:function(){? ? ? ? ? ? ? ? ? ? this.name = 'ls'? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? })### Vue系統(tǒng)指令- `{{}}`:插值表達式```? ? 作用:將vue對象中的數(shù)據(jù)以及表達式顯示到vue托管區(qū)域中? ? {{這里書寫vue對象中data里面的數(shù)據(jù)或者表達式}}```- `v-cloak`:解決表達式閃爍問題```1. 定義一個樣式 ? [v-cloak]{

? ? ? display:none

? }

2. 使用

{{name}}

原理:當(dāng)vue.js文件還沒有加載出來時 使用[v-cloak]樣式作用于當(dāng)前指令所在標簽,當(dāng)vue.js能夠起作用時,會自動刪除v-cloak指令```? ? ? ? - `v-text`:輸出文本數(shù)據(jù)``````- `v-html`:輸出HTML結(jié)構(gòu)數(shù)據(jù)```

data:{name:'zs'}```- `v-bind`:動態(tài)給標簽或者組件綁定屬性```

// 使用:簡寫v-bind

// 變量和常量組合跳轉(zhuǎn)data:{cls: 'red blue',id: 1}```? - `v-on`:綁定事件```

// 簡寫

methods: { // 這個 methods屬性中定義了當(dāng)前Vue實例所有可用的方法? ? ? ? show: function () {? ? ? ? ? alert('Hello')? ? ? ? } }```- `v-model`:雙向數(shù)據(jù)綁定```// 可以使用的標簽:input textarea select 組件// name會和表單元素的value進行關(guān)聯(lián) value值變化 name值變化 反過來name值發(fā)生變化 value值也會發(fā)生變化```- `v-for`:循環(huán)輸出HTML元素```

{{item.name}}

```- `v-if`:根據(jù)表達式值的真假決定元素的顯示隱藏```// isShow為true顯示div 為false隱藏div// v-if是直接操作DOM 即隱藏時會將該div從DOM結(jié)構(gòu)中移除

```- `v-show`: 根據(jù)表達式值的真假決定元素的顯示隱藏```// isShow為true顯示div 為false隱藏div// v-show是操作div的樣式 顯示時添加 style = 'display:block'; 隱藏時添加style = 'display:none'

v-if 是刪除DOM元素 效率比較低 會造成頁面的結(jié)構(gòu)重新繪制v-show 是控制樣式 只會改變當(dāng)前這一個元素的樣式 不會造成頁面結(jié)構(gòu)的重新繪制```### 在Vue中使用樣式#### 使用class樣式1. 數(shù)組```

這是一個邪惡的H1

```2. 數(shù)組中使用三元表達式```

這是一個邪惡的H1

```3. 數(shù)組中嵌套對象```

這是一個邪惡的H1

```4. 直接使用對象```

這是一個邪惡的H1

```#### 使用內(nèi)聯(lián)樣式1. 直接在元素上通過 `:style` 的形式,書寫樣式對象```

這是一個善良的H1

```2. 將樣式對象,定義到 `data` 中,并直接引用到 `:style` 中 + 在data上定義樣式:```data: {? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }}``` + 在元素中,通過屬性綁定的形式,將樣式對象應(yīng)用到元素中:```

這是一個善良的H1

```3. 在 `:style` 中通過數(shù)組,引用多個 `data` 上的樣式對象 + 在data上定義樣式:```data: {? ? ? ? h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },? ? ? ? h1StyleObj2: { fontStyle: 'italic' }}``` + 在元素中,通過屬性綁定的形式,將樣式對象應(yīng)用到元素中:```

這是一個善良的H1

```### 過濾器> `過濾器`:對需要展示的數(shù)據(jù)進行加工處理后再展示到界面,并不會改變原數(shù)據(jù)- 全局過濾器:當(dāng)前頁面所有Vue實例的托管區(qū)域都可以使用```JavaScriptVue.filter('過濾器名稱',function(value,arg){? ? // value就是需要處理的原始數(shù)據(jù) arg是使用過濾器時傳遞的參數(shù)? ? // 對數(shù)據(jù)處理的業(yè)務(wù)邏輯? ? return 處理完畢的數(shù)據(jù)})使用方法:原始數(shù)據(jù) | 過濾器名稱(參數(shù))```- 私有過濾器:只有當(dāng)前定義過濾器的Vue實例所托管的區(qū)域可以使用```JavaScriptnew Vue({? ? el:'#app',? ? // 私有過濾器? ? filters:{? ? ? ? '過濾器的名稱':function(value){? ? ? ? ? ? return 處理完畢的數(shù)據(jù)? ? ? ? }? ? }})```### 自定義指令> `指令`: 其實就是Vue給我們提供的操作DOM元素的一些方法- 全局指令```JavaScriptVue.directive('指令名稱',{? ? // 指令第一次綁定到元素身上時執(zhí)行(在內(nèi)存中綁定到了DOM對象上邊)? ? bind:function(el,binding,VNode){? ? ? ? // el: 指令所在的DOM元素對象? ? ? ? // binging.value 指令等號右邊表達式的值? ? ? ? // binging.expression 指令等號右邊表達式? ? ? ? // VNode.context 當(dāng)前指令所在托管區(qū)域?qū)τ诘腣ue實例對象? ? },? ? // 當(dāng)前指令所在元素插入到父節(jié)點時調(diào)用(不保證DOM已經(jīng)渲染完畢)? ? inserted:function(){},? ? // 指令綁定的值發(fā)生變化時會去執(zhí)行? ? update:function(){},? ? // 指令所在的組件值更新完畢時調(diào)用? ? componentUpdated:function(){},? ? // 自定義指令從當(dāng)前元素解綁時調(diào)用? ? unbind:function(){}})```- 私有指令```JavaScriptnew Vue({? ? el:'#app',? ? // 私有指令? ? directives:{? ? ? ? '指令名稱':{? ? ? ? ? ? bind:function(el,binding){? ? ? ? ? ? }? ? ? ? }? ? },? ? // 私有過濾器? ? filters:{? ? ? ? '過濾器的名稱':function(value){? ? ? ? ? ? return 處理完畢的數(shù)據(jù)? ? ? ? }? ? }})```## 生命周期鉤子函數(shù)> 回調(diào)函數(shù):一個函數(shù)被當(dāng)做參數(shù)進行傳遞的時候,稱作這個函數(shù)為回調(diào)函數(shù)> 構(gòu)造函數(shù):一個函數(shù)被new 關(guān)鍵字引導(dǎo)執(zhí)行的時候,稱作這個函數(shù)為構(gòu)造函數(shù)> 鉤子函數(shù): 一個應(yīng)用程序或者框架內(nèi)部提前定義好的一批函數(shù),這些函數(shù)會在特定的時間段自動執(zhí)行>> 生命周期: 一個程序會存在初始化 - 運行 - 銷毀等階段,這些階段統(tǒng)稱為該程序的生命周期```new Vue({? ? el:'#app',? ? data:{},? ? methods:{},? ? beforeCreated(){},? ? // data中的數(shù)據(jù)和methods中的方法已經(jīng)初始化完畢會去自動執(zhí)行created方法? ? created(){? ? ? ? // 用于發(fā)生數(shù)據(jù)請求,也可以初始化一些數(shù)據(jù)? ? },? ? beforeMount(){},? ? // 真實DOM已經(jīng)渲染完畢會執(zhí)行mounted函數(shù)? ? mounted(){? ? ? ? // 操作真實DOM? ? }? ? beforeUpdate(){},? ? // data中的發(fā)生了變化而且被重新渲染到了界面上時才會執(zhí)行? ? updated(){? ? ? ? // 數(shù)據(jù)更新后重新操作DOM? ? },? ? // 實例銷毀之前,實例上面的各種屬性和方法都還可以正常訪問,通??梢栽谶@里手動回收一些頁面沒有被釋放的變量,比如清楚定時器的操作。? ? beforeDestroy(){},? ? // 實例已經(jīng)從內(nèi)存中被銷毀? ? destroyed(){}})```## vue-resource發(fā)生ajax請求> vue.studyit.io```javascript// get請求this.$http.get('url').then(function(res){? ? // res.body 里面就是請求回來的數(shù)據(jù)})// post 請求 application/x-www-form-urlencode -> name=zs&age=18// application/json => {'name':'zs','age':18}this.$http.post('url',{name:'zs',age:18},{emulateJSON:true}).then(function(res){? ? // res.body})// jsonp請求this.$http.jsonp('url').then(function(res){? ? // res.body})```- **JSONP**:JSON數(shù)據(jù)格式的一種使用方式,用于解決跨域問題- **跨域**: 由于瀏覽器同源策略的限制,不同源的URL不能互相通信,這種現(xiàn)象叫做跨域- **同源策略**: 兩個域名只有 **協(xié)議** **主機地址** **端口號**完全一致時才能相互通信訪問- **JSONP實現(xiàn)原理**:利用script標簽的src屬性發(fā)送請求不受同源策略的限制這個機制去實現(xiàn)跨域資源共享(script標簽?zāi)軌蚩缬蛟L問是歷史遺留問題,并不安全)? ? 1. 動態(tài)創(chuàng)建一個script標簽,并且將需要請求的URL地址設(shè)置給script標簽的src屬性,同時在URL地址后面拼接上一個回調(diào)函數(shù)名稱```? ? ? ? function getJson(data){? ? ? ? ? ? console.log(data)? ? ? ? }// getJson就是在前端本地定義好的一個方法的方法名 ```? ? ? 2. 后臺接收到該請求后,先根據(jù)參數(shù)判斷是否是JSONP請求,如果是,則將客戶端請求的數(shù)據(jù)整理好,和前端發(fā)送過來的方法名一起拼接成一個函數(shù)調(diào)用的字符串,客戶端需要的數(shù)據(jù)就是這個函數(shù)調(diào)用時傳的參數(shù)```? ? ? ? // 假設(shè)要發(fā)送給前端的數(shù)據(jù)是 'ok'? ? ? ? 'getJson('ok')'? ? ? ? // 響應(yīng)給前端? ? ? ? res.end('getJson('ok')') ```? ? ? 3. 由于后臺響應(yīng)回來的數(shù)據(jù)是一個字符串,而且是函數(shù)調(diào)用,所以前端拿到響應(yīng)回來的數(shù)據(jù)相當(dāng)于調(diào)用了該方法,那么前端定義好的方法會自動執(zhí)行,而且方法內(nèi)的形參可以接收到實參值,也就是后臺拼接的數(shù)據(jù)```? ? ? ? function getJson(data){? ? ? ? ? ? console.log(data) // ok? ? ? ? }```? ? 4. 數(shù)據(jù)拿到之后,一般這個動態(tài)創(chuàng)建的script標簽會被刪除掉## vue過渡動畫### 原生css類實現(xiàn)```JavaScript// 1. 將需要實現(xiàn)動畫的元素使用transition標簽包裹起來? ?

我是需要過渡動畫的元素
// 2. 使用系統(tǒng)提供的類名書寫動畫樣式// v-enter: 動畫進入時候的初始狀態(tài)// v-leave-to: 動畫離開時候的結(jié)束狀態(tài)v-enter,v-leave-to {}// v-enter-active: 動畫進入期間持續(xù)狀態(tài)// v-enter-active: 動畫離開期間持續(xù)狀態(tài) v-enter-active,v-leave-active {}// 動畫離開時候的初始狀態(tài)// 動畫進入時候的結(jié)束狀態(tài)v-leave,v-enter-to {}// 3. 也可以使用transition上面的name屬性指定v-前綴```### animatie.css類庫實現(xiàn)```JavaScript// 1. 將需要實現(xiàn)動畫的元素使用transition標簽包裹起來? ?
我是需要過渡動畫的元素
// 2. 在transition上設(shè)置動畫類名? ?
我是需要過渡動畫的元素
```### 動畫鉤子函數(shù)實現(xiàn)```javascript// 1. 將需要實現(xiàn)動畫的元素使用transition標簽包裹起來? ?
我是需要過渡動畫的元素
// 2. 在transition上注冊實現(xiàn)動畫的鉤子函數(shù),入場動畫三個,出場動畫三個? ?
我是需要過渡動畫的元素
// 3. 在vue實例的methods中定義鉤子函數(shù)new Vue({? ? el:'#app',? ? data:{},? ? methods:{? ? ? ? // 入場動畫初始狀態(tài)設(shè)置? ? ? ? beforeEnter(){? ? ? ? ? ? // 一般使用JS設(shè)置執(zhí)行動畫元素的初始位置和其他樣式屬性? ? ? ? },? ? ? ? // 入場動畫持續(xù)過程? ? ? ? enter(el,done){? ? ? ? ? ? // 1. 固定寫法 迫使瀏覽器重繪 刷新動畫? ? ? ? ? ? el.offsetWidth? ? ? ? ? ? // 2. 一般設(shè)置執(zhí)行動畫元素最終的位置和其他樣式屬性? ? ? ? ? ? // 3. 固定寫法 調(diào)用afterEnter函數(shù)? ? ? ? ? ? done()? ? ? ? },? ? ? ? // 入場動畫結(jié)束狀態(tài)? ? ? ? afterEnter(){? ? ? ? ? ? // 設(shè)置動畫元素回到初始狀態(tài)? ? ? ? },? ? ? ? // 出場動畫初始狀態(tài)? ? ? ? beforeLeave(){? ? ? ? },? ? ? ? // 出場動畫持續(xù)狀態(tài)? ? ? ? leave(){? ? ? ? },? ? ? ? // 出場動畫結(jié)束狀態(tài)? ? ? ? afterLeave(){? ? ? ? }? ? }})```### transition-group列表渲染> 如果需要渲染的元素是一個列表,則不能使用transition包裹元素,需要使用transition-group- `appear`屬性可以使默認出現(xiàn)的元素出現(xiàn)過渡動畫- `tag`屬性可以指定`transition-group`標簽被渲染成一個什么元素,默認情況下`transition-group`會被渲染成`span````? ?
```## 組件> http://blog.gdfengshuo.com/example/work/#/login> https://github.com/UniverseKing/awesome-github-vue> **注意**:> 1. 定義組件時如果使用的是駝峰命名,那么使用組件時需要將駝峰的大寫字母轉(zhuǎn)成小寫,并且用-連接兩個單詞 ```javascriptVue.component('myCom',{? ? template:'
我是一個駝峰命名的組件
'})// 使用```> 2. 組件的`template`屬性中的模版內(nèi)部如果有多個元素,必須被包含在唯一的一個根元素中```javascript? ?
? ? ? ?

我是p元素

? ? ? ? 我是span元素? ?
```> 3. 私有組件(子組件)使用`components`屬性進行定義,定義好的私有組件只能在父組件的模板中使用```javascript? ?
? ? ? ? ? ?
// 父組件Vue.component('father',{? ? template:'#father',? ? components:{? ? ? ? // 子組件? ? ? ? son:{? ? ? ? ? ? template:'
我是son組件
'? ? ? ? }? ? }})```### 全局組件的三種定義方式-? `vue.extend()`定義```javascript// 1. 使用vue.extend()定義組件模板var dv = Vue.extend({? ? template:'
我是一個組件
'})// 2. 使用Vue.component()注冊組件Vue.component('com',dv)// 3. 在Vue托管區(qū)域像使用普通HTML標簽一樣使用組件```-? `vue.component()`定義```javascript// 1. 使用Vue.component定義組件Vue.component('com',{? ? template:'

我是一個組件中的元素

我也是組件中的元素
'})// 2. 使用組件```- 使用`template`標簽定義模板```javascript// 1. 使用Vue.component定義組件,并且使用選擇器選擇模板Vue.component('com',{? ? template:'#temp'}) // 2. 使用template標簽定義模板,并且給template標簽添加id? ?
? ? ? ?

我是p元素

? ? ? ? 我是span元素? ?
// 3. 使用組件```### 私有組件的定義方式> 私有組件使用`components`屬性進行定義,該屬性可以定義在Vue實例內(nèi)部,也可以定義在組件內(nèi)部,私有組件一般也是其他組件的子組件```javascript// Vue實例的私有組件new Vue({? ? el:'#app',? ? data:{},? ? methods:{},? ? components:{? ? ? ? 'login': {? ? ? ? ? ? template:'
我是一個私有組件,只能使用在當(dāng)前#appVue實例托管區(qū)域內(nèi)部
'? ? ? ? }? ? }})// 組件的私有組件(子組件)? ?
? ? ? ? 我是賬號組件,我有兩個子組件login和register? ? ? ? ? ? ? ? ? ?
Vue.component('account',{? ? tempalte:'#account',? ? components:{? ? ? ? 'login':{? ? ? ? ? ? template:'
我是登錄組件,我的父組件是account
',? ? ? ? ? ? components:{? ? ? ? ? ? ? ? 'com':{? ? ? ? ? ? ? ? ? ? template:'
123
'? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? },? ? ? ? 'register':{? ? ? ? ? ? template:'
我是注冊組件,我的父組件是account
'? ? ? ? }? ? }})```### is屬性和component實現(xiàn)組件切換```// comname 是哪個組件名,則component就會被渲染成哪個組件// component 就是一個占位標簽 new Vue({? ? el:'#app',? ? comname:'login'})```### 父子組件傳值#### 父向子傳值```javascript// 1. 先在父組件中定義好要傳遞的數(shù)據(jù)new Vue({? ? el:'#app'? ? data:{? ? ? ? msg:'我是要傳遞給子組件的數(shù)據(jù)'? ? },? ? components:{? ? ? ? son:{? ? ? ? ? ? template:'
我是子組件{{message}}
',? ? ? ? ? ? props:['message']? ? ? ? }? ? }})// 2. 在父組件中使用子組件的時候,用綁定屬性的方式將父組件中的數(shù)據(jù)傳遞給子組件
? ?
// 3. 在子組件中定義一個props屬性,該屬性是一個數(shù)組,數(shù)組中定義用于接收傳過來的變量。這個變量// 和第二步綁定的這個屬性同名son:{? ? template:'
我是子組件
',? ? props:['message']}```#### 子向父傳值> 發(fā)布訂閱者 設(shè)計模式```javascript// 1. 定義好父子組件,定義好子組件需要傳遞給父組件的數(shù)據(jù)new Vue({? ? el:'#app'? ? components:{? ? ? ? son:{? ? ? ? ? ? template:'
我是子組件{{message}}
',? ? ? ? ? ? data:function(){? ? ? ? ? ? ? ? return {? ? ? ? ? ? ? ? ? ? msg:'傳給父組件的數(shù)據(jù)'? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? }})// 2. 在子組件中使用this.$emit觸發(fā)一個自定義的方法名,然后傳遞數(shù)據(jù)// 第一個參數(shù)就是自定義的方法名// 第二個參數(shù)就是需要傳遞給父組件的數(shù)據(jù)this.$emit('func',this.msg)// 3. 在父組件中使用子組件時,綁定一個事件,事件名稱和子組件觸發(fā)的方法名同名
? ?
// 4. 在父組件的methods中定義一個事件處理函數(shù)methods:{? ? getmsg:function(data){? ? ? ? // data就是子組件傳過來的數(shù)據(jù)? ? }}```### ref獲取DOM和組件對象```javascript// 1. 在DOM元素或者組件上面綁定ref屬性
我是一個div
// 2. 使用this.$refs.屬性值獲取對象引用this.$refs.mydiv // DOM對象this.$refs.mycom // 組件對象```## vur-router路由> **后端路由**: 服務(wù)端對前端請求的URL地址的監(jiān)聽,一個路由地址對應(yīng)一個資源> **前端路由**: 瀏覽器對前端頁面實現(xiàn)的跳轉(zhuǎn)方式,一般只在單頁應(yīng)用(SPA)程序中出現(xiàn)> router? route routes? 的區(qū)別是?- router: 是Vue實例內(nèi)部的一個屬性,是專門用來掛載vue-router對象的- route: 表示routers內(nèi)部的每一個路由對象的引用- routes: 是Vue-Router實例內(nèi)部的一個屬性,是用來保存所有的路由規(guī)則### 基本使用步驟```javascript1. 創(chuàng)建路由對象并配置路由規(guī)則// 1.1 創(chuàng)建組件模板對象var login = {? ? template:'
登錄
'}var register = {? ? template:'
注冊
'}// 1.2 創(chuàng)建路由對象并配置路由規(guī)則var router1 = new VueRouter({? ? // routes用來存放路由規(guī)則,每個路由規(guī)則都是一個對象? ? routes:[? ? ? ? // path: 頁面#后面的地址? ? ? ? // component 需要顯示的組件對象? ? ? ? {path:'/',redirect:'/login'},? ? ? ? {path:'/login',component:login},? ? ? ? {path:'/register',component:register}? ? ]})// 1.3 將創(chuàng)建處理的路由對象和Vue進行綁定new Vue({? ? el:'#app',? ? // 將vuerouter對象注冊到Vue內(nèi)部,以保證在托管區(qū)域中科院使用VueRouter內(nèi)部提供的組件以及其他屬性和方法? ? router:router1})2. 使用進行占位
? ? ?
3. 使用設(shè)置跳轉(zhuǎn)路徑登錄```### redirect重定向> 在路由規(guī)則中配置`redirect`屬性可以使路由進行內(nèi)部切換,當(dāng)訪問`path`中的路徑時,會默認跳轉(zhuǎn)到`redirect`中指定的路徑去。```JavaScript{path:'/',redirect:'/login'} // 當(dāng)訪問根路徑時,會默認跳轉(zhuǎn)到login路徑中```### linkActiveClass路由高亮> `linkActiveClass` 用來設(shè)置被激活路由的樣式類,默認類名是`router-link-active````JavaScriptnew VueRouter({? ? linkActiveClass:'mylink' // 被選中的路由對應(yīng)的標簽上面會有一個類名叫mylink})```### 路由傳參#### query傳參```JavaScript// 1. 在跳轉(zhuǎn)路徑后面使用查詢字符串拼接參數(shù)登錄// 2. 在路由對應(yīng)的組件內(nèi)部使用`this.$route.query`獲取參數(shù)this.$route.query.name // zsthis.$route.query.id // 18```#### params傳參```JavaScript// 1. 更改路由規(guī)則用于匹配參數(shù)new VueRouter({? ? routes:[? ? ? ? // :id用于匹配/login/13后面的參數(shù)13? ? ? ? {path:'/login/:id',component:login}? ? ]})// 2. 在跳轉(zhuǎn)路徑后面使用/拼接參數(shù)登錄// 3. 在路由對應(yīng)組件內(nèi)部使用`this.$route.params`獲取參數(shù)var login = {? ? template:'
登錄組件{{this.$route.params.id}}
',? ? created(){? ? ? ? console.log(this.$route.params.id) // 獲取到的就是13? ? }}```### 嵌套路由```JavaScript// 1. 在父路由內(nèi)部使用children屬性配置子路由規(guī)則,子路由規(guī)則對象中的path屬性不要 '/' // 2. 在父路由規(guī)則對應(yīng)的組件模板中添加router-view用于顯示子路由規(guī)則對應(yīng)的組件// 3. 在中設(shè)置跳轉(zhuǎn)路徑(將父路由和子路由的path拼接)```### 路由命名視圖> 給``添加name屬性,用于指定顯示哪一個組件```JavaScript// 1. 將路由規(guī)則對象中的component改為components,表示一個路由規(guī)則下可以顯示多個組件,每一個組件用一個名稱對應(yīng)起來,默認顯示的組件用default對應(yīng)new VueRouter({? ? routes:[? ? ? ? // components對象內(nèi)部按照 名稱 - 組件對象的方式定義? ? ? ? {path:'/',components:{? ? ? ? ? ? 'default': header,? ? ? ? ? ? 'left': leftBox,? ? ? ? ? ? 'main': mainBox? ? ? ? }}? ? ]})// 2. 給添加name屬性指定顯示哪一個組件? // 不指定默認顯示default對應(yīng)的組件 // 顯示leftBox組件 // 顯示mainBox組件```## watch的使用> `watch`: 用于監(jiān)聽data中定義的數(shù)據(jù)的變化,只要被監(jiān)聽的數(shù)據(jù)發(fā)生了變化,就會執(zhí)行對應(yīng)的處理函數(shù)### watch監(jiān)視數(shù)據(jù)變化```new Vue({? ? el:'#app',? ? data:{? ? ? ? msg:'hello'? ? },? ? watch:{? ? ? ? 'msg': function(newVal,oldVal){? ? ? ? ? ? // newVal 表示變化后的值 oldVal 表示變化前的值? ? ? ? ? ? // 只要data中定義的msg發(fā)生了改變,就會執(zhí)行這個函數(shù)? ? ? ? }? ? }})```### watch監(jiān)視路由變化> 通過監(jiān)聽`$route.path`可以監(jiān)視到路由地址的變化```javascriptnew Vue({? ? el:'#app',? ? watch:{? ? ? ? '$route.path': function(newVal,oldVal){? ? ? ? ? // newVal 新跳轉(zhuǎn)的路由地址? ? ? ? ? // oldVal 跳轉(zhuǎn)之前的路由地址? ? ? ? }? ? }})```## computed計算屬性> `computed`:計算屬性,是指在computed對象中定義屬性,屬性的值是該屬性后面函數(shù)的返回值,而且函數(shù)內(nèi)部如果用到了data中定義的其他數(shù)據(jù),只要這些數(shù)據(jù)發(fā)生了變化,都會重新觸發(fā)函數(shù)的執(zhí)行,計算屬性的值也會發(fā)生變化。```javascriptnew Vue({? ? el:'#app',? ? data:{? ? ? ? msg:'hello'? ? },? ? computed:{? ? ? ? 'info': function(){? ? ? ? ? ? // 只要msg發(fā)生了變化,會重新觸發(fā)該函數(shù)的執(zhí)行? ? ? ? ? ? // info的值就是函數(shù)的返回值? ? ? ? ? return this.msg + 'world'? ? ? ? }? ? },? ? methods:{},? ? watch:{}})```### watch 和 computed計算屬性的區(qū)別> watch可以對data中申明過的數(shù)據(jù)進行監(jiān)視,只要被監(jiān)視的數(shù)據(jù)發(fā)生了變化,就會觸發(fā)對應(yīng)函數(shù)> computed定義計算屬性,定義的屬性和在data中定義的使用方式一樣,但是computed中的屬性值是對應(yīng)函數(shù)的返回值,只要函數(shù)中依賴的其他數(shù)據(jù)發(fā)生了變化,會重新計算返回值### data、props、computed的區(qū)別> data中的相當(dāng)于申明變量,可以直接賦值也可以隨后賦值> props中數(shù)據(jù)是從其他組件傳遞得到> computed中的數(shù)據(jù)是通過計算得到,是屬性對應(yīng)函數(shù)的返回值,計算結(jié)果會被緩存- npm: node package manager node包管理工具- nrm: node registry manager node 鏡像地址管理工具- nvm: node version manager node 版本管理工具## webpack的學(xué)習(xí)> 什么是webpack? 一個基于Node的前端構(gòu)建工具,可以實現(xiàn)對項目的打包(構(gòu)建),主要解決文件(模塊)之間的依賴,高級代碼的轉(zhuǎn)譯,文件(模塊)的合并和壓縮等問題。### 基本使用 - `webpack3.~`版本安裝使用```JavaScript// 1. 全局安裝webpacknpm i webpack@3.10.0 -g// 2. 使用webpack 入口文件 輸出文件webpack ./src/main.js ./dist/build.js```- `webpack4.~`版本安裝使用```JavaScript// 1. 全局安裝webpacknpm i webpack? -gnpm i webpack-cli -g// 2. 使用webpack 入口文件 -o 輸出文件 --mode development/productionwebpack ./src/main.js -o ./dist/build.js --mode development```### webpack配置文件使用```javascript// 1. 在項目根目錄新建webpack.config.js,并設(shè)置 打包的入口文件 和 輸出文件module.exports = {? ? // 入口文件(絕對路徑)? ? entry: path.join(__dirname,'./src/main.js'),? ? // 輸出文件? ? output: {? ? ? ? path: path.join(__dirname,'./dist'), // 輸出文件目錄? ? ? ? filename: 'build.js' // 輸出文件名稱? ? }}// 2. 執(zhí)行打包命令webpack```### webpack-dev-server的使用> #### 命令行方式> `--hot`: 熱更新,可以局部更新文件> `--open`: 自動打開瀏覽器> `--port`: 配置端口號> `--contentBase`: 指定服務(wù)器目錄```javascript// 1. 局部安裝webpack-dev-server和webpacknpm i webpack-dev-server webpack --save-dev// 2. 在package.json的scripts節(jié)點中添加啟動命令"scripts":{? ? "dev":"webpack-dev-server --open --hot --contentBase --port 8888"}// 3. 在項目根目錄運行項目npm run dev```#### 配置文件方式```javascript// 1. 在webpack.config.js配置文件中添加如下配置devServer:{? ? open: true,? ? port: 8888,? ? contentBase: 'src',? ? hot: true}// 2. 如果設(shè)置了 hot:true 這個屬性,則需要配置熱更新插件// 2.0 引入webpack模塊const webpack = require('webpack')// 2.1 配置熱更新插件plugins: [? ? new webpack.HotModuleReplacementPlugin()]// 3. package.json中配置啟動命令"scripts":{? ? "dev":"webpack-dev-server"}```### `html-webpack-plugin`的使用> 可以根據(jù)指定的HTML模板文件生成一個HTML頁面,并且在HTML頁面中自動引入打包好的js文件```javascript// 1. 安裝html-webpack-pluginnpm i html-webpack-plugin --save-dev// 2. 在webpack.config.js中的plugins節(jié)點中配置插件// 2.1 導(dǎo)入html-webpack-pluginconst htmlWebpackPlugin = require('html-webpack-plugin')// 2.2 配置插件plugins:[? ? new htmlWebpackPlugin({? ? ? ? template:path.join(__dirname,'./src/index.html'),// 需要生成的HTML的模板文件? ? ? ? filename:'index.html' // 生成的HTML文件的名稱? ? })]```### `css-loader`處理CSS文件> 解析處理文件后綴名為.css的文件```javascript// 1. 安裝style-loader css-loadernpm i style-loader css-loader --save-dev// 2. 在webpack.config.js中的moudle節(jié)點中配置解析規(guī)則module:{? ? rules:[? ? ? ? {? ? ? ? ? ? test:/\.css$/,? ? ? ? ? ? use:['style-loader','css-loader']? ? ? ? }? ? ]}```### `less-loader`處理less文件> 解析處理文件后綴名為.less的文件```javascript// 1. 安裝less less-loadernpm i less less-loader --save-dev// 2. 在webpack.config.js中的moudle節(jié)點中配置解析規(guī)則module:{? ? rules:[? ? ? ? {? ? ? ? ? ? test:/\.less$/,? ? ? ? ? ? use:['style-loader','css-loader','less-loader']? ? ? ? }? ? ]}```### `scss-loader`處理scss文件> 解析處理文件后綴名為.scss的文件```javascript// 1. 安裝node-sass sass-loadernpm i node-sass sass-loader --save-dev// 2. 在webpack.config.js中的moudle節(jié)點中配置解析規(guī)則module:{? ? rules:[? ? ? ? {? ? ? ? ? ? test:/\.scss$/,? ? ? ? ? ? use:['style-loader','css-loader','sass-loader']? ? ? ? }? ? ]}```### `url-loader`處理圖片等資源文件> 解析處理項目中引入的圖片、字體圖標、音視頻等資源文件```javascript// 1. 安裝file-loader ulr-loadernpm i file-loader ulr-loader --save-dev// 2. 在webpack.config.js中的moudle節(jié)點中配置解析規(guī)則module:{? ? rules:[? ? ? ? {? ? ? ? ? ? test:/\.(png|jpg|gif)/,? ? ? ? ? ? use:'url-loader?limit=20000&name=[hash:8]-[name].[ext]'? ? ? ? ? ? // 當(dāng)需要打包的文件小于limit的值,會將圖片轉(zhuǎn)換成base64字符串在build.js中進行引用? ? ? ? ? ? // 當(dāng)需要打包的文件大于limit的值,會將圖片打包到輸出目錄中? ? ? ? ? ? //一般比較小的圖片才需要被轉(zhuǎn)成base64,所以該值不宜太大? ? ? ? ? ? // name=[hash:8]-[name].[ext]表示將來打包出來的文件名稱以8位hash值和原來的名稱進行拼接,文件擴展名不變? ? ? ? }? ? ]}```### `babel`的使用> 解析webpack默認不能處理的JS```JavaScript// 1. 安裝babel-core babel-loader babel-plugin-transform-runtimenpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev// 2. 安裝babel-preset-env babel-preset-stage-0npm i babel-preset-env babel-preset-stage-0 --save-dev// 3. 在webpack.config.js中的moudle節(jié)點中配置解析規(guī)則module:{? ? rules:[? ? ? ? {? ? ? ? ? ? test:/\.js$/,? ? ? ? ? ? use:'babel-loader',? ? ? ? ? ? exclude:/node_modules/ //排除掉node_modules文件夾,讓babel-loader不去解析node_modules文件夾中的js文件? ? ? ? }? ? ]}// 4. 在項目根目錄新建.babelrc文件,書寫如下配置{? ? "presets":["env","stage-0"],? ? "plugins":["transform-runtime"]}```## webpack中使用Vue```JavaScript// 1. 安裝vue vue-loader vue-template-compilernpm i vue --savenpm i vue-loader vue-template-compiler --save-dev// 2. webpack.config.js中配置解析規(guī)則module: {? ? rules: [? ? ? ? {? ? ? ? ? ? test:/\.vue$/,use:'vue-loader'? ? ? ? }? ? ]}// 3. 在index.html中加入一個需要Vue托管的區(qū)域
// 4. 新建App.vue組件? ?
vue組件
export default {}// 5. main.js中導(dǎo)入vue的包,渲染App.vue組件import Vue from 'vue'import App from './App.vue'new Vue({? ? el:'#app',? ? render:c=>c(App) //將App組件渲染到id為app的區(qū)域中})```## webpack 中集成vue-router```JavaScript// 1. 安裝vue-routernpm i vue-router --save// 2. 在main.js中導(dǎo)入vue-router并實例化路由添加路由規(guī)則import VueRouter from 'vue-router'Vue.use(VueRouter) // 保證在vue的組件中可以使用vue-router提供的組件 如const router = new VueRouter({? ? routes: [? ? ? ? {? ? ? ? ? ? path: '/login', component: login? ? ? ? }? ? ]})// 3. 將實例化的router綁定到Vuenew Vue({? ? el: '#app',? ? render: c => c(App),? ? router // 將router實例綁定到Vue上 以保證vue實例中可以訪問$route $router等屬性})// 4. 在App.vue中添加路由占位router-view標簽登錄```--- ## --save和--save-dev```// 項目開發(fā)期間需要安裝的依賴// --save-dev 會將安裝的包名以及版本號記錄到package.json文件中的devDependencies節(jié)點中npm install webpack --save-dev 等價于 npm install webpack -D// 項目上線后需要安裝的依賴// --save 會將安裝的包名以及版本號記錄到package.json文件中的dependencies節(jié)點中npm i webpack --save 等價于 npm i webpack -Snpm i 會將所有在package.json文件中的devDependencies節(jié)點和dependencies節(jié)點內(nèi)所有的依賴包全部安裝一遍npm i --save-dev 只會下載devDependencies中的所有依賴包npm i --save 只會下載dependencies中的所有依賴包// 為什么安裝包的時候要區(qū)分 --save 和 --save-dev// 1. 使項目的閱讀更加友好,便于理解項目結(jié)構(gòu)// 2. 安裝對應(yīng)階段的包時更加方便npm i cnpm -gcnpm ```## VSCode用戶代碼片段```json"Print to vue": {"prefix": "vuec","body": ["","? ? ? ? ? ","",

"export default{",

"? ? $2? ? ? ? ",

"}",

"","",

"$3? ? ? ? ? ? ",

""],"description": "create a vue template"}```## yarn的使用```// 1. 使用npm全局安裝yarnnpm i yarn -g// 2. 初始化命令yarn init -y// 3. 安裝包yarn add package-name // 會將安裝的包記錄到dependencies節(jié)點里面yarn add package-name --dev // 會將安裝的包記錄到devDependencies節(jié)點里面yarn global add package-name // 安裝全局包// 4. 刪除包yarn remove package-name// 5. 執(zhí)行命令yarn run devyarn global bin 查看全局包安裝的路徑```## vue-cli腳手架的使用```// 1. 安裝vue-cli腳手架npm i vue-cli -g// 2. 初始化項目模板vue init webpack 項目名稱eslint(語法規(guī)范化插件) 不要安裝? 當(dāng)安裝之后只能按照ESLint中規(guī)定的語法格式去書寫代碼e2e(測試框架) 不要安裝unit test(單元測試框架) 不要安裝// 3. 進入項目安裝所有依賴npm i// 4. 運行npm run devconfig/index.js中 17/18行改端口號和自動打開瀏覽器```## 將項目提交到碼云```// 1. 在項目文件夾初始化gitgit init// 2. 將代碼提交到暫存區(qū)git add .// 3. 提交代碼git commit -m '描述信息'// 4. 關(guān)聯(lián)遠程分支git remote add origin https://gitee.com/UniverseKing/tes.git// 5. 推送到遠程分支git push -u origin master// 6. 查看文件信息git status// 7. 查看loggit log --oenline// 8. 切換版本記錄git reset --hard 版本號```## vue-loader深度作用選擇器> 如果希望在父組件中去改變子組件中的樣式,有時候通過普通子類選擇器無法實現(xiàn),主要是由于添加了`scoped`屬性導(dǎo)致,`vue-loader`中提供了[深度作用選擇器](https://vue-loader.vuejs.org/zh-cn/features/scoped-css.html)可以實現(xiàn)> 這種問題主要出現(xiàn)在使用第三方組件時,需要改第三方組件的樣式時```CSS/*假設(shè).content是父組件中的類 img是子組件中的標簽*//*css中使用>>>*/.content >>> img {}/*scss或者less中使用/deep/*/.content /deep/ img {}```## Promise> `Promise` 是異步編程的一種解決方案.簡單說就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。從語法上說,`Promise` 是一個對象,可以從該對象獲取異步操作的消息。```Promise有幾種狀態(tài)?Promise有三種狀態(tài)promsie實例一被創(chuàng)建? 默認就是pending狀態(tài)(表示異步操作進行中)如果異步操作成功 狀態(tài)會從 pending 變成 fulfilled(表示異步操作成功)如果異步操作失敗 狀態(tài)會從 pending 變成 rejected(表示異步操作失敗)```### 基本用法```js// 1. 創(chuàng)建promise實例,在實例中執(zhí)行異步操作(比如發(fā)送網(wǎng)絡(luò)請求)// 2. 異步操作成功時,調(diào)用reslove函數(shù)傳遞數(shù)據(jù)// 3. 異步操作失敗時,調(diào)用reject函數(shù)傳遞錯誤信息const promise = new Promise(function(resolve, reject) {// 異步操作// ... if (/* 異步操作成功 */){resolve(value);} else {reject(error);}});// 4. 使用promise實例then方法接收reslove或reject返回的數(shù)據(jù)promise.then(function(value) {// 此處數(shù)據(jù)即為reslove回來的數(shù)據(jù)? // success}, function(error) {// 此處數(shù)據(jù)即為reject回來的數(shù)據(jù)// failure});```### 網(wǎng)絡(luò)請求案例```js// 1. 定義一個使用promise封裝的請求函數(shù),函數(shù)內(nèi)部返回一個promise實例function fetch(){// 函數(shù)內(nèi)部返回一個promise實例return new Promise(function(reslove,reject){// 發(fā)送異步請求axios.get('http://www.lovegf.cn:8090/api/getlunbo').then(function(res){// 請求正常if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}// 2. 調(diào)用函數(shù)發(fā)送請求,通過Promise.prototype.then方法獲取resolve或reject出來的數(shù)據(jù)fetch().then(function(res){// res為reslove函數(shù)傳出的數(shù)據(jù)},function(err){// err為reject函數(shù)傳出的錯誤})```### 解決回調(diào)地獄> 假設(shè)有三個請求A、B、C,B請求需要依賴A請求的數(shù)據(jù),C請求需要依賴B請求的數(shù)據(jù).> > 傳統(tǒng)回調(diào)函數(shù)式寫法如下:```jsfunction dependices_fetch(){// A請求axios.get('A').then(function(res){if(res.status == 1){// B請求axios.get('B').then(function(res){if(res.status == 1){// C請求axios.get('C').then(function(res){// 請求完畢,執(zhí)行后續(xù)邏輯})}})}})}```> 這種代碼雖然能夠滿足業(yè)務(wù),但是代碼組織結(jié)構(gòu)非常不便于閱讀> > 通過Promise可以封裝代碼,使用鏈式方式解決這種多個異步依賴的回調(diào)> > 如下:```jsfunction fetch(url){return new Promise(function(reslove,reject){axios.get(url).then(function(res){if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}//then方法內(nèi)部返回的promise實例reslove或reject出來的對象會在下一個then方法內(nèi)部得到fetch('A').then(function(res){// A 請求正常return fetch('B')// 這里返回一個新的promise實例,在后面的then中可以得到該實例reslove或reject出來的對象}).then(function(res){// B 請求正常return fetch('C')}).then(function(res){// C 請求正常// 請求完畢})```### 多個異步請求結(jié)果組合問題> 假設(shè)有A、B、C三個異步請求,需要三個請求的數(shù)據(jù)都回來之后,將數(shù)據(jù)整合后再渲染頁面,這種需求可以使用`Promise.all()`> > Promise.all方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。```jsfunction fetch(url){return new Promise(function(reslove,reject){axios.get(url).then(function(res){if(res.status == 1){reslove(res.data)}else{reject(res.error)}})})}const p1 = fetch('A')const p2 = fetch('B')const p3 = fetch('C')const p = Promise.all([p1, p2, p3]);p.then(function(res){// res是一個數(shù)組,存放著p1,p2,p3的返回值})```## async 和 await 的使用> async 和 await 是ES7中新提供的兩個操作異步函數(shù)的關(guān)鍵字,本質(zhì)是對Promise進一步的封裝> await 只能用在 async 定義的函數(shù)內(nèi)部,await 可以等待異步操作,并同步的得到異步操作的返回值```JavaScript// 1. 基于Promise的異步操作函數(shù)const fs = require('fs')function getFileByPath(fpath) {? ? return new Promise(function (resolve, reject) {? ? ? ? fs.readFile(fpath, 'utf-8', (err, dataStr) => {? ? ? ? ? ? if (err) return reject(err)? ? ? ? ? ? resolve(dataStr)? ? ? ? })? ? })}// 2. 基于 await 的異步依賴問題(異步操作3依賴異步操作2,異步操作2依賴異步操作1)// 2.1 先使用async定義異步操作const start = async function(){// 2.2 在async內(nèi)部使用await 同步操作? ? ? ? const n1 = await getFileByPath('./1.txt')? ? const n2 = await getFileByPath('./2.txt')? ? const n3 = await getFileByPath('./3.txt')? ? // n3會等待n2 n2 會等待n1}```## axios 使用```JavaScript1. 安裝axiosnpm i axios qs --save2. 在main.js中導(dǎo)入axios,并將axios 掛載到Vue的原型中improt axios from 'axios'Vue.prototype.$axios = axios 3. get請求this.$axios.get('url').then(function(res){? ? // 注意:? ? // 1. 響應(yīng)的數(shù)據(jù)在res.data中? ? // 2. 在回調(diào)函數(shù)內(nèi)部的this 不是Vue實例(通常會將這個回調(diào)函數(shù)改成箭頭函數(shù))})4. post 請求// 注意:當(dāng)后臺要求傳遞的參數(shù)數(shù)據(jù)格式是 application/x-www-form-urlencode// 需要對參數(shù)進行序列化// 使用qs模塊序列化qs.stringify({name:'zs',age:18})// 如果后臺要求的參數(shù)格式 是json格式 appliction/json 不需要序列化this.$axios.post('url',qs.stringify({name:'zs',age:18})).then(res=>{})5. 全局配置// 5.1 設(shè)置全局的請求根域名axios.defaults.baseURL = 'http://vue.studyit.io/';// 5.2 通過設(shè)置請求攔截器 配置post參數(shù)序列化axios.interceptors.request.use(function (config) {? ? // 統(tǒng)一處理post請求的參數(shù) 為application/x-www-form-urlencode? ? if (config.method == 'post') {? ? ? ? config.data = qs.stringify(config.data)? ? }? ? return config;});```## Vue插件開發(fā)```JavaScript1. 單獨新建一個JS文件,在這個文件中導(dǎo)入需要制作成Vue插件的模塊import axios from 'axios'2. 在該模塊身上定義一個install函數(shù),可以接受兩個參數(shù),第一個用于接收Vue構(gòu)造函數(shù)第二個用于配置插件的一些選項axios.install = function(Vue,config){? ? // 1. 注冊全局組件? ? // 2. 將屬性掛載到原型中}3. 導(dǎo)出制作好的Vue插件模塊export default axios4. 使用插件// 能夠使用Vue.use的前提就是傳入的對象一定要有install方法// 調(diào)用Vue.use()的時候 會自動去調(diào)用 傳入對象的 install方法import axios from '插件路徑'Vue.use(axios) // 會自動調(diào)用axios的install方法```## 去除webpack打包后的嚴格模式> 在使用babel-loader的時候,會將所有轉(zhuǎn)換的代碼加上嚴格模式```JavaScript// 方法一: .babelrc文件中忽略不需要使用嚴格模式轉(zhuǎn)換的文件路徑 "ignore": [? ? "./src/js/mui/mui.min.js"? ]// 方法二: babel-loader配置中排除掉不需要嚴格模式轉(zhuǎn)換的文件{? ? test: /\.js$/,? ? use: 'babel-loader',? ? exclude: /mui\.min\.js/}// 方法三: babel-plugin-transform-remove-strict-mode 移除整個項目打包編譯時的嚴格模式// https://www.npmjs.com/package/babel-plugin-transform-remove-strict-mode1. 安裝babel-plugin-transform-remove-strict-modenpm install babel-plugin-transform-remove-strict-mode --save-dev2. babelrc中添加{? "plugins": ["transform-remove-strict-mode"]}```## 路由模式> 通過給`vue-router`配置`mode`屬性,可以指定URL路徑的顯示方式> `mode`屬性默認值是`hash`,此時URL中有#,如:`http://localhost:8888/#/home`,實現(xiàn)方式即`window.location.hash`> 如果`mode`設(shè)置成`history`,此時URL路徑?jīng)]有#,如:`http://localhost:8888/home`,實現(xiàn)方式為`window.history`,這種方式同一個URL不能再其他頁面打開,需要服務(wù)端配置```JavaScriptnew VueRouter({? ? mode:'hash',? ? routes:[? ? ]})```## Vuex的使用> Vuex是一個狀態(tài)管理庫,或者說是專為Vue應(yīng)用程序開發(fā)設(shè)計的狀態(tài)管理模式,它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。> 注:所謂狀態(tài),可以理解成項目中各個組件需要用到的數(shù)據(jù)。> Demo:https://gitee.com/UniverseKing/vuex-study### 初始化公共狀態(tài)``` JavaScript1. 安裝vuexnpm i vuex --save2. 入口文件中實例化Storeimport Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({? // 1. 用于定義狀態(tài)(公共數(shù)據(jù)),類似于Vue實例中的data方法? state:{? ? ? msg:'初始化的數(shù)據(jù)'? },? // 2. 用于修改狀態(tài),類似于Vue實例中methods? mutations:{? ? ? change(state,arg){? ? ? ? ? // 更改狀態(tài)? ? ? ? ? state.msg = arg? ? ? }? },? // 3. 用于獲取數(shù)據(jù)(獲取數(shù)據(jù)之前可以進行一些操作),類似于Vue實例中的過濾器和計算屬性? // getters 主要會用在跨組件傳值? // getters 中定義的方法內(nèi)部依賴的數(shù)據(jù)發(fā)生變化會自動重新調(diào)用函數(shù)計算返回值? getters:{? ? ? fixmsg(state){? ? ? ? ? return `${state.msg}----處理后的數(shù)據(jù)`? ? ? }? },? // 4. actions和mutations都是定義對數(shù)據(jù)進行操作的方法,mutations中都是同步方法,mutations中定義異步方法? // Action 提交的是 mutation,而不是直接變更狀態(tài)。所以需要修改狀態(tài)還是需要使用mutations中定義的方法? // 從網(wǎng)絡(luò)請求回來的數(shù)據(jù)需要保存到store? // 發(fā)送網(wǎng)絡(luò)請求的方法可以定義到actions中? // actions主要用于處理異步方法? actions:{? ? ? asyncchange(context,arg){? ? ? ? ? // 異步方法? ? ? ? ? setTimeout(() => {? ? ? ? ? ? ? context.commit('change',arg)? ? ? ? ? }, 3000)? ? ? }? }})3. 注入到Vue實例中new Vue({? ? el:'#app',? ? store})```### 使用狀態(tài)``` JavaScript1. 使用state中的數(shù)據(jù)JavaScript: this.$store.state.msgHTML: $store.state.msg2. 使用getters中的數(shù)據(jù)JavaScript: this.$store.getters.fixmsgHTML: $store.getters.msg```### 變更狀態(tài)(修改數(shù)據(jù))> 狀態(tài)的變更必須使用mutations中提供的方法進行修改``` JavaScript1. 提交mutations中的變更方法this.$store.commit('change','我是被修改的數(shù)據(jù)')2. 異步提交actions中的變更方法this.$store.dispatch('asyncchange','我是被異步修改的數(shù)據(jù)')```### 使用輔助函數(shù)> 輔助函數(shù)可以直接將`state`,`getters`中的數(shù)據(jù)映射到Vue組件中的計算屬性上,可以將`mutations`,`actions`中的方法映射到組件中的`methods`中``` JavaScriptimport { mapState } from 'vuex'import { mapGetters } from 'vuex' import { mapMutations } from 'vuex'import { mapActions } from 'vuex'new Vue({? ? computed:mapGetters([? ? ? ? 'count'? ? ])})// ==>等價于new Vue({? ? computed:{? ? ? ? count(){? ? ? ? ? ? return this.$store.state['count']? ? ? ? }})```## vue-cli配置代理解決開發(fā)階段跨域問題```JavaScript// webpack.config.js配置文件導(dǎo)出對象中加入 devServer:{? ? // 代理跨域? ? proxy: {? ? ? '/api': {? ? ? ? target: 'http://vue.studyit.io/api', // 需要被代理的api根域名? ? ? ? changeOrigin: true, // 是否跨域? ? ? ? pathRewrite: {? ? ? ? ? '^/api': '' // 重寫(target中只有根域名時不需要配置此選項)? ? ? ? }? ? ? }? ? }? }---------------------------// vue-cli中config/index.js中proxyTable: {? ? '/api': {? ? ? ? target: 'http://vue.studyit.io/api',? ? ? ? changeOrigin: true,? ? ? ? pathRewrite: {? ? ? ? ? '^/api': ''? ? ? ? }? ? }},```## webpack打包優(yōu)化> 目前項目中所有資源都會被打包到最終生成的一個build.js中,而build.js又被引用到index.html中,當(dāng)打開index.html時,首先需要從互聯(lián)網(wǎng)下載build.js,只有build.js全部下載完畢,瀏覽器的解析引擎才會開始執(zhí)行該js代碼進行代碼解析,當(dāng)解析引擎將代碼解析完畢后再交給渲染引擎開始進行渲染,所有工作幾乎都是同步執(zhí)行,當(dāng)build.js體積非常大時,往往應(yīng)用的首頁加載速度比較慢,而且會看到白屏效果.可以從以下三方面進行優(yōu)化首頁加載速度過慢問題:1. 下載文件速度慢2. 解析JS比較慢3. 渲染比較慢### 服務(wù)端渲染(SSR)> SEO優(yōu)化> 在服務(wù)端先將JS進行解析,解析完成之后生成HTML片段,再將HTML返回給前端,前端直接執(zhí)行渲染界面### 抽取CSS> 將項目中所有CSS抽取到單獨的文件中進行加載,減小了build.js的體積,只要build.js下載完成即可開始解析代碼> https://github.com/webpack-contrib/extract-text-webpack-plugin```JavaScript1. 安裝插件npm install extract-text-webpack-plugin --save-dev2. webpack.config.js中引入插件var ExtractTextPlugin = require('extract-text-webpack-plugin');3. 修改css-loader配置{? ? test: /\.css$/,? ? use: ExtractTextPlugin.extract({? ? ? ? fallback: "style-loader",? ? ? ? use: "css-loader"? ? })},{? ? test: /\.less$/,? ? use: ExtractTextPlugin.extract({? ? ? ? fallback: 'style-loader',? ? ? ? use: ['css-loader', 'sass-loader']? ? })}, // 處理 less 文件的 loader{? ? test: /\.scss$/,? ? use: ExtractTextPlugin.extract({? ? ? ? fallback: 'style-loader',? ? ? ? use: ['css-loader', 'sass-loader']? ? })}4. plugin配置中使用插件new ExtractTextPlugin('app.css')```### 分離第三方包> 將項目中引用的第三方JS代碼抽取到一個單獨的文件,也可以減少build.js的體積,還是只需要build.js下載完畢瀏覽器解析引擎即可開始進行解析,然后瀏覽器同時再去下載其他JS和CSS> 一般將發(fā)布階段所需要依賴的包全部進行分離,即`package.json`中`dependencies`中的所有包進行分離```JavaScript 1. 引入webpack和路徑處理模塊var webpack = require('webpack');var path = require('path');2. 修改入口文件entry: {? ? app: path.resolve(__dirname, 'src/main.js'),? ? // 需要分離的第三方包名寫在數(shù)組中? ? vendors: ['vue', 'vue-resource', 'vue-router', 'vuex', 'mint-ui', 'moment', 'vue-preview']},3. plugin中配置插件// 分離第三方包插件new webpack.optimize.CommonsChunkPlugin({? ? name: 'vendors',? ? filename: 'vendors.js' // 分離出來的js文件的名稱})```### 組件按需加載> vue-router提供的路由懶加載可以按需加載組件。> 特點: 當(dāng)沒有訪問到某個頁面路由時,不去加載對應(yīng)的組件代碼,節(jié)約數(shù)據(jù)請求量,加快首頁DOM渲染速度```將import home from './components/Home.vue' 這種導(dǎo)入方式換成const home = () => import('../components/Home.vue');```## 路由導(dǎo)航鉤子函數(shù)> 在跳轉(zhuǎn)路由時,進行攔截,一般用于權(quán)限驗證或登錄等操作> https://router.vuejs.org/zh-cn/advanced/navigation-guards.html### 路由獨享守衛(wèi)```JavaScriptconst router = new VueRouter({? routes: [? ? {? ? ? path: '/home',? ? ? component: HomeContainer,? ? ? // 進入路由之前進行攔截? ? ? beforeEnter: (to, from, next) => {? ? ? ? // from 從哪個路由來? ? ? ? // to 到哪個路由去? ? ? ? // 釋放守衛(wèi) 進入下一個環(huán)節(jié)? ? ? }? ? }? ]})```### 全局守衛(wèi)```JavaScriptrouter.beforeEach((to, from, next) => {? })```## Cmder使用> window系統(tǒng)下增強型命令行工具,免安裝,解壓即用```JavaScript// 1. 將cmder.exe加入環(huán)境變量1. window + R 輸入 sysdm.cpl2. 選中 高級 - 環(huán)境變量 - 系統(tǒng)變量 - Path3. 將cmder.exe所在目錄添加到Path中// 2. 天假右鍵菜單在cmder.exe所在目錄打開命令行窗口 輸入 Cmder.exe /REGISTER ALL```## HBuilder打包> HBuilder打包 是將前端開發(fā)的HTML/CSS/JS文件進行打包,打包成可以直接安裝在手機上面的App,不借助瀏覽器就可以直接運行```JavaScript1. 使用webpack將項目進行打包,打包好的文件會在dist目錄webpack -p2. 打開Hbuilder,新建移動App項目,然后刪掉css/js/imgs文件夾和index.html文件3. 將使用webpack打包的dist目錄里面的文件全部拷貝到新建的移動項目目錄中4. 選中HTML文件,點擊HBuilder導(dǎo)航上面的`發(fā)行`-`打原生安裝包`,直接下一步,選安卓公共證書-`打包`5. 在項目的`unpackage\release`中可以得到打包完畢的apk文件```## cordova打包> 直接在本地進行打包> 需要電腦配置Java環(huán)境和Android環(huán)境 `gradle````JavaScript// 1. 安裝全局cordovanpm i cordova -g// 2. 創(chuàng)建cordova項目cordova create cordova_project// 3. 添加需要打包的平臺cordova platform add android// 4. 運行或者打包cordova run androidcordova build android```## vue-cli打包完成后1. 錯誤信息:`postcss-svgo: Error in parsing SVG: Unquoted attribute value`? ? - 需要修改mui.css中的 **圖片引用** 單引號全部改成雙引號2. 提示必須使用服務(wù)器的方式打開,即使用localhost方式打開? ? ? ? // 1. 安裝http-server? ? ? ? npm i http-server -g? ? ? ? // 2. 使用hs -o命令打開index.html文件? ? ? ? hs -o3. 如果打包完成后希望直接用file協(xié)議打開,需要修改config/index.js 中的build下的`assetsPublicPath: '/'`換成`assetsPublicPath: './'`## Parcel使用```JavaScriptnpm i parcel-bundler -gparcel index.html```----> 項目地址:https://gitee.com/UniverseKing/vue_cms> [Vue組件](https://github.com/UniverseKing/awesome-github-vue#%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B)## MVC 和 MVVM 區(qū)別> MVC從后臺業(yè)務(wù)邏輯對項目進行分層開發(fā) 數(shù)據(jù)流通是單向的,所有的數(shù)據(jù)流通都需要C進行控制> MVVM是前端框架的一種設(shè)計模式,核心是雙向數(shù)據(jù)綁定,M和V可以直接進行通信,VM只負責(zé)數(shù)據(jù)的綁定## 你平時開發(fā)項目,有沒有遇到比較難的問題,是怎么解決的?- vue-loader 深度作用選擇器(父組件中不能給v-html渲染出來的標簽添加樣式)- babel-loader在編譯代碼時,會給所有的代碼加上嚴格模式,不能使用call,callee,arguments..## 項目接口:> http://www.escook.cn:3000/> http://www.lovegf.cn:8899/## 真機調(diào)試```1. 手機開一個WiFi熱點2. 使用電腦連接手機的WiFi熱點3. 在電腦上打開CMD命令行 輸入ipconfig命令 查看的IP地址是 無線局域網(wǎng)下面的ipv4地址4. 在項目中使用--host IP地址 重啟項目5. 在手機中訪問項目的IP地址```

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內(nèi)容

  • 1.基本綁定: new Vue( { el:'#elID', data:{ ...
    寒劍飄零閱讀 542評論 0 1
  • VUE介紹 Vue的特點構(gòu)建用戶界面,只關(guān)注View層簡單易學(xué),簡潔、輕量、快速漸進式框架 框架VS庫庫,是一封裝...
    多多醬_DuoDuo_閱讀 2,725評論 1 17
  • Vue筆記六:Vue項目的性能優(yōu)化之路 我最近也經(jīng)常面試外包同事。面試的時候,總會有個問題,“你說一下性能優(yōu)化的手...
    brandonxiang閱讀 6,835評論 5 22
  • 最近出現(xiàn)了一個好玩的App,是果殼網(wǎng)旗下在行的分答,用戶可以在上面自我介紹或描述擅長領(lǐng)域,設(shè)置付費問答的價格,其他...
    大禹小漁閱讀 557評論 1 2
  • 【彭姐原創(chuàng)感悟013】 人真的有時候很賤,想給自己一點寬松的享受,結(jié)果還不受用。 昨天我開始按我計劃的...
    739921988403閱讀 246評論 0 0