1. 程式人生 > 其它 >Vue2全家桶

Vue2全家桶

1. Vue.js是什麼?

1). 一位華裔前Google工程師(尤雨溪)開發的前端js庫
2). 作用: 動態構建使用者介面
3). 特點:
* 遵循MVVM模式
* 編碼簡潔, 體積小, 執行效率高, 移動/PC端開發
* 它本身只關注UI, 可以輕鬆引入vue外掛和其它第三庫開發專案
4). 與其它框架的關聯:
* 借鑑angular的模板和資料繫結技術
* 借鑑react的元件化和虛擬DOM技術
5). vue包含一系列的擴充套件外掛(庫):
* vue-cli: vue腳手架
* vue-resource(axios): ajax請求
* vue-router: 路由
* vuex: 狀態管理
* vue-lazyload: 圖片懶載入
* vue-scroller: 頁面滑動相關
* mint-ui: 基於vue的元件庫(移動端)
* element-ui: 基於vue的元件庫(PC端)

2. 基本使用

1). 引入vue.js
2). 建立Vue例項物件(vm), 指定選項(配置)物件
el : 指定dom標籤容器的選擇器
data : 指定初始化狀態資料的物件/函式(返回一個物件)
3). 在頁面模板中使用{{}}或vue指令

3. Vue物件的選項

1). el

指定dom標籤容器的選擇器
Vue就會管理對應的標籤及其子標籤

2). data

物件或函式型別
指定初始化狀態屬性資料的物件
vm也會自動擁有data中所有屬性
頁面中可以直接訪問使用
資料代理: 由vm物件來代理對data中所有屬性的操作(讀/寫)

3). methods

包含多個方法的物件
供頁面中的事件指令來繫結回撥
回撥函式預設有event引數, 但也可以指定自己的引數
所有的方法由vue物件來呼叫, 訪問data中的屬性直接使用this.xxx

4). computed

包含多個方法的物件
對狀態屬性進行計算返回一個新的資料, 供頁面獲取顯示
一般情況下是相當於是一個只讀的屬性
利用set/get方法來實現屬性資料的計算讀取, 同時監視屬性資料的變化
如何給物件定義get/set屬性
在建立物件時指定: get name () {return xxx} / set name (value) {}
物件建立之後指定: Object.defineProperty(obj, age, {get(){}, set(value){}})

5). watch

包含多個屬性監視的物件
分為一般監視和深度監視
  xxx: function(value){}
xxx : {
deep : true,
handler : fun(value)
}
另一種新增監視方式: vm.$watch('xxx', function(value){})

4. 過渡動畫

利用vue去操控css的transition/animation動畫
模板: 使用<transition name='xxx'>包含帶動畫的標籤
css樣式
.fade-enter-active: 進入過程, 指定進入的transition
.fade-leave-active: 離開過程, 指定離開的transition
.xxx-enter, .xxx-leave-to: 指定隱藏的樣式
編碼例子
  .xxx-enter-active, .xxx-leave-active {
    transition: opacity .5s
  }
  .xxx-enter, .xxx-leave-to {
    opacity: 0
  }
   
  <transition name="xxx">
    <p v-if="show">hello</p>
  </transition>

5. 生命週期

vm/元件物件
生命週期圖
主要的生命週期函式(鉤子)
created() / mounted(): 啟動非同步任務(啟動定時器,傳送ajax請求, 繫結監聽)
beforeDestroy(): 做一些收尾的工作

6. 自定義過濾器

1). 理解

對需要顯示的資料進行格式化後再顯示

2). 編碼

1). 定義過濾器
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 進行一定的資料處理
return newValue
})
2). 使用過濾器
<div>{{myData | filterName}}</div>
<div>{{myData | filterName(arg)}}</div>

7. vue內建指令

v-text/v-html: 指定標籤體
* v-text : 當作純文字
* v-html : 將value作為html標籤來解析
v-if v-else v-show: 顯示/隱藏元素
* v-if : 如果vlaue為true, 當前標籤會輸出在頁面中
* v-else : 與v-if一起使用, 如果value為false, 將當前標籤輸出到頁面中
* v-show: 就會在標籤中新增display樣式, 如果vlaue為true, display=block, 否則是none
v-for : 遍歷
* 遍歷陣列 : v-for="(person, index) in persons"  
* 遍歷物件 : v-for="value in person"   $key
v-on : 繫結事件監聽
* v-on:事件名, 可以縮寫為: @事件名
* 監視具體的按鍵: @keyup.keyCode   @keyup.enter
* 停止事件的冒泡和阻止事件預設行為: @click.stop   @click.prevent
* 隱含物件: $event
v-bind : 強制繫結解析表示式  
* html標籤屬性是不支援表示式的, 就可以使用v-bind
* 可以縮寫為: :id='name'
* :class
* :class="a"
* :class="{classA : isA, classB : isB}"
* :class="[classA, classB]"
* :style
:style="{color : color}"
v-model
* 雙向資料繫結
* 自動收集使用者輸入資料
ref : 標識某個標籤
* ref='xxx'
* 讀取得到標籤物件: this.$refs.xxx

