1. vue雙向數據綁定原理
vue是採用數據劫持結合發佈-訂閱
的方式,通過object.defineProperty()
來劫持各個屬性的setter
,getter
,在數據發生變動時發佈消息給訂閱者,觸發相應的監聽回調來渲染視圖
第一步:
需要observer
的數據對象進行遞歸遍歷
,包括子屬性對象的屬性,都加上setter
,getter
,這樣的話,給這個對象的某個值賦值
,就會觸發setter
,那麼就能監聽到數據變化
簡單來說就是實現一個數據監聽器Observer,它能夠對數據對象的所以屬性進行監聽,如果有變動就可以拿到最新的值並通知訂閱者
第二步:
compile
解析模塊指令,講模塊中的變量替換成數據,然後初始化渲染頁面視圖,並將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變動,收到通知,更新視圖
簡單來說就是實現一個指令解析器Compile,對每個元素節點的指令進行掃描和解析,替換數據,綁定更新函數
第三步:
Watcher
訂閱者時Observer
和Compile
之間的通訊橋樑,主要做的事情是:
1.在自身實例化時往屬性訂閱器(dep
)裏面添加自己
2.自身必須有一個update()
方法
3.待屬性變動dep.notice()
通知時,能調用自身的update()
方法,並觸發Compile
中的綁定回調
簡單來說就是實現一個Watcher,作爲Observer和Compile的橋樑,能夠收到每個屬性變動的通知,綁定相應的回調函數,從而更新視圖
第四步:
MVVM
作爲數據綁定的入口,整合Observer,Compile和Watcher三者
,通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭建起Observer和Compile之間的通信橋樑,達到數據變化->視圖更新; 視圖交互變化->數據model變更的雙向綁定效果
MVVM就是實現Vue雙向數據綁定的根本
,MVVM本質上是MVC的改進版,即模型-視圖-視圖模型
,【模型】
指的是後端傳遞的數據。【視圖】
指的是所看到的頁面。【視圖模型】
MVVM的核心,他是連接view和model的橋樑
。它有兩個方向: 一個是將【模型】轉換成【視圖】,即後端傳遞的數據轉換成所看到的頁面
:實現方式是:數據綁定。第二個是【視圖】轉化成【模型】,即將所看到的頁面轉換成後端的數據
:實現方式是:DOM事件監聽。這兩個方向都實現的話,
我們稱之爲數據的雙向綁定
2.vue虛擬dom,diff算法
虛擬DOM就是爲了解決遊覽器性能問題
而被設計出來的。
就是用對象來模擬dom元素和嵌套關係,指的就是用js對象的形式
,來模擬頁面上的DOM嵌套關係
目的:實現頁面元素的高效更新,避免大量無謂的計算(若一次操作中有10次更新DOM的動作,虛擬DOM不會立即去操作DOM,而是將10次更新的diff內容保存到本地一個JS對象中,最終將這個JS對象一個姓attch到DOM樹上,再進行後續操作
)
作用:用來比較兩次DOM結構
web界面由DOM樹(樹的意思就是數據結構
)來搭建,當其中一部分發生變化時,其實就時對應某個DOM節點發生了變化
diff算法是作爲DOM的加速器
,改進優化了頁面渲染的基礎和性能保障
用js對象表示dom樹結構,用這個樹建立一個真正的dom樹,插入到文檔中,狀態更新
,重新構造一棵新樹,兩樹比較差異,把差異應用到真的dom樹上,更新視圖
3. 組件 通訊
1.父傳子
父組件是通過props屬性給子組件通信的
父組件代碼:
<template>
<div>
<h2>{
{
msg}}</h2>
<Son :faMsg="msg"></Son>
</div>
</template>
<script>
import Son from "./Son";
export default {
name:"HelloWorld",
data(){
return{
msg:"父組件"
}
},
components:{
Son}
}
</script>
子組件代碼:
<template>
<div>
<h2>{
{
sonMsg}}</h2>
<p>子組件接收到的內容是:{
{
faMsg}}</p>
</div>
</template>
<script>
export default {
name:"Son",
data(){
return{
sonMsg:"子組件"
}
},
props:['faMsg'], //接收faMsg值
//還可以這樣,上面的不是很嚴謹
props:{
faMsg:{
type:String,
default:"123"
}
}
}
</script>
在父組件中給子組件標籤上綁定一個屬性, 屬性上掛載需要傳遞的值
在子組件通過props:[“自定義屬性名”]來接收數據
子傳父:
(1) 在父組件中給子組件標籤綁定一個自定義事件,給這個事件掛載需要調用的方法
(2) 在子組件的方法通過this.$emit(‘自定義事件名’)來調用這個方法
父組件代碼:
<template>
<div>
<h2>{
{
msg }}</h2>
<p>父組件接手到的內容:{
{
username }}</p>
<son psMsg="我是你爸爸" @transfer="getUser"></son>
<!-- 監聽子組件觸發的transfer事件,然後調用getUser方法 -->
</div>
</template>
<script>
import son from './Son'
export default {
name: 'HelloWorld',
data () {
return {
msg: '父組件',
username:'',
}
},
components:{
son},
methods:{
getUser(msg){
this.username= msg
}
}
}
</script>
子組件代碼:
<template>
<div class="son">
<p>{
{
sonMsg }}</p>
<p>子組件接收到內容:{
{
psMsg }}</p>
<!--<input type="text" v-model="user" @change="setUser">-->
<button @click="setUser">傳值</button>
</div>
</template>
<script>
export default {
name: "son",
data(){
return {
sonMsg:'子組件',
user:'子傳父的內容'
}
},
props:['psMsg'],
methods:{
setUser:function(){
this.$emit('transfer',this.user)//觸發transfer方法,this.user 爲向父組件傳遞的數據
}
}
}
</script>
兄弟通信: 比如說vuex 就可以說是一個兄弟通信
4. vuex
首先我們要知道Vuex是一個專爲vue.js應用程序開發的狀態管理模式,它由五部分組成:
分別是:state,actions,mutations,getters,modules
vuex的五部分分別是:
- state:存儲狀態
- actions:可以包含異步操作
- getters:類似vue組件中的計算屬性,會對state數據進行計算(會被緩存)
- mutations:唯一可以對state數據修改的場所
- modules:模塊化管理倉庫,每個模塊都擁有自己的 state,actions,mutations,getters,modules
Vuex一般用來存儲在vue.js中大量出現的數據,比如說token,我們就可以把token存放在Vuex中,當然購物車也是要用到Vuex的.
數據持久化
問題:存儲在vuex中的狀態,刷新頁面會丟失。
爲了解決刷新頁面數據丟失,纔有了數據持久化。
最簡單的做法就是利用插件 vuex-persistedState
1.安裝
cnpm i vuex-persistedState -S
備註:
-S 是 --save的簡寫,意思是:把插件安裝到dependencies(生成環境依賴)中
-D 是 --save-dev的簡寫,意思是:把插件安裝到devDependencies(開發環境依賴)中
2.使用
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
plugins: [createPersistedState({
storage: sessionStorage,
key: "token"
})]//會自動保存創建的狀態。刷新還在
})
參數:
storage:存儲方式。(sessionStorage,localStarage) key:定義本地存儲中的key
模塊化管理數據(modules)
1.什麼時候需要用到模塊
管理vuex數據
項目龐大,數據信息量特別大的時候,我們可以考慮分模塊形式管理數據,比如user模塊管理用戶信息數據,cart模塊管理購物車數據,shop模塊管理商品信息數據
5. vue-router(路由原理,路由守衛,路由傳參)
路由實現原理:
概念:
通過改變URL,在不重新請求頁面的情況下,更新頁面視圖。
實現方式:
vue-router通過hash
與History interface
兩種方式實現前端路由,更新視圖但不重新請求頁面”是前端路由原理的核心之一,目前在瀏覽器環境中這一功能的實現主要有兩種方式:
1.hash
---- 利用URL中的hash(’#’);
2.利用History interface
在HTML5中的新增方法
6. vue生命週期
簡單粗暴:
答: 總共分爲8個階段。創建前/後 , 掛載前/後 , 更新前/後 , 銷燬前/後
。
創建前/後: beforeCreated
創建前,vue實例的掛載元素$el
和數據對象data都是undefined,還未初始化。在created階段/創建後,vue實例的數據對象data有了,$el還沒有。
掛載前/後: beforeMount
掛載前,vue實例的el
和data
都初始化了,但是還沒有掛載html 到頁面上。在Mounted
階段/掛載後,模板中的 HTML 渲染到 HTML 頁面中,此時一般可以做一些 ajax 操作,mounted 只會執行一次。
更新前/後: 當data變化時,會觸發beforeUpdate
和updated
方法
銷燬前/後: 在destroy
階段/銷燬前,對data的改變不會再觸發週期函數,說明此時vue實列已經解除了事件監聽和dom綁定,但是dom結構依然存在。destroyed
階段,組件銷燬
7. 自定義指令,自定義過濾器
8. 自定義組件
9. 常用的指令,修飾符
10. vue2.0和vue3.0的區別
11. keep-alive
概念:
是Vue的內置組件,當它包裹動態組件時,會緩存不活動的組件實例,而不是銷燬它們。
keep-alive是一個抽象組件:它自身不會渲染一個DOM元素,也不會出現的父組件鏈中。
作用:
在組件切換的過程中,把切換出去的組件保留在內存中,防止重複渲染DOM,減少加載事件以及性能消耗,提高用戶體驗性
原理:
在 created
鉤子函數調用時將需要緩存的 VNode 節點保存在 this.cache
中/在 render
(頁面渲染) 時,如果VNode
的 name
符合緩存條件(可以用 include
以及 exclude
控制),則會從 this.cache
中取出之前緩存的 VNode
實例進行渲染
VNode: 虛擬DOM,其實就是一個JS對象
參數:
- include - 字符串或者正則表達式。只有匹配的組件會被緩存。
- exclude - 字符串或正則表達式。然後匹配的組件都不會緩存。
- max - 數字。最多可以緩存多少組件實例
對生命週期函數變化:
被包含在keep-alive中的組件,會多出來兩個生命週期的鉤子函數,activated
和 deactiveated
1.activated
在keep-alive
組件激活時調用
2.deactivated
在keep-alive
組件離開時調用
//正常的生命週期:beforeRouterEnter --> created -->mounted --> updated --> destroyed
//使用keepAlive後生命週期:
//首次進入緩存頁面 :beforeRouterEnter --> created -->mounted --> updated --> destroyed
//再次進入緩存頁面 :beforeRouteEnter --> activated --> deactivated
//注:
//1、這裏的activated非常有用,因爲頁面被緩存時,created,mounted等生命週期均失效,你若想進行一些操作,那麼可以在activated內完成(下面會舉個栗子:列表頁回到上次瀏覽位置)
//2、activated keep-alive組件激活時調用,該鉤子在服務器端渲染期間不被調用。
//3、deactivated keep-alive組件停用時調用,該鉤子在服務端渲染期間不被調用
可以結合Router中的meta,來緩存部分頁面
12. 多環境變量
13. 對axios封裝,(url統一管理,axios請求攔截,響應攔截,函數封裝)
14. element-ui,vant-ui 按需引入
15. sass配置
16. rem , vw/vh 適配
rem適配:
使用vant裏面的遊覽器適配,
Vant 中的樣式默認使用 px 作爲單位,如果需要使用 rem 單位,推薦使用以下兩個工具:
postcss-pxtorem 是一款 postcss 插件,用於將單位轉化爲 rem
lib-flexible用於設置 rem 基準值
安裝 lib-flexible
和 postcss-plugin-px2rem
cnpm i lib-flexible postcss-plugin-px2rem --save-dev
配置rem: mian.js 導入
import 'lib-flexible/flexible'; //rem 就可以生效了
配置px–> rem:創建vue.config.js
//可以在此配置的基礎上根據項目需求進行修改。
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-plugin-px2rem')({
rootValue:75, //換算基數, 默認100 ,這樣的話把根標籤的字體規定爲1rem爲50px,這樣就可以從設計稿上量出多少個px直接在代碼中寫多上px了。
// unitPrecision: 5, //允許REM單位增長到的十進制數字。
//propWhiteList: [], //默認值是一個空數組,這意味着禁用白名單並啓用所有屬性。
// propBlackList: [], //黑名單
// exclude: /(page_pc)/i, //默認false,可以(reg)利用正則表達式排除某些文件夾的方法,例如/(node_module)/ 。如果想把前端UI框架內的px也轉換成rem,請把此屬性設爲默認值
exclude: /node_modules/i,
// selectorBlackList: ['van-'], //要忽略並保留爲px的選擇器,我們一般不轉換vantui中的大小
// ignoreIdentifier: false, //(boolean/string)忽略單個屬性的方法,啓用ignoreidentifier後,replace將自動設置爲true。
// replace: true, // (布爾值)替換包含REM的規則,而不是添加回退。
mediaQuery: false, //(布爾值)允許在媒體查詢中轉換px。
minPixelValue: 3 //設置要替換的最小像素值(3px會被轉rem)。 默認 0
}),
]
}
}
},
}