vue筆記整理與總結

Vue

1、 簡介:(爲何使用vue)

一、 與angular相比優勢:

a) api簡單,快速上手,學習成本低;
b) Angular 使用雙向綁定,Vue 也支持雙向綁定,不過爲單向數據流,數據從父組件單向傳給子組件;
c) Vue.js 中指令和組件分得更清晰。指令只封裝 DOM 操做,而組件表明一個自給自足的獨立單元 —— 有本身的視圖和數據邏輯。在 Angular 中二者有很多相混的地方
d) Angular的髒檢查機制,形成了若是項目龐大以後性能下降問題;每一次更新數據,都致使全部的數據綁定,進行一次遍歷;
Vue的數據變化更新是根據依賴追蹤的觀察系統而且異步列隊去更新,數據變化都是獨立的觸發隊列中相應的事件;
e) 渲染層建立了虛擬dom(輕量級,2.0),減小了內存開銷和加快了渲染速度;
f) 組件式開發,每一個組件都具備生命週期,便於本身狀態的維護;實現了代碼的高複用性;php

二、 與react相比:

λ 共同點:
a) 使用 Virtual DOM
b) 提供了響應式(Reactive)和組件化(Composable)的視圖組件
c) 將注意力集中保持在覈心庫,而將其餘功能如路由和全局狀態管理交給相關的庫
λ 優點:
″ 性能:
a) vue的更新渲染過程是自動追蹤的,而react若是想要提升更新的性能須要經過shouldComponentUpdate鉤子函數對數據進行對比;
b) 對於組件的語法,在vue中既能夠支持jsx語法,將css和html都寫入js文件中,又可使用template模板進行編譯,在vue中推薦使用template模板進行編譯,減小學習成本,更加符合前端開發語法;而react僅僅支持jsx語法,jsx的優勢:1、開發工具對jsx的支持比其餘的vue模板更先進;
c) 對於css的支持:
vue中能夠直接在style中寫css語法,能夠支持媒體查詢,等等一切css屬性,而且能夠經過scoped進行組件做用域的封閉;
react的組件中若是進行css樣式的隔離,只能寫入js文件中,比較簡單的樣式能夠進行支持,可是若是比較複雜的則沒法支持;
″ 規模:
共同點:
都提供了路由和狀態管理機制;
都有本身的自動化構建工具;
不一樣點:
react的學習成本比較高,須要掌握jsx語法和es2015;雖然支持前端babel進行編譯,可是不適合生產環境;
vue向下擴展能夠像jq那樣使用在前端項目中,向上擴展能夠像react同樣進行前端的自動化構建;
″ 本地渲染:(跨平臺)
reactNative
weexcss

三、 總結vue:

優勢:
a) MVVM的開發模式,從dom中解脫出來,雙向數據綁定;
b) 數據更新採用異步事件機制;
c) 採用單向數據流;
d) 組件式開發;
e) 採用虛擬dom
f) 支持模板和jsx兩種開發模式;
g) 能夠進行服務端渲染;
h) 擴展性強,既能夠向上又能夠向下擴展
缺點:
a) 不兼容IE8如下版本
b) 生態圈不繁榮,開源社區不活躍;html

2、 安裝與使用:

一、 直接使用CDN引入:

<script src="https://unpkg.com/vue&quot;></script>前端

二、 下載到本地:

https://vuejs.org/js/vue.js

三、 自動化構建工具:

Vue.js 有一款官方的腳手架生成工具 vue-cli:vue

λ 全局安裝
npm install –g vue-clijava

λ 建立項目
vue init webpack myprojectnode

λ 安裝依賴包
npm installreact

λ 目錄以下:
build: 用於存放 webpack 相關配置和腳本。
config: 主要存放配置文件,用於區分開發環境、測試環境、線上環境的不一樣。
src: 項目源碼及須要引用的資源文件。
static: 不須要 webpack 處理的靜態資源。
test: 用於存放測試文件;
λ 啓動服務:
正常開發時,就會運行命令npm run dev,啓動一個小型的express 服務。在這個 express 服務中,會使用webpack-dev-middleware 和 webpack-hot-middleware 這兩個 中間件,來進行項目的熱部署,即每次修改 src 中的文件後,不須要再按瀏覽器的刷新來更新 代碼,啓動的 server 服務會自動監聽文件的變化並編譯,通知瀏覽器自動刷新。
λ 分析packjson文件:webpack

"scripts": {
    "dev": "node build/dev-server.js",
    "start": "node build/dev-server.js --open",
    "build": "node build/build.js",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run e2e",
    "lint": "eslint --ext .js,.vue src test/e2e/specs"
  },

dev:爲本地開發的啓動項;
start:和dev同樣;
build:打包線上部署代碼
e2e:這個表明端對端測試,確切的來講就是前端的一個自動化測試;這裏使用的是java的nightwatch自動化測試工具,使用測試須要進行java的全局安裝es6

3、 實例:

一、一個 Vue 實例其實正是一個 MVVM 模式中所描述的 ViewModel - 所以在文檔中常常會使用 vm 這個變量名。
二、在實例化 Vue 時,須要傳入一個選項對象,它能夠包含數據、模板、掛載元素、方法、生命週期鉤子等選項 ;
(1)模板:

三個屬性:template、el、replace(2.0)已經刪除,規定template中必須有個根節點;
  Replace:爲true時不會保留原dom節點,直接將原節點替換,若是是false則,保留原節點

(2)數據:

能夠對外部數據進行代理,外部傳入的數據若是爲對象,對此數據進行的淺拷貝,此時咱們成爲數據的響應式;
  對於初始化後,進行的數據添加無效,要想對於初始後添加的數據生效,須要使用$set(),不過不推薦這麼,儘可能在數據初始化時,就對全部須要的數據進行添加,能夠用undefined和null進行佔位;
  $watch方法對於實例對象的數據進行監聽,並在回掉中接受舊數據和新數據;

(3)方法:

Methods對象來定義方法,而且使用v-on指令來監聽DOM事件;
 自定義事件:$emit、$on、($broadcast、$dispatch在2.0中已經刪除)

(4)生命週期:

在vue實例建立時一系列的初始化步驟:
  beforeCreate、created、beforeMount、mounted、beforeDestroy、destroyed 、beforeUpdate、updated、activated、deactivated
(5)數據綁定:
  傳統的web項目,每每是經過後端模板引擎來進行數據和視圖的渲染,例如:php的smarty、java的velocity、node的express、也就是傳統的服務端渲染,致使先後端語言混雜在一塊兒,形成渲染後期進行視圖更改是,只能經過dom;
  a、文本插值
     使用{{}}大括號,單次賦值:{{*}}   (2.0中使用v-once=」」)  
  b、 屬性插值{{}}   (2.0 v-bind:id=」」)
  c、表達式{{}} 
 (6)指令:

a、參數:v-bind:src=」attr」,給屬性綁定值;
或者能夠這樣寫:src=」{{attr}}」
或者能夠這樣寫 :src=「attr」

b、v-on

4、 計算屬性:

####三種對於數據變化監聽機制:
一、 computed:一個屬性依賴於多個屬性時,推薦使用
二、 watch():多個屬性依賴一個屬性是,推薦使用
三、 Set、get:set對一個屬性設置值時,會自動的調用相應的回掉函數,get的回調函數會根據,函數內部依賴的屬性的改變而自動改變

5、 條件渲染:

一、 v-if

二、 template v-if

若是在一個判斷中要對多個元素進行渲染,則須要配合template標籤;

三、 v-else

四、 v-else-if

屢次進行鏈式的使用

五、 key管理可複用的元素:

Vue 會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染
在這裏用key進行元素的惟一標識賦值,下降元素的複用性;

六、 v-if與v-show

v-if 是「真正的」條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建
v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷

七、 v-if與v-for一塊兒使用

當 v-if 與 v-for 一塊兒使用時,v-for 具備比 v-if 更高的優先級;若是想讓v-if優先級更高,則須要在外套一層標籤;進行v-if的渲染

6、 列表渲染:

A、數組:

一、 經常使用寫法:
v-for=」item in items」
v-for=」(item,index) in items」
二、 結合template使用:
帶有 v-for 的 <template> 標籤來渲染多個元素塊

B、對象:

一、 經常使用寫法:
v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key, index) in object"

C、整數迭代:

一、 經常使用寫法:
v-for="n in 10"

D、組件:

一、 經常使用寫法:
<my-component v-for="item in items" :key="item.id"></my-component>

E、key:

當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用 「就地複用」 策略,默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態。爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。
注:若是加key值,列表從新渲染的元素,是從key變化的第一個元素起到key值變化的最後一個元素結束,中間全部的元素都是從新渲染,無論中間元素的key值變化與否;

F、變異方法,觸發視圖更新:

Push、pop、shift、unshift、splice、sort、reverse

G、重塑數組、顯示過濾/排序結果

對於非變異的數組方法,在操做數組時,通常是採用從新賦值的方式,操做作完原數組,再將結果賦給原屬性;如:filter、concat、slice

evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
}

7、 方法與事件:

一、 方法處理器:

v-on 指令監聽 DOM 事件

二、 內聯語句處理器:

方法的調用方式,能夠直接出入參數,或$event當前事件傳入

三、 事件修飾符:

.stop:等同於調用event.stopPropagetion()
.prevent:等同於調用event.preventDefault()
.capture:使用capture模式添加事件監聽器,使用事件捕獲模式
.self:只當事件是從監聽元素自己時纔會觸發回調;
.once:事件將只會觸發一次;

四、 按鍵修飾符:

KeyCode: (鍵值)
<input v-on:keyup.13="submit">
按鍵別名:
enter、tab、delete、esc、space、up、down、left、right

8、 表單控件綁定:

一、 v-model 會忽略全部表單元素的 value、checked、selected 特性的初始值。

二、 text、textarea

三、 複選框:

單選:(值爲true/false)
<input type="checkbox" id="checkbox" v-model="checked">
多選:(值爲數組格式,數組中每一項爲input的value值)
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<input type="checkbox" id="john" value="John" v-model="checkedNames">

四、 單選按鈕

值爲字符串,當前選中元素的value值;
<input type="radio" id="one" value="One" v-model="picked">
<input type="radio" id="two" value="Two" v-model="picked">

五、 選擇列表

單選列表:(值爲字符串)
<select v-model="selected">

<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>

</select>
注:若是 v-model 表達初始的值不匹配任何的選項,<select> 元素就會以」未選中」的狀態渲染。在 iOS 中,這會使用戶沒法選擇第一個選項,由於這樣的狀況下,iOS 不會引起 change 事件。所以,像以上提供 disabled 選項是建議的作法

多選列表:
a) 值爲一個數組格式
b) 多選時,須要ctrl配合
c) 無實際意義
d) 比單選列表多一個multiple屬性
<select v-model="selected" multiple style="width: 50px">

<option>A</option>
<option>B</option>
<option>C</option>

</select>

六、 綁定value:

(當單選或複選框選中時,此時的model值通常爲boolen值,可是根據業務需求,有時咱們須要動態綁定值,用法以下)
a) 複選框:
<input type="checkbox" v-model="toggle" v-bind:true-value="a" v-bind:false-value="b">
// 當選中時
vm.toggle === vm.a
// 當沒有選中時
vm.toggle === vm.b
b) 單選框:
<input type="radio" v-model="pick" v-bind:value="a">
// 當選中時
vm.pick === vm.a

七、 修飾符

lazy:在 change 事件中同步
number:自動將用戶的輸入值轉爲 Number 類型
trim:自動過濾用戶輸入的首尾空格

9、 過渡:

經過 Vue.js 的過渡系統,能夠在元素從 DOM 中插入或移除時自動應用過渡效果。Vue.js 會在適當的時機爲你觸發 CSS 過渡或動畫,你也能夠提供相應JavaScript 鉤子函數在過渡過程當中執行自定義的 DOM 操做。

一、 常用工具:

在 CSS 過渡和動畫中自動應用 class
能夠配合使用第三方 CSS 動畫庫,如 Animate.css
在過渡鉤子函數中使用 JavaScript 直接操做 DOM
能夠配合使用第三方 JavaScript 動畫庫,如 Velocity.js

二、 Vue 提供了 transition 的封裝組件,與下面狀況一塊兒使用:

v-if
v-show
動態組件 (介紹見組件)
在組件的根節點上,而且被 Vue 實例 DOM 方法(如 vm.$appendTo(el))觸發。

三、 vue對transition組件的處理方式:

a) 自動嗅探目標元素是否應用了 CSS 過渡或動畫,若是是,在恰當的時機添加/刪除 CSS 類名。
b) 若是過渡組件提供了 JavaScript 鉤子函數,這些鉤子函數將在恰當的時機被調用
c) 若是沒有找到 JavaScript 鉤子而且也沒有檢測到 CSS 過渡/動畫,DOM 操做(插入/刪除)在下一幀中當即執行。

四、 類名的添加和切換取決於 transition 特性的值。好比 <transition name="fade">,會有六個 CSS 類名:

A. 當dom插入時:
1) fade-enter: 定義進入過渡的開始狀態。在元素被插入時生效,在下一個幀移除
2) fade-enter-active: 定義過渡的狀態。在元素整個過渡過程當中做用,在元素被插入時生效,在 transition/animation 完成以後移除。 這個類能夠被用來定義過渡的過程時間,延遲和曲線函數。
3) fade-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入一幀後生效(於此同時 v-enter 被刪除),在 transition/animation 完成以後移除。
B. 當dom移除時:
1) fade-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時生效,在下一個幀移除。
2) fade-leave-active: 定義過渡的狀態。在元素整個過渡過程當中做用,在離開過渡被觸發後當即生效,在 transition/animation 完成以後移除。 這個類能夠被用來定義過渡的過程時間,延遲和曲線函數。
3) fade-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發一幀後生效(於此同時 v-leave 被刪除),在 transition/animation 完成以後移除。

注:若是一個動畫在dom插入和刪除時執行的效果正好相反,則只須要將v-enter和v-leave-to的樣式設置成同樣就能夠;不須要對v-enter-to和v-leave進行設置,對於v-enter-active和v-leave-active能夠進行相應的過渡時間和過渡曲線的設置;

五、 經過css的animation屬性來實現過渡的效果:

CSS 動畫用法同 CSS 過渡,區別是在動畫中 v-enter 類名在節點插入 DOM 後不會當即刪除,而是在 animationend 事件觸發時刪除;

注:對於animation的使用,能夠直接在定義一個動畫,而後再v-enter-active和v-leave-active中用animation屬性定義動畫的曲線和時間便可;

六、 自定義過渡類名結合第三方動畫庫如Animate.css:

http://cdn.bootcss.com/animat...

自定義的類名屬性有:
enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)

注:他們的優先級高於普通的類名;
使用方法:
將上述屬性添加到transition元素上,屬性值爲第三方庫的動畫名,能夠不書寫name屬性定義的過渡名稱,通常只使用enter-active-class和leave-active-class就能夠知足需求書寫方式:
注:屬性值中必定要加入animated屬性值,不然不生效;
如:
enter-active-class="animated bounce"

七、 css樣式中與第三方動畫庫的結合:

將動畫定義到v-enter-active和v-leave-active類名上:
如:

.animations-enter-active,
  .animations-leave-active {
    animation: bounce 1s;
  }

八、 同時使用transitions和animations時顯示的聲明過渡類型

Vue 爲了知道過渡的完成,dom要顯示原有的樣式,必須設置相應的事件監聽器,它能夠是 transitionend 或 animationend ,這取決於給元素應用的 CSS 規則。若是你使用其中任何一種,Vue 能自動識別類型並設置監聽。
有時候同時使用transition 和animation ,而執行完畢的時間不統一,會形成後者沒法將動畫執行完畢,此時能夠用type屬性在transition元素上進行相應的設置須要 Vue 監聽的類型,屬性值爲transition 或animation

九、 顯示定義過渡效果的持續時間

應用場景:
Vue 會等待其在過渡效果的根元素第一個 transitionend 或 animationend 事件觸發後,結束過渡效果;一些嵌套的內部元素相比於過渡效果的根元素有延遲的或更長的過渡效果。
使用方式:
<transition :duration="1000">...</transition>
<transition :duration="{ enter: 500, leave: 800 }">...</transition>

十、 js中的鉤子函數

