继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

vue-router教程

holdtom
关注TA
已关注
手记 1703
粉丝 240
获赞 991


一、文件目录说明

main.js:应用的入口文件【js文件入口】

App.vue:根组件,整个组件的入口【组件文件入口】

加载文件不要后缀名:

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({

            ...配置参数

        })

    注入Vue选项参数

        new Vue({

            router

        })

    告诉路由渲染位置

        <router-view></router-view>

三、router-link各种配置项

一个路径,对应渲染一个组件,实际就是分别替换<router-view></router-view>

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、不同组件,设置同一套样式

<router-view class="center" />  //这会把类名.center渲染到每个组件的根元素上,就可以所有路由组件共享一个类名

6、改变导航切换事件,默认是click

<router-link :to="index" tag="li" event="mouseover">

7、重定向

{

        path:'*',

        //component:noPath

        //重定向

        //redirect:'/about'

        //redirect:{path:'/home'}

        //redirect:{name:'Document'}

        redirect:(to)=>{  //动态设置重定向的目标

            console.log(to) //目标路由对象就是访问的路径的路由信息

            if(to.path === '/123'){

                return '/home'

            }else if(to.path === '/456'){

                return {path:'/about'}

            }else{

                return {name:'Document'}

            }

        }

    }

四、路由嵌套子路由

在path里面,'/'都是相对根路径而言,如果写子路由,那么前面就不需要加'/'了

{

    path: '/about',

    component: about,

    children:[

        {

            path:'',  //默认的子路由 /about

            name: 'About',

            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,此时需要动态绑定v-bind

<template>

  <div class="about">

    <ul>

        <router-link :to="{name:'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>

五、命名视图:单页面多路由区域操作

在同级同时展示多个视图,而不是嵌套展示

{

      path: '/document',

      name: 'Document',

      components:{

        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}

        }

    },

    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 当前激活的路由信息对象,每个组件实例都会有,每次成功导航后都会产生一个新的对象

vue-router教程

{

    path: '/user/:userId?',

    name: 'User',

    component: user

},

<template>

    <div class="user">

        <div class="user-list">

           <!-- <router-link style="padding: 0 20px;" :to="'/user/'+item.id" :key="index" v-for="item,index in userList">{{item.userName}}</router-link>-->

            <router-link style="padding: 0 20px;" :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" style="font-size: 20px;" 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;

            if(id){

                this.userInfo = this.userList.filter((item)=>{  //this.userList是数组,现在需要返回的是一个对象,所以取数组的第一项

                    return item.id == id;

                })[0]

            }else{

                this.userInfo = {}

            }

        }

    }

}

</script>

八、给导航切换增加过度动画transition

过渡的css类名:

v-enter:定义进入过渡的开始状态

v-enter-active:定义进入活动状态

v-enter-to:定义进入的结束状态

v-leave:定义离开过渡的开始状态

v-leave-active:定义离开活动状态

v-leave-to:定义离开的结束状态

vue-router教程

自定义过度动画:

.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个组件同时出现在页面上的情况,会重叠在一起,很难看。这里就用到了过渡模式

in-out:新元素先进行过渡,完成之后当前元素过渡离开

out-in:当前元素先进行过渡,完成之后新元素过渡进入

<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,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,通过编写代码来实现导航的切换

$route为当前router跳转对象,里面可以获取name、path、query、params等

$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法

back:回退一步 //this.$router.back();

forward:前进一步,这两种都只能前进或者后退一步 //this.$router.forward();

go:指定前进回退步数 //this.$router.go(-2);如果为0,则是刷新当前页面

push:导航到不同url,向history栈添加一个新的记录,用的比较多

this.$router.push('/document');或下面的用法:

this.$router.push({ path:'/document',query:{info:'follow'} });

replace:导航到不同url,替换history栈中当前记录

十:导航钩子函数

导航发生变化时,导航钩子主要用来拦截导航,让它完成跳转或者取消

执行钩子函数位置:

router全局

单个路由

组件中

钩子函数:

router实例上(全局钩子函数,所有导航通用):beforeEach、afterEach

单个路由中(只在访问定义beforeEnter的那个组件导航上才会触发):beforeEnter

组件内的钩子:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

钩子函数接收的参数:

to:要进入的目标路有对象,到哪里去

from:正要离开导航的路有对象,从哪里来

next:用来决定跳转或取消导航,只有执行改函数才会渲染要进入的组件

案例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:'改变前',

        beforeRouteEnter( to,from,next ){

            //next();  //执行了这个才会渲染组件

            console.log(this);  //this是undefined,所以不能通过this.msg获取data,可以通过next的回调函数

            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或者第三方工具库放在这里面

怎么使用自定义的库呢:

首先在main.js引入:import Utile from './lib/utils'

然后注册到Vue实例:Vue.use( Utile )

最后:就可以在每个组件,通过this访问到$local对象,对象上面有save和fetch两个方法

如果在组件内部获取不到this,可以通过router.app.$local来获取$local对象

4、

十一、项目知识点集结

1、$refs的用法

<input type="text" class="input1" ref="input1"/>

一般来讲,获取DOM元素,需document.querySelector(".input1").value获取这个dom节点的值

用ref绑定之后,this.$refs.input1.value 就可以

2、

vue-router教程

router.beforeEach( ( to,from,next )=>{  

    if( to.meta.login ){ 

        console.log(to);  //这个是要进入的路由信息对象

    }

}

to对象里面有一个:matched数组Array[2],包含当前路由所有嵌套路径片段的路由信息,包括自己的信息和父路由的信息

3、some()方法

Array.some(function( item ){})

用于检测数组中的元素是否满足指定条件(函数提供),会依次执行数组的每个元素

如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测

如果没有满足条件的元素,则返回false

4、导航钩子函数,主要是用在进行导航是否跳转或者拦截的一些操作,比如点击导航,用户是否需要登录才能跳转还是说可以直接进行跳转

有三个地方可以写导航钩子函数

全局、单个路由、单个组件中

5、开发环境页面完成之后,使用命令:npm run build打包项目,生成dist文件夹上线

默认是把dist文件夹下面的所有文件放在服务器的根目录下

但是,如果不是放在根目录下,而是服务器的二级目录下,那么就得配置config/index.js文件,里面的assetsPublicPath属性,改为二级目录名称即可

6、页面上线之后,打开页面,然后刷新会出现404,需要配置apache里的httpd.conf文件

删除...前面的#号,释放该模块...具体看视频,只要是404,都重定向到index.html

©著作权归作者所有:来自51CTO博客作者xxxpjgl的原创作品,如需转载,请注明出处,否则将追究法律责任


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP