一、 vue 有多少個(gè)生命周期,每個(gè)作用是什么?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
<script src="https://cdn.bootcss.com/vue/2.2.1/vue.min.js"></script>
</head>
<body>
<div id="app">
<template>
<div>
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
<hr>
<button onclick="vm.$destroy()">此按鈕用來銷毀實(shí)例</button>
</div>
</template>
</div>
<script>
Vue.component('button-counter', {
template: '<button @click="increment">我是按鈕{{ counter }}</button>',
data: function() {
return {
counter: 0
}
},
methods: {
increment(){
this.counter ++;
this.$emit('increment')
}
}
})
var vm = new Vue({
el: "#app",
data() {
return {
total: 0
}
},
methods: {
incrementTotal(){
this.total ++;
}
},
// 組件生命周期
beforeCreate() { // 在實(shí)例創(chuàng)建之后,在數(shù)據(jù)初始化之前被調(diào)用
console.log('beforeCreated-1')
},
created() { // 在數(shù)據(jù)初始化之后被調(diào)用,如果你的頁面進(jìn)來的時(shí)候就調(diào)用接口,那么created是第一選擇
console.log('created-2')
},
beforeMount() { // 在數(shù)據(jù)渲染之前被調(diào)用
console.log('beforeMount-3')
},
mounted() { // 實(shí)例創(chuàng)建完成、數(shù)據(jù)初始化、渲染頁面數(shù)據(jù)后,才被調(diào)用
console.log('mounted-4')
},
beforeUpdate() { // 在數(shù)據(jù)改變時(shí)被調(diào)用
console.log('beforeUpdate-5')
},
updated() { // 數(shù)據(jù)被更新之后
console.log('updated-6')
},
//keep-alive生命周期有兩個(gè) (activated , deactivated)
activated() { // keep-alive 組件激活時(shí)調(diào)用,也就是說在路由切換時(shí)被調(diào)用,注意要配合keep-alive使用才會(huì)被調(diào)用, <keep-alive>
// 可以看下別人寫的 https://www.cnblogs.com/sysuhanyf/p/7454530.html
},
deactivated(){// keep-alive 組件停用時(shí)調(diào)用,也可以理解成在路由切換的會(huì)自動(dòng)停用組件,
// 可以看下別人寫的 https://www.cnblogs.com/sysuhanyf/p/7454530.html
},
beforeDestroy() { // 實(shí)例銷毀前被調(diào)用
console.log('beroreDestroy-9')
},
destroyed() { //實(shí)例銷毀后被調(diào)用
console.log('destroyed-10')
}
})
</script>
</body>
</html>
|
二、 vue路由有多少個(gè)鉤子,每個(gè)作用是什么?
1. beforeEach 全局路由鉤子,只要頁面路由改變就會(huì)執(zhí)行,鉤子有是三個(gè)參數(shù) to 、from 、next
export default {
name: 'app',
data() {
return {
}
},
mounted() {
this.$router.beforeEach((to, from, next) => {
console.log(to, from)
next()
})
}
}
to 要去哪個(gè)頁面 返回信息如下圖
from 是我從哪個(gè)頁面過來的,和to參數(shù)格式一樣,只不過path不同
next 是一個(gè)執(zhí)行的參數(shù) 必須要加上next(),不然路由不會(huì)跳轉(zhuǎn)