beforeEnter、enter、afterEnter、enterCancelled、beforeLeave、leave、afterLeave、leaveCancelled

結合第三方js動畫庫:<script src="https://cdnjs.cloudflare.com/...;></script>
動畫的書寫格式:
Velocity的參數:第一個爲動畫掛載的元素,第二個爲定義的動畫css樣式,第三個參數爲動畫的時間或者回調函數
如:
Velocity(el,{fontSize:’1.5em’},{duration:300,complete:done})

經常使用鉤子函數爲:beforeEnter 、enter、beforeLeave 、leave分別定義,元素進入時的動畫和元素離開時的動畫;
beforeEnter:定義元素進入時的初始樣式;
enter:定義元素進入過程的動畫樣式(通常第三方庫的動畫使用在此鉤子中)
beforeLeave:定義元素離開是的初始樣式;
leave:定義元素離開過程的動畫樣式(通常第三方庫的動畫使用在此鉤子中)
注:必定注意在enter、leave鉤子中必定使用done的方法的調用,不然動畫將無效;

十一、 初始渲染的過渡;

經過appear屬性的添加實現初始渲染的過渡

十二、 在一個transition元素中對多個標籤動畫的實現:

須要給每個元素添加一個key標籤,防止元素的複用(不產生任何動畫)
過渡模式:
場景:在兩個元素的切換過程當中,進入元素和離開元素的過渡同時進行,將會致使效果誤差;
解決:
能夠在過渡的標籤上添加過渡模式:(mode)
in-out: 新元素先進行過渡,完成以後當前元素過渡離開。(通常不用)
out-in: 當前元素先進行過渡,完成以後新元素過渡進入。

1三、 多個組件的過渡

通常使用動態組件的方式實現不一樣組件間的切換,而後在切換過程當中實現過渡效果;
注:動態組件的切換不存在標籤的複用問題

1四、 列表過渡:

1) 列表的進入和離開過渡
使用transition-group組件,不一樣於transition組件,會以一個真實元素呈現,默認爲span元素,也能夠經過tag特性更換爲其餘元素;
內部元素必須提供惟一的key值
2) 列表的位移過渡
v-move特性能夠在元素的改變定位的過程當中應用,能夠經過name屬性自定義前綴,也能夠經過move-class手動設置

10、 組件

組件 (Component) 是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。

(一) 組件註冊:

組件構造器:Vue.extend({ }),2.0中能夠不使用構造器進行構造,直接寫入對象;
規則:對於自定義標籤名,Vue.js 不強制要求遵循 W3C 規則 (小寫,而且包含一個短槓),儘管遵循這個規則比較好
一、 全局註冊:
全局註冊須要在根實例初始化前註冊,這樣才能使組件在任意實例中被使用,方式:Vue.component(「組件名」,組件)
二、 局部註冊:
組件只能在被註冊的組件中使用,而沒法在其餘組件中使用.
三、 註冊語法糖:
全局註冊和局部註冊(使用components屬性,值爲對象,組件名和組件定義對象是鍵值對的關係);

(二) 組件選項:

一、 template:注意分析模板,is使用;

二、 el和data兩個屬性,不能夠直接賦值,好比data若是直接賦值,組件使用屢次的時候,多個組件將公用一個對象;若是一個改變,則全部都會改變;因此使用function方式,每次return出一個新的對象;el相似;因爲el不多直接在組件中掛載,因此能夠忽略;
三、 props:
組件間的做用域是孤立的,這裏跟angular的指令做用域有所不一樣,angular指令的默認做用域是公用的,無論是在子指令仍是父指令中定義的;在vue中,props起到了父組件向下與子組件間的橋樑做用;子組件給父組件發送消息,須要events;
ν 駝峯命名:html的屬性不區分大小寫;

ν 動態props:
經過v-bind進行綁定;
若是要進行數值的傳遞,必須經過動態綁定,不然直接傳遞過去的是個字符串;
ν props的接受:
在子組件中使用props屬性進行接受,props的值能夠爲數組(不可作校驗),能夠爲對象(能夠作校驗)
ν props數據的處理:
不該該在子組件中進行prop值的改變,由於prop的值是隨父組件進行更變,若是在組件中直接對prop進行改變,vue則會拋出警告
正確的處理方式:
a) 定義一個局部變量,並用 prop 的值初始化它:(只會在初始化時,進行一次賦值,後期不會動態改變)
props: ['initialCounter'],

data: function () {
  return { counter: this.initialCounter }
}

b) 定義一個計算屬性,處理prop的值並返回:(進行屬性值的動態跟蹤)
props: ['size'],

computed: {
  normalizedSize: function () {
   return this.size.trim().toLowerCase()
  }
}

ν 綁定類型:
1) 默認時一直跟隨父組件值得變化而變化,
2) .sync:雙向綁定(取消);在2.3.0之後,再次以事件監聽實現雙向數據流;如:
父組件:
<comp :foo="bar" @updata="val => bar = val"></comp>
子組件:
this.$emit('update:foo', newValue)
3) .once:單次綁定,子組件接受一次父組件傳遞的數據後,單獨對這份數據進行維護;(2.0版本後取消此修飾符)
注:若是prop傳遞的是一個引用類型的數據,如對象或數組,即便單向綁定,子組件也會影響父組件;(傳遞爲單向傳遞)
ν Props驗證:
1) 基礎類型檢測:prop:Number,接受的參數爲原生的構造器:String、Number、Boolen、Function、Object、Aarry、Symbol、Null(意味着任何類型都行)
2) 能夠爲多種類型:props:[Number,String]
3) 參數必須:props:{type:Number,required:true} 對象的寫法
4) 參數默認:props {type:Number,default:0} 對象的寫法
5) 綁定類型:props:{twoWay:true} 校驗數據綁定類型,若是非雙向綁定會拋出一條警告;(這個不用了)
6) 自定義驗證函數:props:{validator:function(val){ return val>1},這樣就能夠驗證一個數值是否大於1;

(三) 非Prop屬性:

一、 在組件上使用自定義屬性,若是不在子組件中使用props進行接受,則此屬性會被默認添加到組件的根元素上;
二、 在組件上使用html元素已有的屬性,如class、style等,則組件上的屬性值,會和組件的根節點的相應屬性值進行合併等特性;如type等屬性值,會進行覆蓋或替換;如:組件中的input的type爲number,使用組件時傳入的type值爲text,則組件內部的input的type值將被替換爲text;

(四) 組件間通訊:

一、 直接訪問:
1) $parent:父組件實例
2) $children:包含全部子組件實例
3) $root:組件所在的根實例;
這三個屬性都掛載在組件的this上,不推薦這樣作,會形成父子組件間的強耦合;
二、 自定義事件監聽:
1) 組件實例化時,在組件的標籤上使用@進行事件的監聽;
三、 自定義事件觸發機制:
1) $emit:在實例自己上觸發事件在子組件的鉤子函數中去觸發事件;
四、 子組件索引:
經過ref指令,綁定一個子組件,能夠在父組件中使用this.$refs.屬性名 的方式獲取子組件;
五、 非父子通訊:
思想:創建一個空的vue實例做爲中央事件總線,即全局的vue實例;
代碼以下:

var bus = new Vue()
// 觸發組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 建立的鉤子中監聽事件
bus.$on('id-selected', function (id) {
  // ...
})

(五) 內容分發:

一、 基礎用法:
提供一種混合父組件內容與子組件本身模板的方式叫作內容分發;
Slot標籤;
二、 使用需求:
當子組件中的dom結構以及展現的內容由父組件決定時
三、 編譯做用域:
若是在子組件的模板中使用{{}}解析數據,則模板會解析本身做用域中的數據,而不是解析父組件做用中的數據;
四、 默認slot:
<slot>標籤容許有一個匿名slot,不須要name值,做爲找不到匹配的內容片斷的回退插槽,若是沒有默認的slot,這些找不到匹配的內容片斷將被忽略;
五、 做用域插槽:
在父組件的slot模板中使用子組件中數據;如:

//子組件
<div class="child">
  <slot text="hello from child"></slot>
</div>
//父組件
<div class="parent">
  <child>
    <template scope="props">
      <span>hello from parent</span>
      <span>{{ props.text }}</span>
    </template>
  </child>
</div>

在父級中,具備特殊屬性 scope 的 <template> 元素必須存在,表示它是做用域插槽的模板。scope 的值對應一個臨時變量名,此變量接收從子組件中傳遞的 props 對象;
在slot中能夠動態綁定屬性值,綁定的屬性須要在父組件的scope中進行顯示聲明;

(六) 動態組件:

一、基礎用法:
component 標籤上 is 屬性決定了當前採用的子組件,:is 是 v-bind:is 的縮寫,綁定了父 組件中 data 的 currentView 屬性。頂部的 ul 則起到導航的做用,點擊便可修改 currentView 值,也就修改 component 標籤中使用的子組件類型,須要注意的事,currentView 的值須要 和父組件實例中的 components 屬性的 key 相對應。(起到路由的做用)
二、keep-alive
在component 標籤外層包裹一個 keep-alive 標籤,能夠將切換出去的組件保留在內存中,避免從新 渲染。

(七) 雜項:

一、 異步組件:
局部定義組件寫法:

new Vue({
  components: {
//使用webpack+es6
    'my-component': () => import('./my-async-component')
//使用webpack+es5
'my-component': require(['./my-async-component'], resolve)
  }
})
使用webpack + es5的寫法:

二、 當註冊組件 (或者 props) 時,可使用 kebab-case,camelCase,或 PascalCase。可是使用組件時只能用kebab-case這種寫法;html不識別大小寫;
三、 當組件中包含大量靜態內容時,能夠考慮使用 v-once 將渲染結果緩存起來

Vue.component('terms-of-service', {
  template: '\
    <div v-once>\
      <h1>Terms of Service</h1>\
      ... a lot of static content ...\
    </div>\
  '
})

四、 X-Templates
另外一種定義模版的方式是在 JavaScript 標籤裏使用 text/x-template 類型
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>

11、 指令

一、 內置指令:

1) V-bind
2) V-model
3) V-if/ v-else-if/v-else/v-show
4) V-for
5) V-on
6) V-text
7) V-html
8) v-pre 指令相對簡單,就是跳過編譯這個元素和子元素,顯示原始的 {{}}Mustache 標 籤,用來減小編譯時間。
9) v-cloak 指令至關於在元素上添加了一個 [v-cloak] 的屬性,直到關聯的實例結束編譯。 官方推薦能夠和 css 規則 [v-cloak]{ display :none } 一塊兒使用,能夠隱藏未編譯的 Mustache 標籤直到實例準備完畢
10) v-once 指令是 Vue.js 2.0 中新增的內置指令,用於標明元素或組件只渲染一次,即便隨 後發生綁定數據的變化或更新,該元素或組件及包含的子元素都不會再次被編譯和渲染。

二、 自定義指令基礎:

1) 註冊:經過 Vue.directive(id, definition) 方法註冊一個全局自定義指令,接收參數 id 和定義對象。id 是指令的惟一標識,定義對象則是指令的相關屬性及鉤子函數。
也能夠經過在組件的 directives 選項註冊一個局部的自定 義指令
2) 指令的定義對象:
主要包含鉤子函數:
bind: 只被調用一次,在指令第一次綁定到元素上時調用。用這個鉤子函數能夠定義一個在綁定時執行一次的初始化動做。
inserted: 被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於 document 中)。
update : 所在組件的 VNode 更新時調用,可是可能發生在其孩子的 VNode 更新以前。指令的值可能發生了改變也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新
componentUpdated: 所在組件的 VNode 及其孩子的 VNode 所有更新時調用。
unbind :指令從元素上解綁時調用,只調用一次。
注:若是咱們只須要使用 update 函數時,能夠直接傳入一個函數代替定義對象;
指令綁定的值:
a) data 中的屬性,使用<div v-my-directive="constant string"/></div>
b) 綁定字符串須要加單引號,<div v-my-direcitve="'constant string'"></div>
c) 利用字面修飾符後無需使用單引號

<div v-my-directive.literal="constant string"></div>

d) 受對象字面量或任意合法的 JavaScript 表達式:

<div v-my-directive="{ title : 'Vue.js', author : 'You'}" ></div> 
<div v-my-directive="isExist ? 'yes' : 'no'" ></div>

3) 指令的實例屬性:
a) el: 指令所綁定的元素,能夠用來直接操做 DOM 。
b) binding: 一個對象,包含如下屬性:
name: 指令名,不包括 v- 前綴。
value: 指令的綁定值, 例如: v-my-directive="1 + 1", value 的值是 2。
oldValue: 指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。不管值是否改變均可用。
expression: 綁定值的表達式形式。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
arg: 傳給指令的參數。例如 v-my-directive:foo, arg 的值是 "foo"。
modifiers: 一個包含修飾符的對象。 例如: v-my-directive.foo.bar, 修飾符對象 modifiers 的值是 { foo: true, bar: true }。
c) vnode: Vue 編譯生成的虛擬節點,查閱 VNode API 瞭解更多詳情。
d) oldVnode: 上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。

三、 指令與組件的區別:

組件通常是指一個獨立實體,組件之間的關係一般都是樹狀。
指令是一種Decorator模式,用以改寫某個組件的默認行爲,或者加強使其得到額外功能,通常來講能夠在同一個組件上疊加若干個指令,使其得到多種功能。

12、 vue-route

(一) 基本用法:

一、 router-link:

a) <router-link> 組件支持用戶在具備路由功能的應用中(點擊)導航。 經過 to 屬性指定目標地址,默認渲染成帶有正確連接的 標籤,能夠經過配置 tag 屬性生成別的標籤,<router-link> 比起寫死的 會好一些;
b) props:路由參數:
to:格式爲字符串或者是對象;
寫法:

<router-link to="home">Home</router-link>
<router-link :to="'home'">Home</router-link>
<router-link :to="{ path: 'home' }">Home</router-link>

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace: 設置 replace 屬性的話,當點擊時,會調用 router.replace() 而不是 router.push(),因而導航後不會留下 history 記錄

append: 在當前(相對)路徑前添加基路徑。例如,咱們從 /a 導航到一個相對路徑 b,若是沒有配置 append,則路徑爲 /b,若是配了,則爲 /a/b
注:另外一個路徑不容許加/;

tag:將touter-link轉換爲另一種標籤;

active-class:設置 連接激活時使用的 CSS 類名。默認值能夠經過路由的構造選項 linkActiveClass 來全局配置。

二、 router-view

渲染對應的路由配置中 components 下的相應組件;能夠和<transition> 、 <keep-alive>等配合使用,兩個結合一塊兒用,要確保在內層使用 <keep-alive>:
<transition>
<keep-alive>

<router-view></router-view>

</keep-alive>
</transition>

三、 路由信息對象:

路由信息對象表示當前激活的路由的狀態信息,是不可變得,每次成功的導航都會產生一個新的對象;
出現的地方:
λ 組件內部的鉤子函數中;
λ 導航的鉤子函數中
λ watch監聽的$route對象中的(to,from)參數:
例:

watch: {
    '$route' (to, from) {
         } }

scrollBehavior 方法的參數
路由信息對象的屬性:
$route.path:字符串,對應當前路由的路徑,老是解析爲絕對路徑,如 "/foo/bar"。

$route.params:包含了 動態片斷 和 全匹配片斷,若是沒有路由參數,就是一個空對象。
$route.query:一個 key/value 對象,表示 URL 查詢參數。例如,對於路徑 /foo?user=1,則有 $route.query.user == 1,若是沒有查詢參數,則是個空對象。
$route.matched:一個數組,包含當前路由的全部嵌套路徑片斷的 路由記錄 。路由記錄就是 routes 配置數組中的對象副本(還有在 children 數組)
$route.name:當前路由的名稱

四、 router構造配置

mode: 配置路由模式:hash | history | abstract
base:應用的基路徑。例如,若是整個單頁應用服務在 /app/ 下,而後 base 就應該設爲 "/app/"。(這裏有坑)
linkActiveClass: 全局配置 <router-link> 的默認『激活 class 類名

五、 router實例:

屬性:
router.app: 配置了 router 的 Vue 根實例。
router.mode: 路由使用的 模式。
router.currentRoute:當前路由信息對象;

方法:
router.push(location) :進行路由的跳轉,而且保存到瀏覽器的history中
router.replace(location):進行路由的替換,不會將上次的路由保存到history中
router.go(n):執行瀏覽器的前進動做,n表明前進的步數,負數表明後退
router.back(): 執行瀏覽器的後退動做
router.forward()
router.addRoutes(routes): 動態添加更多的路由規則。參數必須是一個符合 routes 選項要求的數組

六、 動態路由匹配:

書寫方式:

{ path: '/user/:id', component: User }
{ path: '/user/:username/post/:post_id', component: User }

上述的動態值經過 $route.params去接受
路由參數的變化:
使用路由參數時,例如從 /user/foo 導航到 user/bar,原來的組件實例會被複用。由於兩個路由都渲染同個組件,比起銷燬再建立,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用;
解決辦法:
watch(監測變化) $route 對象:

七、 嵌套路由:

在 VueRouter 的參數中使用 children 配置,屬性值爲路由對象數組;
注意:在子路由的path屬性中設置路由地址時,不能夠加「/」,不然將會以根路由進行添加;

八、 多視圖多組件渲染:

多視圖對應多組件,使用的路由對象屬性爲:components;
例:
html:
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
js:

{
  path: '/',
  components: {
    default: Foo,
    a: Bar,
    b: Baz
  }
}

九、 重定向:

屬性爲redirect,屬性值能夠爲{name:「foo」}或「foo」或者爲一個方法的返回值
例:
{ path: '/a', redirect: { name: 'foo' }}

十、 別名:

例:{ path: '/a', component: A, alias: '/b' }
當用戶訪問/b時,路由顯示的是/b,其實規則爲/a

十一、 路由的鉤子函數:

1) 全局鉤子:(通常不使用)
使用router的實例對象進行註冊;當一個導航觸發時,全局的 beforeEach鉤子按照建立順序調用。鉤子是異步解析執行,此時導航在全部鉤子 resolve 完以前一直處於 等待中
三個參數:
next(): 進行管道中的下一個鉤子
next(false): 中斷當前的導航。重置到 from 路由對應的地址
next('/') 或next({ path: '/' }):當前導航被中斷,重定向到另外一個新的導航:
例:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {})

2) 路由的獨享鉤子:
在路由的配置項中定義:beforeEnter屬性;

{
  path: '/foo',
  component: Foo,
  beforeEnter: (to, from, next) => {
  }
 }

3) 組件內的路由鉤子:
beforeRouteEnter:路由跳轉以前執行,不能獲取this,組件實例尚未建立;
beforeRouteUpdate:路由從新跳轉以前,該方法在組件複用時調用,該鉤子函數中能夠訪問組件的實例this
beforeRouteLeave:離開該組件的對應路由時調用,能夠訪問實例this,通常在用戶未保存信息時,不容許跳轉相應的路由,next(false)阻止;

關於beforeRouteEnter鉤子不能訪問this,能夠經過一個回調給next來訪問組件實例,例:

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 經過 `vm` 訪問組件實例
  })
}

十二、 數據的獲取

1) 導航完成以後獲取:先完成導航,而後在接下來的組件生命週期鉤子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。
2) 導航完成以前獲取:導航完成前,在路由的 enter 鉤子中獲取數據,在數據獲取成功後執行導航。
注:
導航完成以後獲取須要藉助組件的watch屬性,在動態路由中組件複用時,進行數據的從新請求;
導航完成以前獲取藉助beforeRouteUpdate, 在動態路由中組件複用時,進行數據的從新請求;

1三、 組件的懶加載

一、 vue的異步組件和webpack的require.ensure()相結合,例:

var index = resolve => require.ensure(['@/components/index'], () =>             
resolve(require('@/components/index')))

二、 採用amd風格的require,例:

var Hello = resolve => require(['@/components/Hello'], resolve)

三、 把組件按組分塊:
提供 require.ensure 第三個參數做爲 chunk 的名稱,Webpack 將相同 chunk 下的全部異步模塊打包到一個異步塊裏面 —— 這也意味着咱們無須明確列出 require.ensure 的依賴(傳空數組就行)
例:

const Foo = resolve => require.ensure([], () => resolve (require('./Foo.vue')), 'group-foo')
const Bar = resolve => require.ensure([], () => resolve (require('./Bar.vue')), 'group-foo')
const Baz = resolve => require.ensure([], () => resolve (require('./Baz.vue')), 'group-foo')

十3、 狀態管理:(vuex)

一、 簡介:

a) 在一些大型應用中,有時咱們會遇到單頁面中包含着大量的組件及複雜的數據結構,而 且可能各組件還會互相影響各自的狀態,在這種狀況下組件樹中的事件流會很快變得很是復 雜,也使調試變得異常困難。爲了解決這種狀況,咱們每每會引入狀態管理這種設計模式,來 下降這種狀況下事件的複雜程度而且使調試變得能夠追蹤。
b) 每一個組件都會擁有本身的狀態,也能夠理解成自身實例中的 data 對 象。用戶在操做的過程當中,會經過一些交互行爲,例如點擊、輸入、拖動等修改組件的 狀態,而此時每每須要將用戶引發的狀態變化通知到其餘相關組件,讓他們也進行對應 的修改。因爲 Vue.js 自己的事件流是依賴於 DOM 結構的,組件修改狀態後須要通過 一系列冒泡才能達到頂部的組件,並且若是須要修改兄弟組件的狀態還須要共同的父組 件再進行一次廣播。這種方式無疑是低效並且不易維護的,咱們也很難去追蹤事件流的 走向。
c) vuex 和 redux 間的差別表示關注,redux 是 React 生態環境中最流行的 Flux 實現。Redux 事實上沒法感知視圖層,因此它可以輕鬆的經過一些簡單綁定和Vue一塊兒使用。vuex區別在於它是一個專門爲 vue 應用所設計。這使得它可以更好地和vue進行整合,同時提供簡潔的API和改善過的開發體驗。

