一、前端路由vue-router介紹
Vue-Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度內建,讓建構單頁面應用變得易如反掌。包含的功能有:
- 嵌套的路由/視圖表
- 子產品化的、基于元件的路由配置
- 路由參數、查詢、通配符
- 基于 Vue.js 過渡系統的視圖過渡效果
- 細粒度的導航控制
- 帶有自動激活的 CSS class 的連結
- HTML5 曆史模式或 hash 模式,在 IE9 中自動降級
- 自定義的滾動條行為
vue + vue-router 主要是用來做 單頁面應用(Single Page Application)。
1、為什麼要做單頁面應用?
(1)傳統的開發方式
url改變後,立馬發送請求,響應整個頁面,有可能資源過多,傳統的開發會讓前端的頁面出現“白屏”。
使用者體驗不好。
(2)SPA單頁面應用
SPA:Single Page Application
錨點值改變後,不會立刻發送請求,而是在某個合适的時機,發送ajax請求,局部改變頁面中的資料。
頁面不立刻跳轉,使用者體驗好。
2、前端路由的實作原理
前端路由:
1.錨點值監視; 2.ajax擷取動态的資料; 3.核心點是錨點值的改變;
前端中的 vue/react/angular 都很适合做單頁面應用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="#/login">登入頁面</a>
<a href="#/register">注冊頁面</a>
<div id="app">
</div>
<script type="text/javascript">
// 擷取div
var oDiv = document.getElementById('app');
window.onhashchange = function () {
console.log(location.hash);
// 根據不同的錨點值,對頁面不同的切換
switch (location.hash) {
case '#/login':
oDiv.innerHTML = '<h2>登入頁面</h2>';
break;
case '#/register':
oDiv.innerHTML = '<h2>注冊頁面</h2>';
break;
default:
// statements_def
break;
}
}
</script>
</body>
</html>
(1)window.onhashchange介紹
當一個視窗的 hash (URL中'#'後面的部分)改變時就會觸發 onhashchange 事件。
onhashchange 事件在目前url的錨點部分(以'#'号為開始)發生改變時觸發。
錨部分的執行個體:指定目前URL為http://www.example.com/test.htm#part2 - 這個 URL 中的錨部分為 #part2。
(2)onhashchange調用事件方法
- 通過設定Location 對象 的 location.hash 或 location.href 屬性修改錨部分。
- 使用不同書簽導航到目前頁面(使用"後退" 或"前進"按鈕)
- 點選連結跳轉到書簽錨
3、根據不同錨點切換頁面效果
(1)初始頁面顯示如下:

(2)點選登入頁面
(3)點選注冊頁面
二、vue-router使用
1、用NPM下載下傳安裝vue-router
(venv) MacBook-Pro:vue_study hqs$ cd 03-vue-router/
(venv) MacBook-Pro:03-vue-router hqs$ ls
01-前端路由實作原理.html vue.js
(venv) MacBook-Pro:03-vue-router hqs$ npm init --yes
Wrote to /Users/hqs/PycharmProjects/vue_study/03-vue-router/package.json:
{
"name": "03-vue-router",
"version": "1.0.0",
"description": "",
"main": "vue.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
(venv) MacBook-Pro:03-vue-router hqs$ npm install vue-router -S
[email protected] /Users/hqs/PycharmProjects/vue_study/03-vue-router
└── [email protected]
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
檢視項目檔案目錄:
2、vue-router應用執行個體
<body>
<div id="app"></div>
<script type="text/javascript" src="vue.js"></script>
<!--1.引入vue-router的對象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<!--全局的VueRouter對象 vue-router還提供了兩個全局的元件router-link / router-view-->
<script type="text/javascript">
// 2.讓Vue使用該VueRouter建立
Vue.use(VueRouter);
var Login = { // 元件建立
template:`
<div>登入頁面</div>
`
};
var Register = { // 元件建立
template:`
<div>注冊頁面</div>
`
};
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/login', // login路由
component:Login
},
{
path:'/register',
component:Register
}
]
});
var App = { // App:入口元件
// router-link預設會被渲染為a标簽,to屬性預設會被渲染為href屬性
// router-view是路由元件的出口
template:`
<div>
<router-link to="/login">登入頁面</router-link>
<router-link to="/register">注冊頁面</router-link>
<router-view></router-view>
</div>
`
};
new Vue({ // Vue執行個體化對象
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>` // 入口元件
});
</script>
</body>
注意要點:
(1)<router-link>元件和<router-view>元件
全局的VueRouter對象 vue-router 還提供了兩個全局的元件router-link / router-view。
<router-link>
元件支援使用者在具有路由功能的應用中 (點選) 導航。 通過
to
屬性指定目标位址,預設渲染成帶有正确連結的
<a>
标簽,可以通過配置
tag
屬性生成别的标簽.。另外,當目标路由成功激活時,連結元素自動設定一個表示激活的 CSS 類名。
<router-view>
元件是一個 functional 元件,渲染路徑比對到的視圖元件,是所有路由元件的出口。
<router-view>
渲染的元件還可以内嵌自己的
<router-view>
,根據嵌套路徑,渲染嵌套元件。
var App = {
// router-link預設會被渲染為a标簽 to屬性預設會被渲染為href屬性
// router-view是路由元件的出口
template:`
<div>
<router-link to="/login">登入頁面</router-link>
<router-link to="/register">注冊頁面</router-link>
<router-view></router-view>
</div>
`
};
(2)報錯Cannot read property 'matched' of undefined
這種問題就是因為自己建立的router對象沒有被Vue執行個體化對象所使用:
new Vue({ // Vue執行個體化對象
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>` // 入口元件
});
(3)頁面通過router-view渲染
1)點選前效果:
可以看到router-link預設會被渲染為a标簽,to屬性預設會被渲染為href屬性。
2)點選後效果:
(4)小結
當你在頁面通路login時,router-link對應着的路徑是'/login',加載對應的component元件:Login,component元件找一個出口渲染出來:router-view。
3、命名路由
有時候,通過一個名稱來辨別一個路由顯得更友善一些,特别是在連結一個路由,或者是執行一些跳轉的時候。你可以在建立 Router 執行個體的時候,在
routes
配置中給某個路由設定名稱。
給目前的配置路由資訊對象設定name屬性。
對上面代碼做如下修改:
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/login',
name:'login', // 設定路由名稱
component:Login
},
{
path:'/register',
name:'register', // 設定路由名稱
component:Register
}
]
});
var App = {
// 不使用to屬性通路路由,改用動态命名路由綁定
// 要連結到一個命名路由,可以給 router-link 的 to 屬性傳一個對象:
template:`
<div>
<router-link :to="{name:'login'}">登入頁面</router-link>
<router-link :to="{name:'register'}">注冊頁面</router-link>
<router-view></router-view>
</div>
`
};
4、總結Vue Router流程
(1)引入vue-router對象子產品
<script type="text/javascript" src="vue.js"></script>
<!--引入vue-router的對象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
該子產品預設會抛出一個VueRouter對象,另外還有兩個全局的元件router-link和router-view。
(2)讓Vue使用該VueRouter建立
// 如果使用子產品化機制程式設計,導入Vue和VueRouter,要調用Vue.use(VueRouter)
<script type="text/javascript">
// 讓Vue使用該VueRouter建立
Vue.use(VueRouter);
// 代碼省略
</script>
(3)建立路由對象
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/login',
name:'login', // 設定路由名稱
component:Login
},
{
path:'/register',
name:'register', // 設定路由名稱
component:Register
}
]
});
(4)路由對象挂載到vue執行個體化對象中
var App = {
// 不使用to屬性通路路由,改用動态命名路由綁定
// 要連結到一個命名路由,可以給 router-link 的 to 屬性傳一個對象:
template:`
<div>
<router-link :to="{name:'login'}">登入頁面</router-link>
<router-link :to="{name:'register'}">注冊頁面</router-link>
<router-view></router-view>
</div>
`
};
new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>`
});
三、路由參數(範式)
在vue-router路由中,傳參方式一般分兩種。如下所示:
(1)xxx.html#/user/1 params 動态路由參數
(2)xxx.html#/user?userId=2 query 查詢
示例代碼如下所示:
<body>
<div id="app"></div>
<script type="text/javascript" src="vue.js"></script>
<!--1.引入vue-router的對象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<!--全局的VueRouter對象 vue-router還提供了兩個全局的元件router-link / router-view-->
<script type="text/javascript">
// 路由範式
//(1)xxx.html#/user/1 params 動态路由參數
//(2)xxx.html#/user?userId=2 query 查詢
// 2.讓Vue使用該VueRouter建立
Vue.use(VueRouter);
var UserParams = {
template:`
<div>我是使用者1</div>
`,
created(){
// 接收參數
console.log(this.$route); // 其中包含params屬性
console.log(this.$route.params.userId); // 輸出:1
// 傳參,發送ajax請求
console.log(this.$router); // VueRouter對象
}
};
var UserQuery = {
template:`
<div>我是使用者2</div>
`,
created(){
// 接收參數
console.log(this.$route); // 包含query屬性,query: {userId: "2"}
console.log(this.$route.query.userId); // 輸出:2
// 傳參,發送ajax請求
console.log(this.$router); // VueRouter對象
}
};
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/user/:userId', // params形式,動态路由參數,以冒号開頭
name:'userp', // 設定路由名稱
component:UserParams
},
{
path:'/user',
name:'userq', // 設定路由名稱
component:UserQuery
}
]
});
var App = {
// 不使用to屬性通路路由,改用動态命名路由綁定.要連結到一個命名路由,可以給 router-link 的 to 屬性傳一個對象
// 路由比對,query是查詢操作
template: `
<div>
<router-link :to="{name:'userp', params:{userId:1}}">使用者1</router-link>
<router-link :to="{name:'userq', query:{userId:2}}">使用者2</router-link>
<router-view></router-view>
</div>
`
};
new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>`
});
</script>
</body>
1、query方式傳參和接收參數
利用$route.query對象的Get方式傳參,與http的get方式一樣,會将參數暴露到位址欄。
var UserQuery = {
template:`
<div>我是使用者2</div>
`,
created(){
// 接收參數
console.log(this.$route); // 包含query屬性,query: {userId: "2"}
console.log(this.$route.query.userId); // 輸出:2
// 傳參,發送ajax請求
console.log(this.$router); // VueRouter對象
}
};
顯示效果如下:
2、params方式傳參和接收參數
利用$route.params對象的Post方式傳參,該方式具有一定限制,必須通過路徑傳參方式。
var UserParams = {
template:`
<div>我是使用者1</div>
`,
created(){
// 接收參數
console.log(this.$route); // 其中包含params屬性
console.log(this.$route.params.userId); // 輸出:1
// 傳參,發送ajax請求
console.log(this.$router); // VueRouter對象
}
};
顯示效果如下所示:
3、源碼分析
// vue-router.js檔案558行到564行
Object.defineProperty(Vue.prototype, '$router', {
get: function get () { return this._routerRoot._router }
});
Object.defineProperty(Vue.prototype, '$route', {
get: function get () { return this._routerRoot._route }
});
相當于給vue執行個體化對象添加了兩個屬性$router(VueRouter)和$route(路由配置資訊)。
4、配置路由對象方式
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/user/:userId', // params形式,動态路由參數,以冒号開頭
name:'userp', // 設定路由名稱
component:UserParams
},
{
path:'/user',
name:'userq', // 設定路由名稱
component:UserQuery
}
]
});
注意params形式,是配置動态路由參數,要以冒号開頭。
5、比對路由
var App = {
// 不使用to屬性通路路由,改用動态命名路由綁定.要連結到一個命名路由,可以給 router-link 的 to 屬性傳一個對象
template:`
<div>
<router-link :to="{name:'userp', params:{userId:1}}">使用者1</router-link>
<router-link :to="{name:'userq', query:{userId:2}}">使用者2</router-link>
<router-view></router-view>
</div>
`
};
通路效果如下所示:
四、程式設計式導航
除了使用
<router-link>
建立 a 标簽來定義導航連結,我們還可以借助 router 的執行個體方法,通過編寫代碼來實作。
1、程式設計式導航示例
對上例做如下修改,不再使用聲明式的<router-link :to='...'>,改為使用程式設計式:router.push(...)
var App = {
// 不使用to屬性通路路由,改用動态命名路由綁定.要連結到一個命名路由,可以給 router-link 的 to 屬性傳一個對象
template:`
<div>
<button @click="paramsHandler">使用者1</button>
<button @click="queryHandler">使用者2</button>
<router-view></router-view>
</div>
`,
methods:{
paramsHandler(){
// 程式設計式導航
this.$router.push({ name: 'userp', params: { userId: 123 }})
},
queryHandler(){
this.$router.push({ name: 'userq', query: {userId: 3221} })
}
}
};
params通路顯示效果:
query通路顯示效果:
2、router.push( location, onComplete?, onAbort?
)
location, onComplete?, onAbort?
注意:在 Vue 執行個體内部,你可以通過
$router
通路路由執行個體。是以你可以調用
this.$router.push
。
想要導航到不同的 URL,則使用
router.push
方法。這個方法會向 history 棧添加一個新的記錄,是以,當使用者點選浏覽器後退按鈕時,則回到之前的 URL。
當你點選
<router-link>
時,這個方法會在内部調用,是以說,點選
<router-link :to="...">
等同于調用
router.push(...)
該方法的參數可以是一個字元串路徑,或者一個描述位址的對象。例如:
// 字元串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了
path
,
params
會被忽略,上述例子中的
query
并不屬于這種情況。取而代之的是下面例子的做法,你需要提供路由的
name
或手寫完整的帶有參數的
path
:
const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 這裡的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
同樣的規則也适用于
router-link
元件的
to
屬性。
在 2.2.0+,可選的在
router.push
或
router.replace
中提供
onComplete
和
onAbort
回調作為第二個和第三個參數。這些回調将會在導航成功完成 (在所有的異步鈎子被解析之後) 或終止 (導航到相同的路由、或在目前導航完成之前導航到另一個不同的路由) 的時候進行相應的調用。
注意:如果目的地和目前路由相同,隻有參數發生了改變 (比如從一個使用者資料到另一個
/users/1
->
/users/2
),你需要使用
beforeRouteUpdate
來響應這個變化 (比如抓取使用者資訊)
五、嵌套路由
實際生活中的應用界面,通常由多層嵌套的元件組合而成。同樣地,URL 中各段動态路徑也按某種結構對應嵌套的各層元件,例如:
/user/foo/profile /user/foo/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
借助
vue-router
,使用嵌套路由配置,就可以很簡單地表達這種關系。
1、嵌套路由示例
<body>
<div id="app"></div>
<script type="text/javascript" src="vue.js"></script>
<!--1.引入vue-router的對象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<!--全局的VueRouter對象 vue-router還提供了兩個全局的元件router-link / router-view-->
<script type="text/javascript">
// 嵌套路由:
// 需求:進入首頁後,點選音樂(/home/music) 電影(/home/movie)
// 2.讓Vue使用該VueRouter建立
Vue.use(VueRouter);
var Home = {
// 子路由出口
template:`
<div>
<br/>
<router-link to="/home/music">音樂</router-link>
<router-link to="/home/movie">電影</router-link>
<router-view></router-view>
</div>
`
};
var Music = {
template:`
<div>我是音樂</div>
`
};
var Movie = {
template:`
<div>我是電影</div>
`
};
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/',
redirect:'home'
// redirect:{name:'home'} // 指令路由的方式
},
{
path:'/home', // params形式,動态路由參數,以冒号開頭
name:'home', // 設定路由名稱
component:Home,
children:[
// 動态路由比對表示你的子元件中的結構是不同的
// 當通路/home元件時,Home元件的出口是不會渲染任何内容的,
// 這是因為沒有比對到合适的子路由
{
path:'', // 通路空字元串就表示通路/home了
component:Music // 預設加載孩子元件Music
},
{
path:'music', // 自己會預設去拼接斜杠
component:Music // 對應加載的元件
// children: // 可以繼續配置三層路由
},
{
path:'movie', // 自己會預設去拼接斜杠
component:Movie // 對應加載的元件
}
]
},
]
});
var App = {
// 路由出口
template:`
<div>
<router-link :to="{name:'home'}">首頁</router-link>
<router-view></router-view>
</div>
`,
};
new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>`
});
</script>
</body>
2、注意要點
(1)以
/
開頭的嵌套路徑會被當作根路徑。 這讓你充分的使用嵌套元件而無須設定嵌套的路徑。
(2)children
配置就是像
routes
配置一樣的路由配置數組,是以呢,你可以嵌套多層路由。
3、顯示效果
(1)頁面首頁預設顯示音樂
(2)點選切換到電影頁面
4、嵌套路由警告處理
這個警告的意思是:當父路由有子路由時,不允許子路由中有命名路由。是以對代碼做如下調整
var router = new VueRouter({
// 配置路由對象
routes:[
{
path:'/',
redirect:'home'
// redirect:{name:'home'} // 指令路由的方式
},
{
path:'/home', // params形式,動态路由參數,以冒号開頭
// name:'home', // 設定路由名稱
component:Home,
children:[
// 動态路由比對表示你的子元件中的結構是不同的
// 當通路/home元件時,Home元件的出口是不會渲染任何内容的,
// 這是因為沒有比對到合适的子路由
{
path:'', // 通路空字元串就表示通路/home了
component:Music // 預設加載孩子元件Music
},
{
path:'music', // 自己會預設去拼接斜杠
component:Music // 對應加載的元件
// children: // 可以繼續配置三層路由
},
{
path:'movie', // 自己會預設去拼接斜杠
component:Movie // 對應加載的元件
}
]
},
]
});
var App = {
// 路由出口
template:`
<div>
<!--<router-link :to="{name:'home'}">首頁</router-link>-->
<router-link to="/home">首頁</router-link>
<router-view></router-view>
</div>
`,
};
再次檢視控制台,警報解除:
六、動态路由比對
我們經常需要把某種模式比對到的所有路由,全都映射到同個元件。例如,我們有一個
User
元件,對于所有 ID 各不相同的使用者,都要使用這個元件來渲染。那麼,我們可以在
vue-router
的路由路徑中使用“動态路徑參數”(dynamic segment) 來達到這個效果。
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// 動态路徑參數 以冒号開頭
{ path: '/user/:id', component: User }
]
})
1、動态路由比對示例
<body>
<div id="app"></div>
<script type="text/javascript" src="vue.js"></script>
<!--1.引入vue-router的對象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<!--全局的VueRouter對象 vue-router還提供了兩個全局的元件router-link / router-view-->
<script type="text/javascript">
// 2.讓Vue使用該VueRouter建立
Vue.use(VueRouter);
var Timeline = {
template:`
<div>
<router-link :to="{name:'comDesc', params:{id:'android'}}">Android</router-link>
<router-link :to="{name:'comDesc', params:{id:'frontend'}}">前端</router-link>
<router-view></router-view>
</div>
`
};
var Pins = {
template:`
<div>
我是沸點
</div>
`
};
// 共同的子元件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
alert(1);
this.msg = '安卓';
}
};
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
// 動态路由參數以冒号開頭
{
path:'/timeline',
component:Timeline,
children:[
{
path:"",
component:ComDesc // 通路Timeline時通路共同元件ComDesc
},
{
path:'/timeline/:id',
name:'comDesc',
component:ComDesc // 通路子動态路由時,也加載共同元件ComDesc
}
]
},
{
path:'/pins',
component:Pins
}
]
});
var App = {
// 路由出口
template:`
<div>
<router-link to="/timeline">首頁</router-link>
<router-link to="/pins">沸點</router-link>
<router-view></router-view>
</div>
`,
};
new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>`
});
</script>
</body>
(1)路由映射到公共路由
var router = new VueRouter({
// 配置路由對象
routes:[
// 動态路由參數以冒号開頭
{
path:'/timeline',
component:Timeline,
children:[
{
path:"",
component:ComDesc // 通路Timeline時通路共同元件ComDesc
},
{
path:'/timeline/:id',
name:'comDesc',
component:ComDesc // 通路子動态路由時,也加載共同元件ComDesc
}
]
},
{
path:'/pins',
component:Pins
}
]
});
/timeline/android和/timeline/frontend都将映射相同的路由。
一個“路徑參數”使用冒号
:
标記。當比對到一個路由時,參數值會被設定到
this.$route.params
,可以在每個元件内使用。
(2)元件執行個體複用
當使用路由參數時,例如從
/user/foo
導航到
/user/bar
,原來的元件執行個體會被複用。因為兩個路由都渲染同個元件,比起銷毀再建立,複用則顯得更加高效。不過,這也意味着元件的生命周期鈎子不會再被調用。
// 共同的子元件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
alert(1);
this.msg = '安卓';
}
};
(3)顯示效果及生命周期鈎子不重複調用
初始狀态:
點選首頁,顯示alert:
點選确認後顯示:
點選前端:
再點回安卓或首頁,頁面顯示會調整,但都不再顯示alert。說明生命周期鈎子不再運作。
2、響應路由參數的變化
前面已經說到當使用路由參數時,例如從
/user/foo
/user/bar
複用元件時,想對路由參數的變化作出響應的話,你可以簡單地 watch (監測變化)
$route
對象:
// 共同子元件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
// alert(1);
// this.msg = '安卓';
},
watch:{
'$route' (to, from) {
// 對路由變化作出響應...
console.log(to);
console.log(from);
}
}
};
(1)點選安卓頁面,列印出的to和from資訊
(2)然後再點選前端頁面,列印的to和from資訊
(3)直接渲染
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
// alert(1);
// this.msg = 'android';
},
watch:{
'$route' (to, from) {
// 對路由變化作出響應...
console.log(to);
console.log(from);
// 直接渲染
this.msg = to.params.id;
}
}
};
點選顯示效果如下所示:
也可以看到元件沒有再次被銷毀或建立。
七、keep-alive在路由中的使用
<keep-alive>
是Vue的内置元件,能在元件切換過程中将狀态保留在記憶體中(緩存),防止重複渲染DOM。
(1)Props:
- include:字元串或正規表達式。隻有名稱比對的元件會被緩存。
- exclude:字元串或正規表達式。任何名稱比對的元件都不會被緩存。
- max:數字。最多可以緩存多少元件執行個體。
(2)用法:
<keep-alive>
包裹動态元件時,會緩存不活動的元件執行個體,而不是銷毀它們。和
<transition>
相似,
<keep-alive>
是一個抽象元件:它自身不會渲染一個 DOM 元素,也不會出現在父元件鍊中。
當元件在
<keep-alive>
内被切換,它的
activated
deactivated
這兩個生命周期鈎子函數将會被對應執行。
主要用于保留元件狀态或皮面重新渲染。
1、不使用keep-alive切換頁面
<script type="text/javascript">
// 2.讓Vue使用該VueRouter建立
Vue.use(VueRouter);
var Timeline = {
template:`
<div>
我是首頁
</div>
`,
created(){
console.log('首頁元件建立了');
},
mounted(){
console.log('首頁元件DOM加載了');
},
destroyed(){
console.log('首頁銷毀了');
}
};
var Pins = {
template:`
<div>
<h3 @click="clickHandler">我是沸點</h3>
</div>
`,
methods:{
clickHandler(e){
e.target.style.color = 'red';
}
},
created(){
console.log('沸點元件建立了');
},
mounted(){
console.log('沸點元件DOM加載了');
},
destroyed(){
console.log('沸點銷毀了');
};
// 3.建立一個路由對象
var router = new VueRouter({
// 配置路由對象
routes:[
// 動态路由參數以冒号開頭
{
path:'/timeline',
component:Timeline,
},
{
path:'/pins',
name:'pins',
component:Pins
}
]
});
var App = {
// keep-alive元件保持緩存,把router-view渲染的出口緩存起來
template:`
<div>
<router-link to="/timeline">首頁</router-link>
<router-link to="/pins">沸點</router-link>
<router-view></router-view>
</div>
`,
};
new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同時可以隻寫一個
template:`<App/>`
});
</script>
此時還沒有使用keep-alive,切換頁面時都會執行生命周期操作:
而且切換到沸點頁面,點選“我是沸點”,可以将字型變紅,但是切換到首頁再切換沸點時,又變黑色了。也說明了重新進行了建立銷毀。
2、用keep-alive元件把router-view渲染的出口緩存起來
注意:
<keep-alive>
是用在其一個直屬的子元件被開關的情形。如果你在其中有
v-for
則不會工作。如果有上述的多個條件性的子元素,
<keep-alive>
要求同時隻有一個子元素被渲染。
var App = {
// keep-alive元件保持緩存,把router-view渲染的出口緩存起來
template:`
<div>
<router-link to="/timeline">首頁</router-link>
<router-link to="/pins">沸點</router-link>
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
`,
};
可以看到第一次點選會建立和加載,但并沒有銷毀DOM,從首頁切換到沸點,仍保持為紅色。