2. afterEach 全局路由鉤子 有兩個(gè)參數(shù) to 、from
這兩個(gè)參數(shù)和beforeEach相同,唯一的區(qū)別是afterEach鉤子是路由跳轉(zhuǎn)之后才被執(zhí)行
this.$router.afterEach((to, from) => {
console.log(to, from)
})
3. beforeEnter 這個(gè)一般情況下用不到,在路由頁面配置 beforeEnter,在進(jìn)入這個(gè)路由后執(zhí)行
routes: [{
path: '/Hello',
name: 'Hello',
component: Hello
},
{
path: '/index',
component: index,
children: [
{ path: 'world', component: world ,
beforeEnter: (to, from, next) => {
// 執(zhí)行邏輯
next()
}
},
{ path: 'world_childen', component: world_childen },
]
}
]
4. beforeRouteEnter 組件私有鉤子
組件私有的鉤子,組件被調(diào)用事執(zhí)行,在beforeRouteEnter這個(gè)鉤子里面沒有this
因?yàn)樵谶@個(gè)鉤子執(zhí)行的時(shí)候組件的實(shí)例還沒有創(chuàng)建,所以打印this是undefined
在next里面使用vm.name可以代替 this。
to 返回的信息是當(dāng)前頁面路由信息
from 返回的是從哪里過來的,和beforeEach 有點(diǎn)差異
export default {
data() {
return {
name: 'web_珂珂'
}
},
beforeRouteEnter(to, from, next){
console.log(this) // undefined
next(vm => {
console.log(vm.name) // web_珂珂
});
}
}
5. beforeRouteUpdate 組件私有鉤子,只有在組件被多次調(diào)用并且路由有變的的時(shí)候才會(huì)執(zhí)行
比如: A頁面調(diào)用了當(dāng)前組件,B頁面也調(diào)用了當(dāng)前組件,但是他們的路由變化了,beforeRouteUpdate就會(huì)被執(zhí)行
beforeRouteUpdate this是指向?qū)嵗?br>
html:
// 類似于這樣 兩個(gè)router-link都調(diào)用world組件,但是參數(shù)不同,就會(huì)被執(zhí)行
<router-link to="/index/world">導(dǎo)航二</router-link>
<router-link to="/index/world?name=web_keke">測(cè)試beforeRouteUpdate鉤子</router-link>
<script>
export default {
data() {
return {
name: 'web_珂珂'
}
},
beforeRouteUpdate(to, from, next){
console.log(this.name) // web_珂珂
console.log(to,from)
next()
}
}
</script>
6. beforeRouteLeave 從當(dāng)前組件的跳轉(zhuǎn)別的路由頁面執(zhí)行,就是離開的時(shí)候執(zhí)行
export default {
data() {
},
beforeRouteLeave (to, from, next) {
console.log(to, from)
next()
}
}
三、computed計(jì)算屬性與methods方法的區(qū)別?
computed 在數(shù)據(jù)沒有更新的情況下,computed緩存數(shù)據(jù),下次進(jìn)來還是讀取緩存的數(shù)據(jù)。
而methods方法會(huì)每次都會(huì)執(zhí)行,不會(huì)走緩存,舉個(gè)例子:
<template>
<div>
<!-- computed -->
我是computed 只要數(shù)據(jù)沒有更新,我會(huì)讀取緩存,不會(huì)重新計(jì)算
<p>
數(shù)量:{{ computedCount }}
</p>
<p>
數(shù)量:{{ computedCount }}
</p>
<p>
數(shù)量:{{ computedCount }}
</p>
<hr>
<!-- 方法 -->
我是methods方法,每次都會(huì)重新調(diào)用methodsCount()函數(shù)
<p>
數(shù)量:{{ methodsCount() }}
</p>
<p>
數(shù)量:{{ methodsCount() }}
</p>
</div>
</template>
<script>
export default {
data() {
return {
count: 1
}
},
// 計(jì)算
computed: {
computedCount(){
return this.count + 100
}
},
// 方法
methods: {
methodsCount(){
return this.count + 100
}
}
}
</script>

四、自定義指令 directive
vue 有他們自己內(nèi)置的指令如v-model, 還可以自己定義一些指令(directive),自定義指令可以寫成局部的,也可以寫成全局的,下面有個(gè)回車搜索的案例(這個(gè)還是我之前的一個(gè)朋友教我的-_-"),用于多個(gè)頁面搜索框輸入直接回車就可以調(diào)用方法
鉤子函數(shù) 和 鉤子函數(shù)參數(shù)
1. 全局指令
全局的寫法我在main.js里面寫的,在任何組件都可以用
Vue.directive('keyup-enter',{
inserted(el, binding) {
let $inputs = el.getElementsByTagName('input')
Array.from($inputs).forEach( $item => {
$item.addEventListener('keydown', event => {
let e = event || window.event
if (e.keyCode === 13) {
if (binding.value) {
setTimeout(() => {
binding.value()
}, 100)
}
}
})
})
}
})
然后在組件中調(diào)用keyup-enter指令,
把指令綁定到最外層的div上面 如,然后在輸入框輸入文本按回車
<template>
<!-- 這里綁定指令 v-keyup-enter -->
<div v-keyup-enter="getName">
名稱:
<input type="text" v-model="name">
年齡:
<input type="text" v-model="age">
</div>
</template>
<script>
export default {
data() {
return {
name: '珂珂',
age: '26'
}
},
methods: {
getName() {
console.log(this.name) // 珂珂
console.log(this.age) // 26
}
}
}
</script>

2. 局部指令
比如有個(gè)需求,要求頁面一進(jìn)來,就讓某一樣文本,添加一個(gè)顏色,并且讓這個(gè)文字翻轉(zhuǎn),或者只有第一次需要添加顏色,這中情況使用指令是最合適的
v-reverse 就是自定義的指令名稱
<template>
<div>
<p v-reverse>{{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '"-_-我是菜鳥',
}
},
directives: {
reverse: {
inserted(el) {
el.innerHTML = el.innerHTML.split('').reverse().join(''); // 鳥菜是我-_-"
el.style.color = 'red';
console.log(el) // <p style="color: red;">鳥菜是我-_-"</p>
}
}
}
}
</script>

