vue2路由手动创建&二级路由&路由传参&路由守卫&打包上线

路由手动配置:

#在@vue/cli创建的项目中,路由用法如下。
1、安装路由
	npm install vue-router@3

2:定义路由所需的组件(.vue文件)
         要实现页面about 和home两个路由,我们先定义两个组件	
         定义页面级组件,创建views文件夹,然后创建Home.vue和About.vue

3.在src目录下创建router文件夹,并在其内创建index.js作为vue路由功能模块js文件
# src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//引入定义好的路由所需组件
    import Home from '../views/Home.vue'
	#配置路由代码:
    const router = new VueRouter({routes:[{
        path:'/',//根目录 加载Home这个组件
        //组件引入两种方法 1.直接引入 2.路由懒加载
        //直接引入  component 路由所映射的组件
        component:Home
    },
    {
        path:'/about',
        //路由懒加载
        component: () => import('./../views/About.vue')
    }
    ]
    })
默认输出路由对象
export default router;

4.创建 router 实例,然后传 `routes` 配置 	 src/main.js
//在main.js中,实例化vue对象时,注册路由
# src/main.js
#通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由,也可以通过 this.$route 访问当前路由

# 1. import router from './router/index.js'

new Vue({
 # 2. router,//注册路由
    
  render: h => h(App)
}).$mount('#app')


5.在页面定义导航和路由出口
#App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <!-- 定义页面导航-->
     <!-- <router-link to="/"> 路由的入口 点击将会跳转的位置 
     根据配置好的path进行调整到执行的组件 -->
    <ul>
      <li> 
        <router-link to="/">home</router-link>
      </li>
      <li> 
        <router-link to="/about">about</router-link>
      </li>
    </ul>

    <!-- 定义路由的出口 -->
    <router-view></router-view>
  </div>
</template>

路由选中默认值

选中的路由,会增加一个类名 router-link-active

全局修改路由选中时出现的类名:

#router/index.js

const router = new VueRouter({
    routes:[
        {
            path:'/',
            component:Home
        },
        {
            path:'/about',
            component: () => import('../views/About.vue')
        }
    ],
    //设置路由选中的类名为act
    linkActiveClass:'act'

使用上述 linkActiveClass:‘act’,有一个问题,

当默认选中的时候,会修改类名为act ,第二个被选中的时候,也会有一个act类名,同时都有act名(act我们自定义的类名) 两种解决方法

第一种:此时,需要使用exact精准匹配(如果有二级路由这种方法不行)

在路由入口标签 添加exact属性

#App.vue

<template>
  <div id="app">
    <span>
     # <!-- exact 精准匹配 -->
       <router-link to="/" exact>Home</router-link>
    </span>

    <span>
           
       <router-link to="/about" exact>About</router-link>
    </span>
   
     <img alt="Vue logo" src="./assets/logo.png" />

    <!-- 出口 -->
    <router-view></router-view>
  </div>
</template>

第二种:

将路由的路径写完整:

#router/index.js

const router = new VueRouter({
    routes:[
        {
            //path:'/',
            path:'/home',
            component:Home
        },
        {
            path:'/about',
            component: () => import('../views/About.vue')
        }
    ],
    //设置路由选中的类名为act
    linkActiveClass:'act'
#App.vue


路由切换

通过路由切换,我们可以控制组件显示与否,路由组件切换的时候,默认隐藏的组件是被销毁的,注意,这里说的是默认

每一次切换,展示出来的组件,都完成了一次新的挂载

离开的组件不要被销毁:

​ 使用标签包裹路由出口

只想让某个组件不被销毁:

​ 在需要进行状态保持的路由配置项中,添加自定义meta属性:

 router/index.js:

{
            path: '/home',
            name: 'home',
            component: () => import("@/views/Home.vue"),
            meta: {
                keepAlive: true
            }
        },
App.vue:  


        
      
      

keepAlive对应的组件,只有第一次进入的时候,会走一系列的生命周期函数,再次切换回来的时候,再也不会执行mouted等声明周期函数

​ 被keep-alive包裹的路由出口对应的路由组件,会有两个新的生命周期函数:activated(),deactivated()

​ actived: 当前组件被激活的时候(我们现在说的组件,都是keep-alive包裹的路由出口对应的组件),即进入当前组件的时候

​ deactivated: 当前组件离开的时候,即切换走当前组件的时候执行的钩子函数

二级路由(嵌套路由)

#二级路由配置 router/index.js
routes:[
    {
        path:'/home',
        children:[
            // 二级路由,path分配,前面不要有 /
            //redirect 重定向
            {path:'/',redirect:'/home/tv'},
            {path:'tv',component:()=>import('./../components/tv.vue')},
            {path:'music',component:()=>import('./../components/music.vue')}
        ]
    }
]

#在一级路由组件模版中定义二级路由导航和路由出口
<!--  在一级路由组件模版中,定义二级路由导航 -->
<router-link to='/home/tv'>tv</router-link>
<router-link to='/home/music'>music</router-link>
<!--  在一级路由组件模版中,定义二级路由出口-->
<router-view></router-view>

路由传参

传统路由传参:

router/index.js

               //路由传参                
               {
                    path: '/news/newsdetali/:newid',
                    component: () => import('@/components/newDetail.vue')
                }

在news.vue中添加路由入口,匹配路由传参

1,第一种

views/news.vue

    新闻详情

2,第二种是传递当前组件data里边的值 通过模板字符串

views/news.vue

<template>
  <div>
         <router-link :to="`/news/newsdetali/${num}`">新闻详情</router-link><br />
    </div>
    <router-view />
  </div>
</template>

<script>
export default {
  props: {},
  data() {
    return {
      num: 2,
    };
  },
  methods: {},
  components: {},
};
</script>

<style scoped lang="less">
.main {
  width: 100%;
  margin: 30px auto;
  display: flex;
  justify-content: space-between;
}
</style>

components/newDetails.vue

   <!-- 根据路由传参的参数名取值-->
{{ this.$route.params.newid }}

 //   通过钩子函数获取参数
  created() {
    console.log(this.$route.params.newid);
  },
命名路由传参&对象传参:

router/index.js

               //路由传参                
              {
                    path: '/news/newsdetali/:newid/:uid',
                    name: 'Detail',
                    component: () => import('@/components/newDetail.vue')
                }

在news.vue中添加路由入口,匹配路由传参

1,params传参

views/news.vue

       // 命名路由传参      
       <router-link :to="{ name: 'Detail', params: { newid: '101', uisd: '202' } }">
      </router-link><br />

components/newDetails.vue

   
 新闻id:{{ this.$route.params.newid }}
    
{{ this.$route.params.newid }} {{ this.$route.params.uisd }} // 通过钩子函数获取参数 created() { console.log(this.$route.params.newid); console.log(this.$route.params.uisd); },

2,query传参

views/news.vue

        //对象传参
       //    
      // 命名路由传参  
       <router-link :to="{ name: "Detail",  query: { newid: '101',uisd: '202' } }">
        命名路由传参 
      </router-link><br />

components/newDetails.vue

   <!-- 根据路由传参的参数名取值-->
 新闻id:{{ this.$route.params.newid }}
    <br />
    {{ this.$route.query.newid }}
    {{ this.$route.query.uisd }}

 //   通过钩子函数获取参数
  created() {
    console.log(this.$route.query.newid);
    console.log(this.$route.query.uisd);
  },

编程式路由:

不传参(只是跳转到对应的路由):

1,path query

router/index.js

               
             {
                    path: '/news/newsdetali',
                    name: 'Detail',
                    component: () => import('@/components/newDetail.vue')
                },

在news.vue中添加路由入口,匹配路由传参

views/news.vue

    <button @click="goDetail()">点击跳转详情页路由</button>

methods: {
    goDetail() {
//点击跳转到对应路由(不传参三种种写法)
//第一种
      // this.$router.push("/news/newsdetali").catch((err)=>'');
//第二种
      // this.$router.push({
       // path: "/news/newsdetali",
      //});
//第三种
         this.$router.push({
           name: "Detail",
        });
    },
  },

传参:

一,this.$router.push:

1,path query(这里不能用params)

router/index.js

               //路由传参                
             {
                    path: '/news/newsdetali/:newid/:uid',
                    name: 'Detail',
                    component: () => import('@/components/newDetail.vue')
                }

在news.vue中添加路由入口,匹配路由传参

views/news.vue

    <button @click="goDetail()">点击跳转详情页</button>

methods: {
    goDetail() {
       this.$router.push({
        path: "/news/newsdetali",
      // 这里不可以使用params
        query: {
          //和路径接受的名字保持一致
          newid: "301",
        },
      });
    },
  },

components/newDetails.vue

   <!-- 根据路由传参的参数名取值-->
    {{ this.$route.query }}
 //   通过钩子函数获取参数
  created() {
    console.log(this.$route.query.newid);
    console.log(this.$route.query.uid);
  },

2,name params

router/index.js

               //路由传参                
             {
                    path: '/news/newsdetali/:newid/:uid',
                    name: 'Detail',
                    component: () => import('@/components/newDetail.vue')
                }

在news.vue中添加路由入口,匹配路由传参

views/news.vue

    

methods: {
    goDetail() {
     this.$router.push({
        name: "Detail",
        params: {
          //和路径接受的名字保持一致
          newid: "301",
          uid: "98",
        },
      });
    },
  },

components/newDetails.vue

   
{{ this.$route.params }}

 //   通过钩子函数获取参数
  created() {
   console.log(this.$route.params.newid);
   console.log(this.$route.params.uid);
  },
3,name query

router/index.js

               //路由传参                
             {
                    path: '/news/newsdetali/:newid/:uid',
                    name: 'Detail',
                    component: () => import('@/components/newDetail.vue')
                }

在news.vue中添加路由入口,匹配路由传参

views/news.vue

    <button @click="goDetail()">点击跳转详情页</button>

methods: {
    goDetail() {
     this.$router.push({
        name: "Detail",
        params: {
          //和路径接受的名字保持一致
          newid: "301",
          uid: "98",
        },
      });
    },
  },

components/newDetails.vue

   <!-- 根据路由传参的参数名取值-->
    {{ this.$route.query }}

 //   通过钩子函数获取参数
  created() {
    console.log(this.$route.query.newid);
    console.log(this.$route.query.uid);
  },

二,this.$router.replace:

用法和push一样

和push区别:

replace 跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 历史记录比较短只有一步后退的时候 直接退到起点
push -步-步记录历史记录每一-次回退都是回退到.上一次操作

query和params区别:

使用编程式路的时,如果跳转路径通过path配置的是,参数是通过query传递的

接受参数 this.$route.query

如果跳转路径是通过name(命名式路由)配置的,参数可以通过query也可以通过params

接受参数 this. r o u t e . q u e r y t h i s . route.query this. route.querythis.route.params

query 传递的参数 和get 一样 会拼接在url路径后面

params 的参数 不会拼接在路径后面

三,this.$router.go()

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
this.$router.go(1)

// 后退一步记录,等同于 history.back()
this.$router.go(-1)

// 前进 3 步记录
this.$router.go(3)

// 如果 history 记录不够用,那就默默地失败呗  就没反应
this.$router.go(-100)
this.$router.go(100)


eg:

<button @click="goback">返回上页</button>
methods:{
  goback(){
    this.$router.go(-1)
  }
}

路由的两种模式的区别

const router = new VueRouter({
    // mode: 'hash',
    mode: 'history',
}

**1.**hash路由在地址栏URL上有#,而history路由没有会好看一点

**2.**我们进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)

**3.**hash路由支持低版本的浏览器,而history路由是HTML5新增的API。

**4.**hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。

**5.**history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。

回答这些就行:

1、样式

​ hash路由在地址栏URL上有#,而history路由没有会好看一点

2、兼容性

​ hash路由支持低版本的浏览器,而history路由是HTML5新增的API。

3、请求的时候 hash 刷新 history 报错 路由 传递数据 #/不会发送给服务器
我们进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)
​ hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。

路由守卫

全局路由守卫 路由独享守卫 组件内的路由守卫
#router/index.js
// 创建VueRouter实例对象
const router = new VueRouter({
   /*  routes:[]定义路由配置,routes里面的每一个选项是一个对象,包含每个路由的具体配置
    routes之所以是数组,因为里面包含多条路由 */
    routes:
        {
            path: '/',
            redirect: '/home'
        },
        {
            path: '/home',
            component: () => import("@/views/Home.vue"),
            meta: {
                titleName: '首页'
            }
        },

        {
            path: "/buy",
            component: () => import("@/components/buy.vue"),
            meta: {
                titleName: '购买',
                xiaoli: true
            },
            // 路由独享守卫
            // beforeEnter: (to, from, next) => {
            //     if (window.localStorage.getItem('islogin') == "true") {
            //         next()
            //     } else {
            //         alert("请先登录")
            //         next("/login")
            //     }
            // }
        },
        {
            path: "/buy/:newid",
            component: () => import("@/components/buy.vue"),
            meta: {
                titleName: '购买',
                xiaoli: true
            },
        },
        {
            path: "/login",
            component: () => import("@/components/login.vue"),
            meta: {
                titleName: '登录'
            }
        }
});

// 添加全局路由前置守卫
router.beforeEach((to, from, next) => {
    // 判断要跳转的路径是否是/buy  同时判断登陆状态是否是未登陆 所以取反
    //   false      if( true)
    if(to.fullPath == '/buy'  && !localStorage.getItem('islogin')){
        next('/login');
    }
            next();
    
})


router.afterEach((to, from,) => {
    // 让网页标题变化
    document.title = to.meta.titleName
})

// 把当前的路由实例 暴露出去 方便其他模块调用
export default router;
#components/buy.vue

<template>
  <div>
    <h1>购买页</h1>
    接收传递的参数:{{ this.$route.query.newid }}{{ this.$route.params.newid }}
    <router-link to="/buy/002">点击购买传参2</router-link>
  </div>
</template>

<script>
export default {
  props: {},
  data() {
    return {};
  },
  methods: {},
  components: {},
  //   组件内守卫
  //   beforeRouteEnter(to, from, next) {
  //     if (window.localStorage.getItem("islogin") == "true") {
  //       next();
  //     } else {
  //       alert("请先登录");
  //       next("/login");
  //     }
  //   },
  beforeRouteLeave(to, from, next) {
    // alert("你要离开了吗");
    // next("/home");
    console.log(0);
    next();
  },
  beforeRouteUpdate(to, from, next) {
    console.log("路由传递的参数变化了");
    next();
  },
};
</script>

<style scoped lang="less">
</style>

谈一谈路由守卫

路由守卫:

​ 就是对路由进行一些保护,比如权限的验证

​ 在路由的跳转前、后 进行校验

​ 分为: 全局路由守卫 路由独享守卫 组件内的路由守卫

​ 全局分为两种: 前置 后置

​ 前置: beforeEach(to,from,next)

​ 后置: affterEach(to,from)

​ 路由独享守卫,写在当前路由的配置项下面,beforeEnter(to,from,next)

​ 组件内路由守卫: beforeRouteEnter(to,from,next) 通过路由进入当前组件后

​ beforeRouteUpdate(to,from,next) 通过路由传值的时候触发 to 拿 params query 参数

​ beforeRouteLeave(to,from,next) 通过路由离开当前组件后

打包上线

1、使用npm run build命令运行

​ 得到一个dist文件夹,里面后html、js、css文件

​ 直接打打开html,发现打不开

​ 需要部署在服务器上

2、创建自己的服务器

​ 2.1、创建一个文件夹,通过vscode打开

​ 2.2、在终端中,输入npm init -y

​ 2.3 、安装express npm install express

image-20230103215718229

​ 2.4、在文件夹下面新建一个server.js

//server.js
const express = require('express');

const app = express();

app.get('/news', (req, res) => {
    res.send({
        name: '新闻三十分',
        author: '陈福国'
    })
})
app.listen(5005, (err) => {
    if (!err) {
        console.log('服务器启动成功,localhost:5005');
    }
})

​ 2.5、启动server.js node server.js

​ 2.6、页面输入路径测试

​ 2.7、服务器搭建成功后,新建一个static文件,把build后的静态资源全部放入当前文件夹,搞定

const express = require('express');

const app = express();

//配置静态资源路径
app.use(express.static(__dirname + '/static'))

app.get('/news', (req, res) => {
    res.send({
        name: '新闻三十分',
        author: '陈福国'
    })
})
app.listen(5005, (err) => {
    if (!err) {
        console.log('服务器启动成功,localhost:5005');
    }
})

2.8 确保启动服务器后,输入路径http://localhost:5003 即可

你可能感兴趣的:(vue.js,javascript,前端)