二、 配置使用:

安裝vuex,在main.js中引入vuex進行使用;

import vuex from 「vuex」,
Vue.use(vuex)

實例化Vuex:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

將vuex掛載到Vue實例中:

const app = new Vue({
  el: '#app',
  // 把 store 對象提供給 「store」 選項,這能夠把 store 的實例注入全部的子組件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
   `
})

如今,你能夠經過 store.state 來獲取狀態對象,以及經過 store.commit 方法觸發狀態變動,咱們經過提交 mutation 的方式,而非直接改變 this.$store.state.count,是由於咱們想要更明確地追蹤到狀態的變化

三、 核心概念:

a) state:
ν 數據的定義以及存放數據的屬性,相似於組件內部的data屬性;全部在vuex使用的數據都必須在此屬性中進行定義與聲明;不建議將應用全部的數據都放入state,交互性低,比較單一使用的數據,建議放在組件內部定義;
ν mapState輔助函數
寫法:
對象寫法:

computed:mapState({
//寫法一:箭頭函數可以使代碼更簡潔
count:state=> state.count 
//寫法二:傳字符串參數 'count' 等同於 `state => state.count`
count:state=> state.count 
//寫法三:爲了可以使用 `this` 獲取局部狀態,必須使用常規函數
count(state){ 
return state.count+this.a 

}
})

數組寫法:
當映射的計算屬性的名稱與 state 的子節點名稱相同時

computed:mapState([
「count」
])

ν 對象展開運算符:
注意運用此方法時,由於對象擴展運算符是在es提案的stage-3階段,因爲babel進行轉碼時,在webpack中默認配置的是es-2015,因此須要藉助babel-plugin-transform-object-rest-spread插件進行編譯;
在babel的配置文件中以下配置:
"plugins": ["transform-runtime", "transform-object-rest-spread"],

在computed屬性中的寫法以下:
...mapState({

// ...

})
上面的mapState的參數能夠是對象,也能夠是數組,跟mapState輔助函數中的配置同樣
b) Getters:
應用場景:
有時候,咱們須要對state數據進行一些操做後再在組件中進行使用,若是多個組件都須要操做後的這個數據,咱們可能會在多個組件computed中都對state進行操做一次;
解決辦法:
使用getters:

getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }

組件中使用,跟state的使用同樣,可使用輔助函數,或者對象展開運算符
c) Mutations:
更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutations 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數;
定義的方式跟getters同樣,例:

mutations: {
    increment (state) {
      // 變動狀態
      state.count++
    }
  }

回調函數的第一個參數爲state,第二個參數能夠動態傳入值,值的類型,能夠爲基本類型或對象;
提交載荷:
可使用store.commit(‘increment’,10)
或store.commit({type:’increment’,amount:10})
遵循vue的數據相應規則:
在對象上添加新屬性時,使用 Vue.set(obj, 'newProp', 123)或者
state.obj = { ...state.obj, newProp: 123 }
mutation必須是同步函數:
若是爲異步,則沒法跟蹤數據
在組件中直接提交(不推薦)

methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 爲 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 爲 this.$store.commit('increment')
    })
  }

d) actions:
action提交的是mutation,而不是直接更變狀態。
action能夠包含任意異步操做。
註冊:

actions: {
    increment (context) {
      context.commit('increment')
    }
  }

i. 在actions的內部能夠獲取以一個context參數。這個參數至關於一個store實例,但不是當前應用的store實例自己,由於若是採用modules方式進行數據的管理時,store實例是一個數組;
ii. 能夠經過context參數獲取state或者getters等等,通常能夠經過此參數來提交commit;

分發action:
應用場景:當一次action對應的數據的更改,必須依賴另一個action中的數據更改時,必須在本此action中先去觸發另一個action操做;另一個action可能爲同步,也可能爲異步,若是爲異步須要藉助promise或者async函數;
// 以載荷形式分發

store.dispatch('incrementAsync', {
  amount: 10
})

// 以對象形式分發
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

在組件中分發action:

methods: {
    ...mapActions([
      'increment' // 映射 this.increment() 爲 this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // 映射 this.add() 爲 this.$store.dispatch('increment')
    })
  }

經過dispatch觸發異步action:
使用promise:

actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
})
}

actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
 }

使用async函數:
getData、getOtherData返回的是promise,或者是axiso的數據請求函數

async actionA ({ commit }) {
    commit('gotData', await getData())
  },
async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }

e) modules:
應用場景:

  1. 當一個項目比較大時,全部的數據與數據管理都放在同一個store中時,此時的store對象就會變得比較臃腫;
  2. 當某個大型項目,幾個開發團隊一塊兒開發時,同時操做一個store,可能會出現衝突等問題,每一個團隊負責的產品鏈的數據管理相對獨立時,能夠採用module的方式管理;

定義:
將 store 分割成模塊(module)。每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行一樣方式的分割
如:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> moduleA 的狀態

模塊的局部狀態:對於模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態對象對於模塊內部的 action,局部狀態經過 context.state 暴露出來, 根節點狀態則爲 context.rootState在getter中根節點狀態會做爲第三個參數暴露出來

相關文章
相關標籤/搜索