VUE框架第一部分:基礎知識及核心原理
VUE基礎概念
cn.vuejs.orgjavascript
Vue (讀音 /vjuː/,相似於 view) 是一套用於構建用戶界面的漸進式框架
特色:易用、靈活、高效
全家桶:vue + components(vue element / iview...) + vue-router + vuex + vue-cli
css
類庫 vs 插件 vs 組件 vs 框架
- 類庫:jquery、zepto、underscore...
- 插件:dialog、banner、drag、tab、iscroll...
- 組件:bootstrap、swiper...
- 框架:backbone、angular、vue、react、uni-app、react native、flutter...
聲明式和命令式
- 命令式編程:命令「機器」如何去作事情(how),這樣無論你想要的是什麼(what),它都會按照你的命令實現,例如for循環
- 聲明式編程:告訴「機器」你想要的是什麼(what),讓機器想出如何去作(how),例如數組內置方法forEach等
MVC & MVVM
- 傳統操做DOM模式
- MVC:model view controller
- MVVM:model view viewModel
<div id="app">
{{msg}}
</div>
<!-- IMPORT JS -->
<script src="node_modules/vue/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'hello world'
}
});
setTimeout(() => {
vm.msg = '你好世界';
}, 1000);
</script>
複製代碼
<div id="app">
人民幣:¥<input type="text" v-model='price'>元
<br>
美圓:${{price/8}}
</div>
<!-- IMPORT JS -->
<script src="node_modules/vue/dist/vue.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
price: 0
}
});
</script>
複製代碼
VUE的基礎語法
new Vue(options)
- 返回值vm(viewModel)
- el:不能掛載到html或者body上 =>querySelector
- data
- 數據值對於對象來講要先聲明,不然新增屬性無效(能夠基於vm.$set處理)
- vm.arr[0]=xxx 改變數組中的某一項視圖不會渲染,須要基於內置的方法,例如:push...
- 對象或者數組能夠總體替換值實現數據變視圖也變
- ...
mustache([ˈmʌstæʃ]) 小鬍子語法
經常使用的指令(directive)
- v-model
- v-html / v-text:取消小鬍子語法刷新中的閃爍問題
- v-bind(縮寫 :)
- v-once
- v-if 和 v-show
- v-for
- for in循環 & for of循環
- 遍歷數據類型的範圍
- 原型上方法遍歷(或者數組新增的xxx:xxx屬性遍歷)
- ......
- Symbol.iteratoer:Array、Set、Map、String、Arguments、NodeList...
- v-on 事件綁定
- v-on:xxx
- methods :和data相似,都會把方法掛載到vm實例上(this都是當前實例)
- @xxx
- @xxx="func" & @xxx="func($event,...)"
directive自定義指令
- Vue.directive([指令名,省略v-], function(el,bindings,vnode){}
- el當前元素
- bindings包含不少信息
- name:指令名,不包括 v- 前綴
- value:指令的綁定值
- oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用
- expression:字符串形式的指令表達式
- arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數爲 "foo"
- modifiers:包含修飾符的對象。例如:my-directive.foo.bar 中,修飾符對象 { foo: true, bar: true }
- vnode虛擬DOM
- ctx = vnode.context 獲取當前元素所在的上下文
- ctx[bindings.expression]=xxx 獲取上下文中的表達式變量,而且把指定的值賦值給它
- 鉤子函數
- bind:當用戶綁定指令時生效(只調一次)
- update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前(一個函數的方式就是把bind和update合在一塊兒的寫法)
- componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用
- unbind:只調用一次,指令與元素解綁時調用
- inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)
- 小練習:建立一個自定義指令控制文本框的校驗
事件修飾符
- 常規:.stop / .prevent / .once ...
- 按鍵:.enter 或者 .13 / .up / .down / .left / .right ...
- 組合修飾符
- ...
表單元素的處理
- 普通文本框 或者 文本域
- 單選框
- 複選框
- 下拉框
- 小案例:全選和非全選
計算屬性、過濾器、監聽器
- methods 普通方法
- filters 過濾器
- 只能應用到鬍子語法和v-bind中
- 小練習:輸入內容的單詞首字母大寫
- computed
- getter & setter
- 相對於普通方法來說,計算屬性是基於它們的響應式依賴進行緩存的
- 依賴data中的數據變量
- 小練習:輸入內容的單詞首字母大寫
- 小練習:全選和非全選
- watch
- 當須要在數據變化時執行異步或開銷較大的操做時應用監聽器
- 小練習:全選和非全選
- 小練習:數據異步綁定的處理
data(){
  return {
    checked:false,
    checkModel:[]
  }
},
watch:{
  checkModel(){
    if(this.checkModel.length==this.list.length){
      this.checked=true;
    }else{
      this.checked=false;
    }
  }
}
...
複製代碼
class和style綁定
- class的處理(對象語法、數組語法)
- 內聯樣式的處理
- ...
生命週期函數(鉤子函數)
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestory
- destory
- ...
經常使用的屬性方法
- $set : 設置響應式數據
- $el : 掛載的元素
- $destroy : 銷燬vue的實例;同時調用beforeDestroy destroyed
- $mount : 掛載真實DOM的方法
- $data : 響應式的對象
- $options: 是Vue的構造函數的參數
- $refs : 能夠用來獲取指定的元素對象 (非受控組件)
- $on : 訂閱
- $emit : 發佈
- $watch:監控
- ...
案例:選項卡
案例:購物車計算器
案例:商城類別篩選
雙向數據綁定的實現原理
- Object.defineProperty
- 實現的底層原理
function observer(obj) {
if (obj && typeof obj === 'object') {
for (let key in obj) {
if (!obj.hasOwnProperty(key)) break;
defineReactive(obj, key, obj[key]);
}
}
}
function defineReactive(obj, key, value) {
observer(value);
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newValue) {
observer(newValue);
if (value === newValue) return;
value = newValue;
}
});
}
function $set(data, key, value) {
defineReactive(data, key, value);
}
複製代碼
Vue 主要經過如下 4 個步驟來實現數據雙向綁定的:
- 實現一個監聽器 Observer:對數據對象進行遍歷,包括子屬性對象的屬性,利用 Object.defineProperty() 對屬性都加上 setter 和 getter。這樣的話,給這個對象的某個值賦值,就會觸發 setter,那麼就能監聽到了數據變化。
- 實現一個解析器 Compile:解析 Vue 模板指令,將模板中的變量都替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變更,收到通知,調用更新函數進行數據更新。
- 實現一個訂閱者 Watcher:Watcher 訂閱者是 Observer 和 Compile 之間通訊的橋樑 ,主要的任務是訂閱 Observer 中的屬性值變化的消息,當收到屬性值變化的消息時,觸發解析器 Compile 中對應的更新函數。
- 實現一個訂閱器 Dep:訂閱器採用 發佈-訂閱 設計模式,用來收集訂閱者 Watcher,對監聽器 Observer 和 訂閱者 Watcher 進行統一管理。
VUE中的組件(component)
組件的特色是:html
- 每一個組件就是一個自定義標籤
- 可複用
- 方便維護
- 方便拆分
- 每一個組件做用域隔離(互不干擾)
- 有完整的生命週期
- 有本身的響應式數據和各類方法(事件)
- ...
1.全局組件 & 組件的基本語法
在任何組件中能夠直接使用(不須要引入,直接在組件模板中調用便可) Vue.component(componentName,options)vue
- 組件名字中的一點規範
- kebab-case:只能調用
- PasalCase:既可相似前種方式調用,也能夠方式調用
- 調用組件的細節規範
- 採用雙閉合方式
- 單閉合方式不符合w3c規範(只能識別一個)
- template
- 每一個組件只能有一個根元素
- 模板字符串方式
- template標記方式
- slot插槽處理
- data必須是一個函數,保證不一樣組件之間的數據互不干擾(返回的對象中初始化數據)
- ...
<my-component>
<template v-slot:xxx 或者 #xxx>
永懷善意
</template>
</my-component>
{
templete:`<div>
<slot name='xxx'></slot>
</div>`
}
複製代碼
2.局部組件
- 建立組件:let componenName={...}
- 基於components屬性聲明組件:想用哪一個組件須要先聲明
- 使用組件
3.組件信息通信之父傳子:props屬性傳遞
<my-component aa='hhh' :bb='xxx'></my-component> 複製代碼
Vue.component('my-component',{
props:['aa','bb'],
...
})
複製代碼
- props中聲明的屬性和data同樣,是響應式數據,掛載到vm實例上,可控制視圖渲染
- props中的一些細節問題
- 命名大小寫:傳遞的是kebab-case格式,props中獲取的是camelCase駝峯命名
- 指定屬性的類型:props:{xxx:String,...}
- 指定屬性的默認值:props:{xxx:{type:String,default:'xxx',required:true}}
- type若是是一個數組,意爲指定的多類型皆能夠
- default能夠是一個函數,函數返回值是默認值
- validator自定義驗證規則函數:必須符合函數中指定的規則,返回true/false
- 傳遞的屬性值默認都是字符串格式,若是想要讓傳遞的值是數字、布爾、數組、對象等格式,咱們須要使用v-bind處理
- 樣式和class自動合併問題
4.vue的單向數據流
全部的 prop 都使得其父子 prop 之間造成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。java
Vue 的父組件和子組件生命週期鉤子函數執行順序能夠歸類爲如下 4 部分:node
- 加載渲染過程:父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
- 子組件更新過程:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
- 父組件更新過程:父 beforeUpdate -> 父 updated
- 銷燬過程:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
每次父級組件發生更新時,子組件中全部的 prop 都將會刷新爲最新的值。這意味着你不該該在一個子組件內部改變 prop。若是你這樣作了,Vue 會在瀏覽器的控制檯中發出警告。子組件想修改時,只能經過 $emit 派發一個自定義事件,父組件接收到後,由父組件修改。有兩種常見的試圖改變一個 prop 的情形 :react
- 這個 prop 用來傳遞一個初始值;這個子組件接下來但願將其做爲一個本地的 prop 數據來使用。 在這種狀況下,最好定義一個本地的 data 屬性並將這個 prop 用做其初始值
- 這個 prop 以一種原始的值傳入且須要進行轉換。 在這種狀況下,最好使用這個 prop 的值來定義一個計算屬性
5.組件信息通信之子改父:this.$emit
- 訂閱自定義事件:調用組件的時候基於屬性傳遞一個方法 (父)
<my-component @func='xxx'></my-component> new Vue({ methods:{ xxx(value){ //=>value是this.$emit時候傳遞的第二個參數值 } } }); 複製代碼
{
methods:{
xxx(){
this.$emit('func',10);
}
}
}
複製代碼
- 也能夠基於此方法實現兄弟組件(父子組件、隔代組件)之間的信息通訊
let eventBus=new Vue;
eventBus.$on('xxxA',this.func);
eventBus.$emit('xxxA');
複製代碼
6.基於ref實現父子組件信息通訊
- ref 若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子組件上,引用就指向組件實例,基於此能夠快速獲取和操做子組件中的數據
children是獲取組件和子組件的實例,只不過$children是一個數組集合,須要咱們記住組件順序才能夠
7.基於provide和inject實現祖先與後代的通訊
- 祖先組件基於provide註冊須要供後代組件使用的數據
{
provide:{
name:'hhh',
year:10
},
...
}
複製代碼
- 後代組件基於inject聲明須要使用的數據並調取使用
{
inject:['name'],
methods:{
func(){
let name=this.name;
}
}
}
複製代碼
VUE中的TRANSITION動畫
1. 什麼狀況下會用動畫
- 條件渲染 v-if
- 條件展現 v-show
- 動態組件 例如:vue-router控制組件渲染
- ...
2. 如何實現動畫
- 修改元素的樣式:style & class
- 使用JS實現動畫(前兩週在某些場景下都須要本身直接去操做DOM或者更加的麻煩)
- 使用vue內置的transition & transition-group
3. transition的基礎使用
- v-enter:定義進入過渡的開始狀態,在元素被插入以前生效,在元素被插入以後的下一幀移除
- v-enter-active:定義進入過渡生效時的狀態,在整個進入過渡的階段中應用,在元素被插入以前生效,在過渡/動畫完成以後移除
- v-enter-to: 定義進入過渡的結束狀態,元素被插入以後下一幀生效 ,在過渡/動畫完成以後移除
- v-leave: 定義離開過渡的開始狀態,在離開過渡被觸發時馬上生效,下一幀被移除
- v-leave-active:定義離開過渡生效時的狀態,在整個離開過渡的階段中應用,在離開過渡被觸發時馬上生效,在過渡/動畫完成以後移除
- v-leave-to: 定義離開過渡的結束狀態,在離開過渡被觸發以後下一幀生效,在過渡/動畫完成以後移除
- 基於 transiton 標記中的 name 屬性來進行動畫樣式區分
- 自定義過渡類名(例如:結合animate.css使用)
4.JAVASCRIPT中的動畫鉤子函數
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
...
>
</transition>
methods:{
beforeEnter: function (el,done) {
},
...
}
複製代碼
5. transition-group 處理多組元素動畫
- 若是在transition-group中使用v-for,須要設置:key惟一值
- 小練習:關鍵詞模糊匹配搜索
綜合實戰案例
1. 輪播圖的實現
2. TASK OA任務管理系統(俗稱TODO)