(1)Vue的生命周期 1)創建vue實例,初始化生命周期鉤子函數 2)數據檢測及方法和計算屬性代理。在數據檢測和初始化數據之前調用beforeCreated(),這時還獲取不到props或者data中的數據;數據、屬性、方法初始化之後,調用created(),可以訪問之前訪問不到的數據,但是組件還 ...
(1)Vue的生命周期
1)創建vue實例,初始化生命周期鉤子函數
2)數據檢測及方法和計算屬性代理。在數據檢測和初始化數據之前調用beforeCreated(),這時還獲取不到props或者data中的數據;數據、屬性、方法初始化之後,調用created(),可以訪問之前訪問不到的數據,但是組件還沒有掛載,$el屬性還沒有顯示,所以看不到組件。
3)判斷是否有el屬性,如果沒有就判斷是否調用了$mount方法,如果也沒有則停止解析。如果調用了二者之一,就繼續解析。
4)獲取視圖模板。判斷是否有template屬性,如果沒有則將el的視圖節點的outerhtml作為模板;如果有則將template視圖作為模板。
5)編譯模板。生成虛擬DOM,解析指令、組件。
6)將虛擬DOM掛載到真實DOM上。掛載前調用beforemount方法,掛在後調用mounted方法。
7)數據更新導致視圖更新。更新前調用beforeUpdate,更新後調用updated。
8)銷毀vue實例。銷毀前調用beforedestroy,銷毀後調用destroyed。
(2)keep-alive的生命周期
如果你需要在組件切換的時候,保存一些組件的狀態防止多次渲染,就可以使用 keep-alive 組件包裹需要保存的組件。
對於 keep-alive 組件來說,它擁有兩個獨有的生命周期鉤子函數,分別為 activated 和 deactivated 。用 keep-alive 包裹的組件在切換時不會進行銷毀,而是緩存到記憶體中並執行 deactivated 鉤子函數,命中緩存渲染後會執行 actived 鉤子函數。
(3)Vue組件通信
1、父子組件通信
父組件通過props傳遞數據給子組件,子組件通過$emit發送事件傳遞數據給父組件,這兩種方式是最常用的父子通信實現方法。
父子通信方式是單向數據流,父組件通過props傳遞數據,子組件不能直接修改props,而是必須通過發送事件的方式告知父組件修改數據。
2.非父子組件間的數據傳遞,兄弟組件傳值
對於這種情況可以通過查找父組件中的子組件實現,也就是 this.$parent.$children,在 $children 中可以通過組件 name 查詢到需要的組件實例,然後進行通信。
(4)路由
1、路由的鉤子函數
1)全局鉤子函數:beforeEach、afterEach
router.beforeEach(to, from , next) 全局鉤子函數,每次每一個路由改變的時候都得執行一遍。
to:即將要進入的目標路由對象;form:當前導航正要離開的路由;next:Function
next( ):進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是confirmed。
next( false):中斷當前的導航。
next( '/' ):跳轉到一個不同的地址。
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
router.afterEach全局後置鉤子,這些鉤子不會接受 next 函數也不會改變導航本身:
router.afterEach((to, from) => {
// ...
})
2)單個路由裡面的鉤子:beforeEnter、beforeLeave
你可以在路由配置上直接定義 beforeEnter 鉤子函數,在進入對應路由時調用對應的beforeEnter
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
3)組件內的鉤子函數:beforeRouteEnter 、beforeRouteUpdate 、beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用;不!能!獲取組件實例 `this`; 因為當守衛執行前,組件實例還沒被創建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被覆用時調用;舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候;由於會渲染同樣的 Foo 組件,因此組件實例會被覆用。而這個鉤子就會在這個情況下被調用。 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用; 可以訪問組件實例 `this`
}
}
2、路由跳轉的幾種方式
1)直接調用$router.push實現路由跳轉:
this.$router.push({
path: `/login/${id}`,
})
對應路由配置如下:
{
path: '/login/:id',
name: 'Login',
component: Login
}
在子組件中獲取參數值:
this.$route.params.id
2)通過路由屬性中的name來確定匹配的路由,通過params來傳遞參數。
this.$router.push({
name: 'Login',
params: {
id: id
}
})
對應路由配置如下:
{
path: '/login',
name: 'Login',
component: Login
}
在子組件中獲取參數值:
this.$route.params.id
3)使用path來匹配路由,然後通過query來傳遞參數。這種情況下 query傳遞的參數會顯示在url後面?id=?
this.$router.push({
path: '/login',
query: {
id: id
}
})
對應路由配置如下:
{
path: '/login',
name: 'Login',
component: Login
}
在子組件中獲取參數值:
this.$route.params.id
(5)組件中data為什麼是一個函數
一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝:
data: function () {
return {
count: 0
}
}
原因:對象為引用類型,當重用組件時,由於數據對象都指向同一個data對象,當在一個組件中修改data時,其他重用的組件中的data會同時被修改;而使用返回對象的函數,由於每次返回的都是一個新對象(Object的實例),引用地址不同,則不會出現這個問題
// 1.對象方式(所有重用的實例中的data均為同一個對象)
var data = {
x: 1
};
var vm1 = {
data: data
};
var vm2 = {
data: data
};
console.log(vm1.data === vm2.data);// true,指向同一個對象
// 2.函數方式(所有重用的實例中的data均為同一個函數)
var func = function () {
return {
x: 1
}
};
var vm3 = {
data: func
};
var vm4 = {
data: func
};
console.log(vm3.data() === vm4.data()); // false,指向不同對象
參考博文:https://blog.csdn.net/qq_33576343/article/details/82793894
(6)v-show 與 v-if 區別
v-show只是在display:none和display:block之間切換。無論初始條件是什麼都會被渲染出來,後面只需切換CSS,DOM還是一直保留。
v-if 初始值為false時,組件不會被渲染,直到條件為true,並且切換條件時會觸發銷毀/掛載組件。
對比來說,v-show在初始時有更高的開銷,但是切換開銷小,適於頻繁切換的場景;v-if初始渲染開銷小,切換時開銷更高,不適合經常切換的場景。
參考:https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5c024ecbf265da616a476638