8. 自定義指令

1). 註冊全域性指令

Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toUpperCase()
})

2). 註冊區域性指令

directives : {
'my-directive' : function(el, binding) {
    el.innerHTML = binding.value.toUpperCase()
}
}

3). 使用指令

<div v-my-directive='xxx'>

----------------------假裝這裡有條分割線------------------

 

1. 準備

1.[].slice.call(lis): 將偽陣列轉換為真陣列
2.node.nodeType: 得到節點型別
3.Object.defineProperty(obj, propertyName, {}): 給物件新增/修改屬性(指定描述符)
configurable: true/false 是否可以重新define
enumerable: true/false 是否可以列舉(for..in / keys())
value: 指定初始值
writable: true/false value是否可以修改存取(訪問)描述符
get: 函式, 用來得到當前屬性值
set: 函式, 用來監視當前屬性值的變化
4.Object.keys(obj): 得到物件自身可列舉的屬性名的陣列
5.DocumentFragment: 文件碎片(高效批量更新多個節點)
6.obj.hasOwnProperty(prop): 判斷prop是否是obj自身的屬性

2. 資料代理(MVVM.js)

1.通過一個物件代理對另一個物件中屬性的操作(讀/寫)
2.通過vm物件來代理data物件中所有屬性的操作
3.好處: 更方便的操作data中的資料
4.基本實現流程
1). 通過Object.defineProperty()給vm新增與data物件的屬性對應的屬性描述符
2). 所有新增的屬性都包含getter/setter
3). 在getter/setter內部去操作data中對應的屬性資料

3. 模板解析(compile.js)

1.模板解析的關鍵物件: compile物件
2.模板解析的基本流程:
1). 將el的所有子節點取出, 新增到一個新建的文件fragment物件中
2). 對fragment中的所有層次子節點遞迴進行編譯解析處理
  * 對錶達式文字節點進行解析
  * 對元素節點的指令屬性進行解析
      * 事件指令解析
      * 一般指令解析
3). 將解析後的fragment新增到el中顯示
3.解析表示式文字節點: textNode.textContent = value
1). 根據正則物件得到匹配出的表示式字串: 子匹配/RegExp.$1
2). 從data中取出表示式對應的屬性值
3). 將屬性值設定為文字節點的textContent
4.事件指令解析: elementNode.addEventListener(事件名, 回撥函式.bind(vm))
  v-on:click="test"
1). 從指令名中取出事件名
2). 根據指令的值(表示式)從methods中得到對應的事件處理函式物件
3). 給當前元素節點繫結指定事件名和回撥函式的dom事件監聽
4). 指令解析完後, 移除此指令屬性
5.一般指令解析: elementNode.xxx = value
1). 得到指令名和指令值(表示式)
2). 從data中根據表示式得到對應的值
3). 根據指令名確定需要操作元素節點的什麼屬性
      * v-text---textContent屬性
      * v-html---innerHTML屬性
      * v-class--className屬性
4). 將得到的表示式的值設定到對應的屬性上
5). 移除元素的指令屬性

4. 資料劫持-->資料繫結

1.資料繫結(model==>View):
1). 一旦更新了data中的某個屬性資料, 所有介面上直接使用或間接使用了此屬性的節點都會更新(更新)
2.資料劫持
1). 資料劫持是vue中用來實現資料繫結的一種技術
2). 基本思想: 通過defineProperty()來監視data中所有屬性(任意層次)資料的變化, 一旦變化就去更新介面
3.四個重要物件
1). Observer
* 用來對data所有屬性資料進行劫持的建構函式
    * 給data中所有屬性重新定義屬性描述(get/set)
    * 為data中的每個屬性建立對應的dep物件
  2). Dep(Depend)
    * data中的每個屬性(所有層次)都對應一個dep物件
    * 建立的時機:
      * 在初始化define data中各個屬性時建立對應的dep物件
      * 在data中的某個屬性值被設定為新的物件時
    * 物件的結構
      {
        id, // 每個dep都有一個唯一的id
        subs //包含n個對應watcher的陣列(subscribes的簡寫)
      }
