Vue快速認識

1.Vue入門初識

1.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端)

1.2 基本使用

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

1.3 Vue對象的選項

1). el

el元素選擇 element
指定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' : {
		deep : true,
		handler : fun(value)
	}
另外一種添加監視方式: vm.$watch('xxx', funn)

1.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>

1.5 生命週期

vm/組件對象
生命週期圖
主要的生命週期函數(鉤子)
	created() / mounted(): 啓動異步任務(啓動定時器,發送ajax請求, 綁定監聽)
	beforeDestroy(): 作一些收尾的工做

1.6 自定義過濾器

1). 理解

對須要顯示的數據進行格式化後再顯示

2). 編碼

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

1.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

1.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'>

2.Vue構建

2.1. vue腳手架

用來建立vue項目的工具包
建立項目:
    npm install -g vue-cli
    vue init webpack VueDemo
開發環境運行:
    cd VueDemo
    npm install
    npm run dev
生產環境打包發佈
    npm run build
    npm install -g serve
    serve dist
    http://localhost:5000

2.2 eslint

用來作項目編碼規範檢查的工具
基本原理: 定義了不少規則, 檢查項目的代碼一旦發現違背了某個規則就輸出相應的提示信息
有相應的配置, 可定製檢查

2.3 組件化編程

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

2.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)
      })

2.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(): 請求(返回)上一個記錄路由

3. vuex

3.1 Vuex是什麼

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

3.2 狀態自管理應用

state: 驅動應用的數據源
view: 以聲明方式將state映射到視圖
actions: 響應在view上的用戶輸入致使的狀態變化(包含n個更新狀態的方法)

[外鏈圖片轉存失敗(img-7zYqBi3G-1566803111088)(https://vuex.vuejs.org/zh-cn/images/flow.png)]css

3.3 多組件共享狀態的問題

多個視圖依賴於同一狀態
來自不一樣視圖的行爲須要變動同一狀態
之前的解決辦法
	* 將數據以及操做數據的行爲都定義在父組件
	* 將數據以及操做數據的行爲傳遞給須要的各個子組件(有可能須要多級傳遞)
vuex就是用來解決這個問題的

[外鏈圖片轉存失敗(img-PD3yiIQB-1566803111091)(https://vuex.vuejs.org/zh-cn/images/vuex.png)]html

3.4 vuex的核心概念

在這裏插入圖片描述

1). state

vuex管理的狀態對象
它應該是惟一的
const state = {
	xxx: initValue
}

2). mutations

包含多個直接更新state的方法(回調函數)的對象
誰來觸發: action中的commit('mutation名稱')
只能包含同步的代碼, 不能寫異步代碼
const mutations = {
	yyy (state, data) { 
		// 更新state的某個屬性
	}
}

3). actions

包含多個事件回調函數的對象
經過執行: commit()來觸發mutation的調用, 間接更新state
誰來觸發: 組件中: $store.dispatch('action名稱')  // 'zzz'
能夠包含異步代碼(定時器, ajax)
const actions = {
	zzz ({commit, state}, data1) {
		commit('yyy', data2)
	}
}

4). getters

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

5). modules

包含多個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

3.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
	})

4.Vue源碼解讀

4.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自身的屬性

4.2 數據代理(MVVM.js)

1.經過一個對象代理對另外一個對象中屬性的操做(讀/寫)
2.經過vm對象來代理data對象中全部屬性的操做
3.好處: 更方便的操做data中的數據
4.基本實現流程
	1). 經過Object.defineProperty()給vm添加與data對象的屬性對應的屬性描述符
	2). 全部添加的屬性都包含getter/setter
	3). 在getter/setter內部去操做data中對應的屬性數據

4.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.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屬性
相關文章
相關標籤/搜索