您好,登錄后才能下訂單哦!
一、文件目錄說明
main.js:應用的入口文件【js文件入口】
App.vue:根組件,整個組件的入口【組件文件入口】
new Vue({}); //Vue是構造函數,本質上是一個函數,函數就有原型prototype
加載文件不要后綴名:
resolve:{
extensions:['.js','.vue','.json'],
alias:{
'vue$':'vue/dist/vue.esm.js',
'@':resolve('src') //@就代表了"src"這個目錄
}
}
import App from './App'; 就相當于 './App.vue';
import router from './router' //加載某個目錄下的index.js文件,可以簡寫,就相當于 './router/index.js'
.gitignore
上傳git倉庫的時候,不上傳某些文件,比如node_modules,因為太大了,
所以從git倉庫clone文件下來的時候,首先就是要npm install,安裝package.json里面定義的依賴包
然后就是npm run dev
index.js文件,定義路由(默認導出)
export default new Router({})
也可以:
let router = new Router({}) //先定義,下面導出,這樣就可以用到router路由實例了
export default router
導出之后,在main.js里面引入的:import router from './router',得到一個路由實例
然后再將路由實例router注入到new Vue()這個根實例里面,就可以用到router里面的一些信息
然后在App.vue里面,寫入<router-view></router-view>,展示對應渲染的組件
index.js Vue.use( Router ) //通過這種寫法,就可以在每個組件里面,通過this.$router訪問到當前路由實例
二、使用步驟
安裝模塊
npm install vue-router --save -dev (vue-cli腳手架里面就已經安裝好了)
引入模塊
import *VueRouter* from 'vue-router'
作為vue的插件
Vue.use(*VueRouter*)
創建路由實例對象
new VueRouter({
//...配置參數
mode:'history',
routes: [
{
path: '/home',
name: 'Home', //在后期使用這個配置好的路由時,需要用到name屬性
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/document',
name: 'Document',
component: Document
}
]
})
注入Vue選項參數
new Vue({
router
})
告訴路由渲染位置
<router-view></router-view>
如果不注冊路由組件Vue.use(VueRouter),那么報錯顯示沒有成功注冊router-view組件;
說明router-view也是一個組件,用于渲染路由組件內容
三、router-link各種配置項
路由跳轉不刷新頁面,默認是使用了hash值進行切換頁面,因為利用hash切換頁面,不是跳轉,不用刷新頁面
在路由配置文件里面寫上:mode:'history',就使用了history模式,url里面也沒有了#號
低版本使用hash模式,因為不支持history,高版本使用history模式
不能使用a標簽來進行頁面的切換,因為a標簽有跳轉鏈接的默認行為,會刷新頁面,這樣就不是一個單頁應用了。
vue-router提供了一個標簽,可以不刷新頁面來進行頁面的切換,功能就類似于優化后的a標簽,凡是涉及到跳轉頁面的導航,都使用router-link(其實是一個組件)
<router-link to='目標鏈接'></router-link>,會生成a標簽,同時把a標簽的默認行為取消掉,并且跳轉到對應的目標頁
一個路徑,對應渲染一個組件,實際就是分別替換<router-view></router-view>
to后面跟的屬性值都是字符串
1、目標地址可以寫死
<li><router-link to="/home">home</router-link></li>
2、目標地址可以動態綁定
<li><router-link :to="index">home</router-link></li>
export default{
name:'App',
data(){
return {
index:'/home'
}
}
}
3、目標地址可以寫成對象形式
<li><router-link :to="{path:'/home'}">home</router-link></li>
4、導航不僅僅只用a標簽來設置,也可以使用別的標簽,如div、p、li等等
<router-link :to="index" tag="li">//寫上tag="li"即可,這樣里面可以添加小圖標,豐富效果
<i class="fa fa-home"></i>
<span>home</span>
</router-link>
5、設置鏈接選中的狀態,vue-router默認會加上router-link-active類名
可以自定義這個選中的類名,這樣就不使用默認類名了
export default new Router({
linkActiveClass:'is-active'
})
然后自己設置這個類的樣式
.is-active{ background:red; }
6、不同組件,設置同一套樣式
同時,每個組件也可以設置自己特有的樣式
<router-view class="center" /> //這會把類名.center渲染到每個組件的根元素上,就可以所有路由組件共享一個類名
7、改變導航切換事件,默認是click,在需要這種方式切換的導航上都得添加
<router-link :to="index" tag="li" event="mouseover">
8、路徑匹配不到
{
path:'*', //情況一、路徑匹配不到,固定渲染這個組件,比如404頁面
//component:noPath
//情況二、不渲染固定的組件,而是重定向到一個其他頁面,有下面三種寫法
//redirect:'/home'
//redirect:{path:'/home'}
//redirect:{name:'Home'} 前面兩個需要加/,后面使用name就不用加/
//情況三、動態設置重定向的目標
redirect:(to)=>{
console.log(to) //to是目標路由對象,即要訪問的路徑的路由信息,見下圖
if(to.path === '/123'){
return '/home' //一定要加上return
}else if(to.path === '/456'){
return {path:'/about'}
}else{
return {name:'Document'}
}
}
}
9、給路由設置別名
{
path: '/home',
name: 'Home',
component: Home,
alias:'/index' //設置別名,即地址欄輸入http://localhost:8080/index,也會調到home頁
}
此時,home導航不會高亮,解決方法:
在router-link上設置判斷:{class:$router.path === '/別名'}
四、路由嵌套子路由
http://localhost:8080/about/study
/:代表根路徑
/about:代表根路徑下的about路徑
/about/study:代表根路徑下的about路徑下的study
/study:代表根路徑下的study
全包含匹配模式:訪問/about,是相對于根路徑來說的,那么根路徑也會匹配到激活狀態,所以home也是高亮的
精確匹配模式:訪問/about,根路徑不匹配到,在根路徑上加個exact即可
<router-link class="btn" exact to='/'>home</router-link>
在path里面,'/'都是相對根路徑而言,如果寫子路由,那么前面就不需要加'/'了,因為以'/'都是相對于根路徑的
study、work、hobby,是about路由里面的二級導航
{
path: '/about',
//name: 'About', 有子路由,父路由不需要設置name屬性,把它給默認子路由
component: about,
children:[
{
path:'/', //默認的子路由(不能寫成 path:'work'),點擊about會默認展現work組件內容
name: 'Work',
component:work
},
{
path:'study', //前面不需要加'/'
name: 'Study',
component:study
},
{
path:'hobby',
name: 'Hobby',
component:hobby
}
]
}
<template>
<div class="about">
<ul>
<router-link to="/about" exact tag="li">
<a>work</a>
</router-link>
<router-link to="/about/study" tag="li">
<a>study</a>
</router-link>
<router-link to="/about/hobby" tag="li">
<a>hobby</a>
</router-link>
</ul>
<router-view></router-view>
</div>
</template>
也可以使用name或者path,此時需要動態綁定v-bind
<template>
<div class="about">
<ul>
<router-link :to='{path:"/about/work"}' exact tag="li">
<a>work</a>
</router-link>
<router-link :to="{name:'Study'}" tag="li">
<a>study</a>
</router-link>
<router-link :to="{name:'Hobby'}" tag="li">
<a>hobby</a>
</router-link>
</ul>
<router-view></router-view>
</div>
</template>
五、命名視圖:單頁面多路由區域操作
在同級同時展示多個視圖,而不是嵌套展示
有幾個視圖,就寫幾個<router-view name=" " />(寫在父級組件內,比如about有多個視圖,就寫在app.vue里面,about下面的work有多個視圖,router-view就寫在about里面),然后通過name屬性來進行區分
{
path: '/document',
name: 'Document',
components:{ //注意這里是復數,加s
default:document, //默認的
slider:slider //新添加的
}
},
<router-view name="slider" class="center" /> //有name屬性的,會匹配到components里面對應名稱的組件
<router-view class="center" /> //沒有name屬性的會自動對應default的組件
六、滾動行為
記錄頁面滾動的位置,點擊瀏覽器上的前進后退按鈕,仍然會回到之前的頁面位置
在index.js里面配置
export default new Router({
mode:'history',
linkActiveClass:'is-active', //表示給選中的導航添加類名is-active
scrollBehavior(to,from,savePosition){ //點擊瀏覽器的前進后退按鈕或切換導航時觸發該事件
console.log(to); //要進入的目標路由對象,即要去向哪里
console.log(from); //離開的路由對象,即從哪里來
console.log(savePosition); //記錄滾動條的坐標位置 只在點擊前進后退按鈕時才有記錄
//方法一:使用坐標值
if(savePosition){ //寫上這個代碼即可,前進后退,仍然到達之前的頁面位置
return savePosition
}else{
return {x:0,y:0}
}
//方法二、使用hash值
//<router-link :to="{path:'/document#abc'}"></router-link>
//document頁面要定位的元素 <p id="abc"></p>
if( to.hash ){
return {
selector:to.hash
}
}
},
routes:[
{
path: '/home',
name: 'Home',
component: home
meta:{ //自定義一些屬性
index:0
}
}
]
})
七、動態路徑
匹配到的所有路由,全部映射到同一個組件
路徑:/user/:userId/ userId為動態路徑參數
獲取參數:路由信息對象的params
具體例子:比如用戶登錄個人信息頁,頁面是一樣的,都是同一個組件,但是不同用戶要展示的信息是不一樣的,這就通過userId來展示對應的信息,拿到userId就可以獲取到用戶的信息
vue的路由有一個路由實例$router
通過在Vue根實例的router配置傳入router實例
new Vue({
el: '#app',
router, //也可以寫成router:router
components: { App },
template: '<App/>'
})
在每一個組件里面,通過$router拿到router路由實例對象
$route 當前激活的路由信息對象,每個組件實例都會有,每次成功導航后都會產生一個新的對象
綁定userId的寫法:<router-link :to="'/user/'+item.id" v-for="item,index in userlist" />
id為1的用戶頁面:http://localhost:8080/user/1 不是以參數的形式:http://localhost:8080/user?userId=1 ,這個是查詢字符串query
userId接收路徑里傳入的參數
{
path: '/user/:userId?',//后面加個問號,正則,表示可以匹配到 /user /user/1 /user/2 /user/3,都走User組件
name: 'User',
component: user
},
<template>
<div class="user">
<div class="user-list">
<router-link :to="'/user/'+item.id" :key="index" v-for="item,index in userList">{{item.userName}}</router-link>
<router-link :to="{path:'/user/'+item.id,query:{info:'follow'}}"
:key="index" v-for="item,index in userList">{{item.userName}}</router-link>
</div>
<div class="user-list" v-show="userInfo.userName">
<p>姓名:{{userInfo.userName}}</p>
<p>性別:{{userInfo.sex}}</p>
<p>愛好:{{userInfo.hobby}}</p>
</div>
<hr />
<div class="info-list" v-if="userInfo.userName">
<router-link exact to="?info=follow" >follow</router-link>
<router-link exact to="?info=share" >share</router-link>
<!--<router-link exact :to="{path:'',query:{info:'follow'}}">他的關注</router-link>
<router-link exact :to="{path:'',query:{info:'share'}}">他的分享</router-link>-->
<div>{{$route.query}}</div>
</div>
</div>
</template>
<script>
let data = [
{
id:1,
userName:"leo1",
sex:'男',
hobby:'寫代碼'
},
{
id:2,
userName:"leo2",
sex:'男',
hobby:'唱歌'
},
{
id:3,
userName:"leo3",
sex:'男',
hobby:'讀書'
}
]
export default{
name:"User",
data(){
return {
userList:data,
userInfo:{}
}
},
watch:{ //監測Vue實例上的數據變動,這里是監聽$route,路徑發生變化,$route會重新賦值,監控了這個屬性,會執行里面的函數
$route(){
this.getData();
}
},
created(){ //編譯之前 ajax提交信息也放在這里面
// 渲染這個組件會調用一次這個生命周期函數
// 復用這個組件,這個函數不會再次被調用了
// 地址一旦發生變化,$route會重新生成一個路由信息對象
this.getData();
},
methods:{
getData(){
let id = this.$route.params.userId; //用戶點擊鏈接,地址欄顯示,獲取動態參數userId
if(id){
this.userInfo = this.userList.filter((item)=>{ //this.userInfo是對象,this.userList是數組,現在需要返回的是一個對象,所以取數組的第一項
return item.id == id;
})[0]
}else{
this.userInfo = {}
}
}
}
}
</script>
八、查詢字符串
query字符串傳參
//點擊默認顯示 關注切頁follow
<router-link v-bind:key="index" v-for="item,index in userlist"
:to="{path:'/user/'+item.tip+'/'+item.id,query:{info:'follow'}}"
{{item.userName}}
</router-link>
:to="{path:'/home'}" //to后面跟的都是字符串,path后面跟的也是字符串,如果有變量就要使用字符串拼接
:to=" '/user/' + item.tip + '/' + item.id "
:to=" { path: '/user/' + item.tip + '/' + item.id , query : {info:'follow'} } "
查詢字符串的兩種寫法:
<router-link exact :to="{path:'',query:{info:'follow'}}">他的關注</router-link>
<router-link exact to="?info=share">他的分享</router-link>
query后面跟的是一個對象,內容是查詢字符串的鍵值,
path里面為空,不能是'/','/'表示根路徑
九、給導航切換增加過度動畫transition
過渡的css類名:
v-enter:定義進入過渡的開始狀態
v-enter-active:定義進入活動狀態
v-enter-to:定義進入的結束狀態
v-leave:定義離開過渡的開始狀態
v-leave-active:定義離開活動狀態
v-leave-to:定義離開的結束狀態
自定義過度動畫:
.left-enter{
tranform:translateX(-100%)
}
.left-enter-to{
tranform:translateX(0)
}
.left-enter-active{
transition:1s;
}
使用:
<transition name="left" mode="out-in">
<router-view class="center"></router-view>
</transition>
過渡模式:
可能會有2個組件同時出現在頁面上的情況,會重疊在一起,很難看。這里就用到了過渡模式
<transition mode="out-in">
<router-view class="center"></router-view>
</transition>
路由元信息:
在路由配置中meta可以配置一些自定義數據,用在路由信息對象中
訪問meta中數據:$route.meta.index //index是自己設置的屬性名
<template>
<div id="app">
<div class="nav-box">
<ul class="nav">
<router-link :to="idx" tag="li" event="mouseover">
<i class="fa fa-home"></i>
<span>home</span>
</router-link>
<li>
<router-link :to="{path:'/about'}" event="mouseover">about</router-link>
</li>
<li>
<router-link to="/document" event="mouseover">document</router-link>
</li>
<li>
<router-link to="/user" event="mouseover">user</router-link>
</li>
</ul>
</div>
<router-view name="slider" class="" />
<!--<transition mode="out-in">
<router-view class="center"></router-view>
</transition>-->
<transition :name="names">
<router-view class="center"></router-view>
</transition>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
idx:'/home',
names:"left"
}
},
watch:{
$route(to,from){
console.log(to.meta.index) //目標導航下標
console.log(from.meta.index) //離開導航下標
if(to.meta.index < from.meta.index){
this.names="left"
}else{
this.names="right"
}
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.v-enter{
opacity: 0;
}
.v-enter-to{
opacity: 1;
}
.v-enter-active{
transition: 0.5s;
}
.v-leave{
opacity: 1;
}
.v-leave-to{
opacity: 0;
}
.v-leave-active{
transition: 0.5s;
}
.left-enter{
transform: translateX(-100%);
}
.left-enter-to{
transform: translateX(0);
}
.left-enter-active,.right-enter-active{
transition: 1s;
}
.right-enter{
transform: translateX(100%);
}
.right-enter-to{
transform: translateX(0);
}
index.js配置:
{
path: '/home',
name: 'Home',
component: home,
meta:{ //自定義一些屬性
index:0
}
},
</style>
十:編程式導航
☆ 借助于router的實例方法$router,通過編寫代碼來實現導航的切換,router-link是標簽進行導航,這里是通過js代碼
$router為VueRouter實例,想要導航到不同URL,則使用$router.push方法
十一:導航鉤子函數
導航發生變化時,導航鉤子主要用來攔截導航,讓它完成跳轉或者取消
案例1:定義全局鉤子函數,只要有導航切換的地方就會觸發,寫在index.js路由配置文件下
let router = new VueRouter({})
//進入路由前
router.beforeEach( ( to,from,next )=>{
if( to.meta.login ){ //要進入的組件需要先進行登錄
console.log(to);
next('/login'); //如果沒有登錄就重定向到登錄頁
}else{
next(); //已經登錄,就渲染要進入的組件內容
}
} )
//進入路由后
router.afterEach( ( to,from )=>{ //這里不需要next了,因為已經進入了
if( to.meta.title ){ //切換不同的組件,頁面title改變為對應的值
window.document.title=to.meta.title;
}else{
window.document.title='myTitle'; //注意這里document前面需要加上window,否則訪問不到
}
} )
index.js
{
path:'home',
component:'home',
meta:{
index:1,
login:true,
title:'home'
}
}
案例2:定義單個路由鉤子函數,只在進入該路由導航時才執行該鉤子函數,寫在路由配置里
{
path:'/document',
conponent:'document',
beforeEnter(to,from,next){
next(); //執行了這個才會渲染組件
}
}
案例3:定義組件內的鉤子函數,進入該組件時執行該鉤子函數,寫在組件內
比如:about.vue組件
<script>
export default({
data(){
msg:'改變前',
beforeCreate(){
console.log('beforeCreate');
},
beforeRouteEnter( to,from,next ){ //進入的導航鉤子,決定是否進入這個導航
//next(); //執行了這個才會渲染組件
console.log(this); //this是undefined,所以不能通過this.msg獲取data,可以通過next的回調函數
//路由的鉤子函數先執行,組件的鉤子函數后執行,此時,組件的實例還沒有創建,所以this是undefined
next( (vm)=>{
vm.msg='改變了';
} )
},
beforeRouteUpdate( to,from,next ){ //點擊二級導航,決定是否進入到二級導航里面
//next //寫了才會更新
},
beforeRouteLeave( to,from,next ){
//next(); //寫了這個,才會從當前導航離開,否則會一直停留在當前導航頁
}
//【注意】,這里面的路由鉤子函數都是寫在單個組件內的,局部的
}
})
</script>
十二、vue-cli項目實戰
1、多個組件,將每個組件所需要的樣式,抽離出來,放在assets/css/文件夾下面(assets文件夾放資源文件:css/js/img),
建立css入口文件app.css
然后在其中import引入全部的組件樣式文件
然后在main.js里面,import這個app.css文件,// import './assets/css/app.css'
即可在項目中引入全部css文件( webpack會幫助引入 )
2、components文件夾放公共組件,即每個頁面都會用到的部分,如導航欄
views文件夾放每個頁面獨立的組件
3、libs:公共庫,自己封裝的js或者第三方工具庫放在這里面
怎么使用自定義的庫呢:
單頁面使用:單頁面引入,然后直接使用里面的方法
import local from '@/lib/utils'
local.fetch、local.save
全局使用:作為Vue的插件
舉例:對象obj作為Vue的插件,key值必須為install,對應的是一個函數
let obj = {
install:function( Vue,options ){
Vue.prototype.$abc = '自定義屬性'; //其他頁面通過this.$abc獲取到'自定義屬性'值
console.log(Vue); //構造函數
console.log(options); //{a:1}
}
}
Vue.use( obj , {a:1} );
首先在main.js引入:import Utile from './lib/utils'
然后注冊到Vue實例:Vue.use( Utile )
最后:就可以在每個組件,通過this訪問到$local對象,對象上面有save和fetch兩個方法
如果在組件內部獲取不到this,可以通過router.app.$local來獲取$local對象
4、在判斷是否需要登錄時,如果父子路由都需要檢測meta里面是否都有需要登錄的情況時,to代表的是當前進入路由的信息對象,下面有一個屬性:matched,是一個數組,里面存了當前的路由信息對象以及父路由信息對象
十三、項目知識點集結
1、$refs的用法
<input type="text" class="input1" ref="input1"/>
一般來講,獲取DOM元素,需document.querySelector(".input1").value獲取這個dom節點的值
用ref綁定之后,this.$refs.input1.value 就可以
2、
router.beforeEach( ( to,from,next )=>{
if( to.meta.login ){
console.log(to); //這個是要進入的路由信息對象
}
}
to對象里面有一個:matched數組Array[2],包含當前路由所有嵌套路徑片段的路由信息,包括自己的信息和父路由的信息
3、some()方法
Array.some(function( item ){})
4、導航鉤子函數,主要是用在進行導航是否跳轉或者攔截的一些操作,比如點擊導航,用戶是否需要登錄才能跳轉還是說可以直接進行跳轉
有三個地方可以寫導航鉤子函數
全局、單個路由、單個組件中
5、開發環境頁面完成之后,使用命令:npm run build打包項目,生成dist文件夾上線
默認是把dist文件夾下面的所有文件放在服務器的根目錄下
但是,如果不是放在根目錄下,而是服務器的二級目錄下,那么就得配置config/index.js文件,里面的assetsPublicPath屬性,改為二級目錄名稱即可
6、頁面上線之后,打開頁面,然后刷新會出現404,需要配置apache里的httpd.conf文件
刪除...前面的#號,釋放該模塊...具體看視頻,只要是404,都重定向到index.html
7、$router和$route的區別
this.$router:router為VueRouter的實例,通過Vue.use(VueRouter)和VueRouter構造函數得到一個router的實例對象,相當于一個全局的路由器對象,里面含有很多屬性和子對象,例如history對象。。。經常用的跳轉鏈接就可以用this.$router.push,和router-link跳轉一樣。。。
this.$route: 表示當前正在用于跳轉的路由器對象,每一個路由都會有一個route對象,是一個局部的對象,可以獲取對應的name、path、query、params等方法;
8、
to:要進入的目標路有對象,到哪里去
from:正要離開導航的路有對象,從哪里來
savePosition:記錄滾動條的坐標位置 只在點擊前進后退按鈕時才有記錄
next:用來決定跳轉或取消導航,只有執行改函數才會渲染要進入的組件
$route(to,from){}
scrollBehavior(to,from,savePosition){}
beforeRouteEnter( to,from,next ){}
9、在任何一個路由里面,可以通過this.$route獲取到如下信息:
在任何一個路由鉤子函數里面,通過to參數,可以獲取到如下信息:
其實二者一模一樣;
在router/index.js里面,可以直接通過router獲取到路由信息
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。