* subs屬性說明
* 當一個watcher被建立時, 內部會將當前watcher物件新增到對應的dep物件的subs中
* 當此data屬性的值發生改變時, 所有subs中的watcher都會收到更新的通知, 從而最終更新對應的介面
3). Compile
* 用來解析模板頁面的物件的建構函式(一個例項)
* 利用compile物件解析模板頁面
* 每解析一個表示式(非事件指令)都會建立一個對應的watcher物件, 並建立watcher與dep的關係
* complie與watcher關係: 一對多的關係
4). Watcher
    * 模板中每個非事件指令或表示式都對應一個watcher物件
    * 監視當前表示式資料的變化
    * 建立的時機: 在初始化編譯模板時
    * 物件的組成
{
        vm, //vm物件
        exp, //對應指令的表示式
        cb, //當表示式所對應的資料發生改變的回撥函式
        value, //表示式當前的值
        depIds //表示式中各級屬性所對應的dep物件的集合物件
                //屬性名為dep的id, 屬性值為dep
}

5). 總結: dep與watcher的關係: 多對多
* 一個data中的屬性對應對應一個dep, 一個dep中可能包含多個watcher(模板中有幾個表示式使用到了屬性)
* 模板中一個非事件表示式對應一個watcher, 一個watcher中可能包含多個dep(表示式中包含了幾個data屬性)
* 資料繫結使用到2個核心技術
* defineProperty()
* 訊息訂閱與釋出

4.雙向資料繫結
1). 雙向資料繫結是建立在單向資料繫結(model==>View)的基礎之上的
2). 雙向資料繫結的實現流程:
    * 在解析v-model指令時, 給當前元素新增input監聽
    * 當input的value發生改變時, 將最新的值賦值給當前表示式所對應的data屬性

 

 

----------------------假裝這裡有條分割線------------------

1. vue腳手架

用來建立vue專案的工具包
建立專案:
  npm install -g vue-cli
  vue init webpack VueDemo
  vue create 專案名稱
開發環境執行:
  cd VueDemo
  npm install
  npm run serve
生產環境打包釋出
  npm run build
  npm install -g serve
  serve dist
  http://localhost:5000

2. eslint

用來做專案編碼規範檢查的工具
基本原理: 定義了很多規則, 檢查專案的程式碼一旦發現違背了某個規則就輸出相應的提示資訊
有相應的配置, 可定製檢查

3. 元件化程式設計

vue檔案包含3個部分
  <template>
    <div></div>
  </template>
  <script>
      export default {
props: []/{}
          data(){},
computed: {}
        methods: {},
watch: {}
filters: {}
directives: {
            color:{
              bind(el,binding){}
              update(el,binding){}
            }
            或
            color(el,binding){}
}
components: {}
      }
  </script>
  <style>
  </style>
元件化編碼的基本流程
1). 拆分介面, 抽取元件
2). 編寫靜態元件
3). 編寫動態元件
  初始化資料, 動態顯示初始化介面
  實現與使用者互動功能
元件通訊的5種方式
props
vue的自定義事件
pubsub第三方庫
slot
vuex(後面單獨講)
props:
  父子元件間通訊的基本方式
  屬性值的2大型別:
      一般: 父元件-->子元件
      函式: 子元件-->父元件
隔層元件間傳遞: 必須逐層傳遞(麻煩)
兄弟元件間: 必須藉助父元件(麻煩)
vue自定義事件
  子元件與父元件的通訊方式
  用來取代function props
  不適合隔層元件和兄弟元件間的通訊
pubsub第三方庫(訊息訂閱與釋出)
  適合於任何關係的元件間通訊
slot
  通訊是帶資料的標籤
  注意: 標籤是在父元件中解析
vuex
  多元件共享狀態(資料的管理)
  元件間的關係也沒有限制
  功能比pubsub強大, 更適用於vue專案

4. ajax

相關庫:
  vue-resource: vue外掛, 多用於vue1.x
  axios: 第三方庫, 多用於vue2.x
vue-resource使用
  // 引入模組
  import VueResource from 'vue-resource'
  // 使用外掛
  Vue.use(VueResource)
   
  // 通過vue/元件物件傳送ajax請求
  this.$http.get('/someUrl').then((response) => {
    // success callback
    console.log(response.data) //返回結果資料
  }, (response) => {
    // error callback
    console.log(response.statusText) //錯誤資訊
  })