五、 keep-alive 緩存
詳解 keep-alive
keep-alive有兩個(gè)生命周期 activated和deactivated,activated是組件被緩存的時(shí)候執(zhí)行,deactivated是離開緩存組件的時(shí)候執(zhí)行。
keep-alive屬性 如: <keep-alive include="Hello"> 緩存Hello組件
include - 字符串或正則表達(dá)式。只有名稱匹配的組件會(huì)被緩存。
exclude - 字符串或正則表達(dá)式。任何名稱匹配的組件都不會(huì)被緩存。
max - 數(shù)字。最多可以緩存多少組件實(shí)例
在Hello中切換tab到內(nèi)容二選項(xiàng),然后在跳轉(zhuǎn)的world組件后,在切回到Hello組件中,你會(huì)發(fā)現(xiàn)還是剛才的內(nèi)容二的文本,他并沒有顯示初始化的內(nèi)容一的文本,這樣就實(shí)現(xiàn)了緩存,另外keep-alive屬性include 設(shè)置的名稱是你要緩存的組件中寫的那個(gè)name名稱,如果名字不統(tǒng)一,緩存則無效。
如果想緩存多個(gè)組件,可以以逗號(hào)分隔,如: <keep-alive include="Hello, world">
緩存方式一、
app.vue
<template>
<div id="app">
<div class="nav">
<ul>
<router-link
v-for="(item, index) in arr"
:key="index"
:to="item.routerPath">
{{item.routerName}}
<br><br><br>
</router-link>
</ul>
</div>
<div class="view-box">
// 這里緩存組件Hello
<keep-alive include="Hello">
<router-view></router-view>
</keep-alive>
</div>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
active: '/Hello',
arr: [
{
routerName: '我是hello組件',
routerPath: '/Hello'
},
{
routerName: '我是world組件',
routerPath: '/world'
}
]
}
}
}
</script>
Hello.vue
<template>
<div class="hello">
<ul>
<li v-for="(item, index) in navArr" :key="index">
<button
@click="tab(item.tab)"
:class="{ active : tabShow == item.tab }"
>
{{ item.name }}
</button>
</li>
</ul>
<div class="box">
<div :is="tabShow"></div>
</div>
</div>
</template>
<script>
let A = {
template:`<h3>我是內(nèi)容一的信息11111</h3>`
}
let B = {
template:`<h3>我是內(nèi)容二的信息22222222222</h3>`
}
export default {
name:'Hello', // 這個(gè)name要和 keep-alive中include 設(shè)置的名字統(tǒng)一,否則無效
data () {
return {
tabShow:'A',
navArr: [
{
name: '內(nèi)容一',
tab: 'A'
},
{
name: '內(nèi)容二',
tab: 'B'
}
]
}
},
components: {
'A': A,
'B': B
},
methods: {
tab(currentShowTab){
this.tabShow = currentShowTab;
}
},
activated(){ // 組件被緩存的時(shí)候執(zhí)行
console.log('組件被緩存的時(shí)候執(zhí)行')
},
deactivated(){ // 離開緩存組件的時(shí)候執(zhí)行
console.log('離開緩存組件的時(shí)候執(zhí)行')
}
}
</script>
緩存方式二、
配合router路由去動(dòng)態(tài)緩存, 這種方式 keep-alive 就是根據(jù)路由配置里面來實(shí)現(xiàn)的
index.js (router下的index.js文件)
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '../components/Hello'
import index from '../components/index'
import world from '../components/world'
Vue.use(Router)
export default new Router({
routes: [{
path: '/Hello',
name: 'Hello',
component: Hello,
meta: {
keepAlive: true // 設(shè)置為緩存
}
},
{
path: '/world',
name: 'world',
component: world,
meta:{
keepAlive: false //設(shè)置為不緩存
}
}
]
})
然后修改app.vue
<template>
<div id="app">
<div class="nav">
<ul>
<router-link v-for="(item, index) in arr" :key="index" :to="item.routerPath">
{{item.routerName}}
<br><br><br>
</router-link>
</ul>
</div>
<div class="view-box">
// 修改為根據(jù)路由配置來實(shí)現(xiàn)緩存某些頁面
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</div>
</template>