axios使用
  // 引入模組
  import axios from 'axios'
   
  // 傳送ajax請求
  axios.get(url)
    .then(response => {
      console.log(response.data) // 得到返回結果資料
    })
    .catch(error => {
  console.log(error.message)
    })

5. vue-router

vue用來實現SPA的外掛
使用vue-router
  1. 建立路由器: router/index.js
    new VueRouter({
      routes: [
        { // 一般路由
          path: '/about',
          component: about
        },
        { // 自動跳轉路由
          path: '/',
          redirect: '/about'
        }
      ]
    })
  2. 註冊路由器: main.js
      import router from './router'
      new Vue({
      router
      })
  3. 使用路由元件標籤:
      <router-link to="/xxx">Go to XXX</router-link>
      <router-view></router-view>
編寫路由的3步
  1. 定義路由元件    
  2. 對映路由
  3. 編寫路由2個標籤
巢狀路由
  children: [
      {
        path: '/home/news',
        component: news
      },
      {
        path: 'message',
        component: message
      }
    ]
向路由元件傳遞資料
  params: <router-link to="/home/news/abc/123">
  props: <router-view msg='abc'>
快取路由元件
  <keep-alive>
    <router-view></router-view>
  </keep-alive>
路由的程式設計式導航
this.$router.push(path): 相當於點選路由連結(可以返回到當前路由介面)
this.$router.replace(path): 用新路由替換當前路由(不可以返回到當前路由介面)
this.$router.back(): 請求(返回)上一個記錄路由



----------------------假裝這裡有條分割線------------------

1. vuex是什麼

github站點: https://github.com/vuejs/vuex
線上文件: https://vuex.vuejs.org/zh-cn/
簡單來說: 對應用中元件的狀態進行集中式的管理(讀/寫)

2. 狀態自管理應用

state: 驅動應用的資料來源
view: 以宣告方式將state對映到檢視
actions: 響應在view上的使用者輸入導致的狀態變化(包含n個更新狀態的方法)

 

3. 多元件共享狀態的問題

多個檢視依賴於同一狀態
來自不同檢視的行為需要變更同一狀態
以前的解決辦法
* 將資料以及操作資料的行為都定義在父元件
* 將資料以及操作資料的行為傳遞給需要的各個子元件(有可能需要多級傳遞)
vuex就是用來解決這個問題的

 

4. vuex的核心概念

1). state(資料)

vuex管理的狀態物件
它應該是唯一的
const state = {
xxx: initValue
}

2). mutations(操作資料的方法,影響原資料。必須為同步)

包含多個直接更新state的方法(回撥函式)的物件
誰來觸發: action中的commit('mutation名稱')
只能包含同步的程式碼, 不能寫非同步程式碼
const mutations = {
yyy (state, data) {
// 更新state的某個屬性
}
}

3). actions($store.dispatch觸發mutations方法 可以為非同步)

包含多個事件回撥函式的物件
通過執行: commit()來觸發mutation的呼叫, 間接更新state
誰來觸發: 元件中: $store.dispatch('action名稱') // 'zzz'
可以包含非同步程式碼(定時器, ajax)
const actions = {
zzz ({commit, state}, data1) {
commit('yyy', data2)
}
}

4). getters(相當於store中的計算屬性,對state中的資料操作後快取,不會影響原資料)

包含多個計算屬性(get)的物件
誰來讀取: 元件中: $store.getters.xxx
const getters = {
mmm (state) {
return ...
}
}

5). modules(store分割的模組)

包含多個module
一個module是一個store的配置物件
與一個元件(包含有共享資料)對應

6). 向外暴露store物件

export default new Vuex.Store({
state,
mutations,
actions,
getters
})

7). 元件中:

import {mapGetters, mapActions} from 'vuex'
export default {
computed: mapGetters(['mmm'])
methods: mapActions(['zzz'])
}

{{mmm}} @click="zzz(data)"

8). 對映store

import store from './store'
new Vue({
store
})

9). store物件

1.所有用vuex管理的元件中都多了一個屬性$store, 它就是一個store物件
2.屬性:
state: 註冊的state物件
getters: 註冊的getters物件
3.方法:
dispatch(actionName, data): 分發action

5. 將vuex引到專案中

1). 下載: npm install vuex --save

2). 使用vuex

1.store.js
import Vuex from 'vuex'
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules
})
2.main.js
import store from './store.js'
new Vue({
store
})