Day41:Vue路由基础

路由切换页面的时候,视图改变了,前端的路径也变了,但是没有重新访问该页面。可以说是视图和url的匹配关系。

vue2对应的是路由的v3版本,vue3对应的是路由的v4版本

vue2路由

选择安装版本时,@3 vue2选择三号版本

 npm i vue-router@3

  1. 新建文件夹,放基础配置,引入vue方法,调用核心方法路由

  2. 生成实例并导出

  3. 在实例中生成路由对象
  4. mode为路由模式,分为History和hash

  5. 每个路由对象中有最关键的两个属性,它们共同构建了路由映射表

  6. 在路由映射表头部设置首页默认显示样式

  7. 在main中引入路由并挂载到vue实例中

  8. 需要将视图切换的区域最终渲染到模板(app)中(调用VueRouter方法的时候默认注册了router-view组件

  9. 给按钮包裹跳转组件。跳转组件routerLink可以进行跳转,必须要写to属性,指定跳转的链接地址

  10. routerLink是一种声明式导航,它的特点:点击被包裹的按钮时,页面跳转时会自动给被跳转的页面添加类名,可以通过这些类名给被选中的页面添加样式。
  11. hash模式在url多了一个#/,这样是不会发送请求校验给后端的。所以在前端使用时推荐使用History模式。
  12. 如果我们需要处理不存在的路径(没有在路径列表中匹配到内容),进行404处理,写一个NotFound页面,使用通配符来匹配404路径

  13. $router实现页面跳转,这种导航形式叫编程式导航。进入到404页面后,开启定时器,定时器结束自动跳转到首页。我们可以在mounted生命周期中,在进入到页面之后,打印this,新增了$route $router ,只有挂载了才会出现,(...)是响应式属性,使用this.$router,在整个项目的路由中调用push方法进行跳转

  14. push和replace的区别:replace执行的跳转无法记录,也就无法回退,可以进行无痕功能的书写。push可以记录跳转,可以回退,能执行普通功能的编程式导航。
<template>
  <div>
    <!-- 需要将视图切换的区域最终渲染到模板中,需要一个叫路由的出口 -->
    <router-view></router-view>  
  </div>
</template>
<script>
  export default {
    data(){
      return {
        song:"",
      }
    },
    methods:{
      search(){  // 做页面跳转
        this.$router.push(`/search?song=${this.song}&peiqi=123`)
      }
    }
  }
</script>
import Vue from 'vue'
import App from './App.vue'
import router from './rouder'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  router // 将路由挂载到vue实例上
}).$mount('#app')
// 配置路由_前端路由,是视图和URL的映射关系
import VueRouter from "vue-router";
import Vue from 'vue'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Self from '../views/Self.vue'
import NotFound from '../views/NotFound.vue'
import Search from '../views/Search.vue'
// vue需要使用VueRouter
Vue.use(VueRouter)
// 生产一个router实例 传入一个配置对象,这个配置对象表达了视图和URL的映射关系
const router = new VueRouter({
    mode: 'history',
    // routes是一个数组,这个数组中表达了映射关系
    // 两组映射关系,一组/about => About 组件,一组/self => Self组件
    // routes是一个对象形式,里面表达映射关系
    routes: [
        {
            path:'/',  // 表示首页默认显示
            name:'home',
            component:Home,
        },
        {
            path: '/about', // 绝对路径,不要加.  对应了一个叫about的组件
            name:'about',
            component: About,  
          // 不要加s!!先定义about组件。路由组件不放在components中,放在views中
        }, {
            path: '/self',
            name:'self',
            component: Self,
        },
        {
            path:'*',
            name:'404',
            component:NotFound,
        },
        {
            // 在需要被跳转的页面配置动态占位符
            path:'/search/:song/:id',
            name:'search',
            component:Search,
            // props:true // 传参可以用props接收
        },
    ]
})
export default router
<template>
  <div>
    <!-- <router-link to="/about"><button>About</button></router-link>
    <router-link to="/self">  <button>Self</button></router-link> -->
    <button @click="$router.push('/about')">About</button>
    <button @click="$router.push('/self')">Self</button>
    <br/>
    <input type="text" placeholder="请搜索" v-model.trim="song" 
    @keyup.enter="search">
  </div>
</template>
<script>
  export default {
    data(){
      return {
        song:"",
      }
    },
    methods:{
      search(){
        // 做页面跳转 查询参数,传递参数
      //   this.$router.push(`/search?song=${this.song}&peiqi=123`)
        // 2 动态参数
        this.$router.push(`/search/${this.song}/123`)
        /* this.$router.push({
          name:'search',
          parent:{
              song:this.song,
          },
        }) */
      }
    }
  }
</script>
<style scoped>
.router-link-active button{
  background-color: plum;
  color: #ccc;
}
</style>

网易云项目

删掉node_modules重新执行npm i

打开之后 node app.js ,不要关闭终端

  1. 使用搜索功能时,回车后使用编程式导航进行跳转
    1. 使用v-model动态绑定输入的内容为song
    2. 监听enter按下来传递song向下一个页面传递去发送请求
  1. 在第二个页面中,获取到上一个页面中输入的内容,发送ajax请求,得到数据。(路由组件之间如何传参)——查询参数格式
    1. 查询参数 在app的 中 this.$router.push(`/search?song=${this.song}`);
    2. 这是传参语法格式,可以通过URL传递参数。value是动态变量,所以动态包裹在模板字符串中,在路径上已经能看到传参了
    3. 可以通过{{ $route.query.song }}来接收传参,也可以在url后面增加其他参数,用&符来连接
    4. 在search中接收

      其中this.$route.query是用来接收参数的,利用传递过来的关键字song发送ajax请求,并将请求得到的数据渲染到页面上。
  1. 动态参数传参
    1. 在传递的URL直接传参

    2. 在需要被跳转的页面,添加动态占位符,要传几个参,就配置多少动态占位符

    3. 在被跳转的页面接收参数,

    4. 如果传递的是字符串值,建议使用查询参数;如果传递的是数值,建议使用动态参数
    5. 配置表的时候添加name属性,可以通过name属性传参

    6. 所以在配置表时,最好为每个页面都添加name属性
  1. 如果向path路径传递params参数(传递params参数需要写占位符),不能成功。所以path传递参数,只能用query,不能用params。接收参数的时候书写的方法也需要和传参方法一致,否则无法成功

  2. 使用props传参(不建议)
    1. 在映射表中开启props

    2. 在子组件中接收props,并且在页面上渲染接收内容

1.vue3路由入门

1.1 安装依赖

在我们的Vite项目中,通过命令来安装Vue-router,vue3版本使用的是最新的Vue-router@4版本。

npm install vue-router

可以在package.json中确认成功安装了依赖。

1.2 配置路由

我们现在有这样一个需求:在页面上有2个button,点击button搜索,可以跳转到一个搜索页面,点击button列表,可以跳到一个列表页面。

稍微分析下,就应该知道这个需求要用路由来实现,我们现在需要2个路由页面(搜索 列表),路由页面其实就是组件。

我们首选需要来在项目中配置一下路由:

在项目的src目录中新建一个router目录,再建立一个index.js来存放我们的路由配置文件。

import { createRouter, createWebHashHistory } from 'vue-router'
import Search from '../components/Search.vue'
import List from '../components/List.vue'
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/search',
      name: 'search',
      component: Search,
    },
    {
      path: '/list',
      name: 'list',
      component: List,
    },
  ],
})
export default router

然后需要在主入口中引入路由配置文件,作用到整个项目中。

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index.js'
createApp(App).use(router).mount('#app')
1.3 内置路由组件使用

在App.vue也就是项目的根组件中,通过Vue-router内置的2个组件和,最终实现页面的正确跳转。

<template>
  <div>
    <h1>这是首页</h1>
    <router-link to="search"><button>搜索页</button></router-link>
    <router-link to="list"><button>列表页</button></router-link>
    <router-view></router-view>
  </div>
</template>

可以理解为路由页面的出口,它可以根据路径来决定具体展示哪个组件 可以理解一个a标签,to属性决定它最终跳转到哪个路径

此时我们已经实现了路由页面的正确跳转。

2.路由传参

当路由跳转到一个页面的时候,往往需要携带一些信息,然后通过这些信息可以向服务端请求数据渲染页面,那如何来实现路由传参呢,Vue给我们提供了2种常见的形式。

2.1 query传参

利用查询字符串的形式来进行参数传递。

在刚才的搜索页中,现在希望点击搜索按钮能够跳转到详情页面,此时我们在做路由跳转的时候必须思考一个问题:我必须将我在搜索页种输入的文本内容传递到详情页面。

在路由配置文件中,新增一项配置信息。

routes: [
  {
    path: '/search',
    name: 'search',
    component: Search,
  },
  {
    path: '/list',
    name: 'list',
    component: List,
  },
  {
    path: '/detail',
    name: 'detail',
    component: detail,
  },
],

然后在搜索按钮那里通过来实现跳转,此时在路径中通过查询字符串的形式来携带参数

<template>
  <div>
    <input type="text" placeholder="请输入搜索内容" v-model="text" />
    <router-link :to="`/detail?text=${text}`"><button>点击搜索</button></router-link>
  </div>
</template>

<script setup>
  import { ref } from 'vue'
  const text = ref('')
</script>

最终在详情页中来接受这个传递过来的数据。

在url中可以直接观测到传递的数据。

通过Vue-router提供了一个hook函数useRoute可以获取到传递过来的query参数。

<template>
  <h1>这是搜索的内容:{{ text }}</h1>
</template>

<script setup>
  import { onMounted, ref } from 'vue'
  import { useRoute } from 'vue-router'
  let text = ref('')
  onMounted(() => {
    text.value = useRoute().query.text
  })
</script>

最终页面也能正确显示传递过来的参数。

2.2 params传参

刚才的需求同样可以使用另一种方式来实现,我们称之为params动态传参。

使用这种方式实现传参的时候在配置路由信息时需要额外处理。

{
  path: '/detail/:text', //这里添加了一个:text的占位符 这个占位符名称可以任意指定
    name: 'detail',
    component: Detail,
    },

然后是通过搜索按钮进行跳转时传递参数。注意区分和query传参的格式区别。

<template>
  <div>
    <input type="text" placeholder="请输入搜索内容" v-model="text" />
    <!--query传参 <router-link :to="`/detail?text=${text}`"><button>点击搜索</button></router-link> -->
    <router-link :to="`/detail/${text}`"><button>点击搜索</button></router-link>
  </div>
</template>

最终在详情页中来接受参数。

<template>
  <h1>这是搜索的内容:{{ text }}</h1>
</template>

<script setup>
  import { onMounted, ref } from 'vue'
  import { useRoute } from 'vue-router'
  let text = ref('')
  onMounted(() => {
    // text.value = useRoute().query.text   这是query传参的接受方式
    text.value = useRoute().params.text
  })
</script>

页面同样能正确显示参数内容。

3.编程式导航

3.1 基本使用

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以通过获取router的方式来控制页面的跳转。

上面示例中的跳转都是通过<router-link> 渲染的a标签实现的,如果我们希望页面能够自动跳转呢?具体来说,希望进入到首页后过3S自动进入到搜索页,这种场景下,使用<router-link> 显然无法实现,因为a标签必须手动去点击,我们现在希望通过代码能完成点击,这里就需要使用编程式导航了。

在App.vue中通过useRouter来获取整个router,然后开启一个3s的定时器,通过push方法进行路径的跳转。

<script setup>
  import { onMounted } from 'vue'
  import { useRouter } from 'vue-router'
  onMounted(() => {
    const router = useRouter()
    setTimeout(() => {
      router.push('/search')
    }, 3000)
  })
</script>

<template>
  <div>
    <h1>这是首页</h1>
    <router-link to="/search"><button>搜索页</button></router-link>
    <router-link to="/list"><button>列表页</button></router-link>
    <router-view></router-view>
  </div>
</template>

当你点击 <router-link> 时,Vue内部其实仍然会调用push这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...) ,可以根据实际需求来选用更合理的方式。

3.2 路由传参

和声明式导航类似,编程式导航也可以采用query和params2种方式传递参数。

// 字符串路径
router.push('/users')

// 带有路径的对象
router.push({ path: '/users' })

// 命名的路由,并加上动态参数  同样需要对应地配置路由信息
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
3.3 replace,push和go

刚才详细说明了push方法可以实现编程式导航跳转,replace方法同样可以,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

go方法采用一个整数作为参数,表示在history历史中前进或后退多少步,类似于 window.history.go(n)。

4.路由重定向和404

4.1 重定向

当我们匹配到某个路径进行页面跳转的时候,希望能够再次跳转到另一个路由地址,可以采用重定向来实现。

在上面的示例中,比如进入首页就希望能够自动跳转到搜索页:

routes: [
  {
    path: '/',
    redirect: '/search', //配置首页的路由信息时通过redirect属性来实现重定向
  },
  {
    path: '/search',
    name: 'search',
    component: Search,
  },
  {
    path: '/list',
    name: 'list',
    component: List,
  },
  {
    path: '/detail/:text?',
    name: 'detail',
    component: Detail,
  },
],
4.2 404

当我们访问一些不存在的路径时,一般都会给出一个404的的页面提示,404也是通过重定向来实现的。

首先可以新建一个404页面组件,当路由路径没有正确匹配的时候,统一重定向到404这个页面中,需要注意path路径的格式。

import { createRouter, createWebHashHistory } from 'vue-router'
import Search from '../components/Search.vue'
import List from '../components/List.vue'
import Detail from '../components/Detail.vue'
import NotFound from '../components/404.vue'
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    ...
    {
      path: '/404',
      name: '404',
      component: NotFound,
    },
    {
      path: '/:catchAll(.*)',
      redirect: '/404',
    },
  ],
})
export default router

5.路由组件传参

我们之前已经深入学习了如何进行路由组件的参数传递,但之前通过useRoute来获取路由参数的方式耦合度太强,我们希望用我们最习惯的方式props来获取这个参数。

5.1 布尔模式

当 props 设置为 true 时,route.params 将被设置为组件的 props

回到之前的示例中来实现一下,首先在路由配置信息中添加props这个属性,并设置为true。

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    ...
    {
      path: '/detail/:text?',
      name: 'detail',
      component: Detail,
      props:true
    },
    ...
  ],
})

在detail页面中,便可以通过props形式来接受这个参数并且放到模板中使用了。

<template>
  <h1>这是搜索的内容:{{ props.text }}</h1>
</template>

<script setup>
  import { onMounted, ref } from 'vue'
  let text = ref('')
  onMounted(() => {
    // text.value = useRoute().query.text   这是query传参的接受方式
    // text.value = useRoute().params.text  这是params传参的接受方式
  })
  const props = defineProps(['text'])
</script>
5.2 对象模式

当希望给路由组件传递一些静态属性的时候,使用对象形式是更好的选择。

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    ...
    {
      path: '/list',
      name: 'list',
      component: List,
      props:{
        a:5,
        b:6
      }
    },
    ...
  ],
})
//List.vue中
<template>
  <ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>{{ a }}</li>
  <li>{{ b }}</li>
  </ul>
  </template>

  <script setup>
  defineProps(['a', 'b'])
  </script>
5.3 函数模式

这种模式大家也可以了解一下,props还可以是一个函数,返回的对象最终会被并入到传递给路由组件的props中。

const routes = [
  {
    path: '/detail',
    component: Detail,
    props: route => ({ query: route.query.q })
  }
]

URL /detail?q=vue 将传递 {query: 'vue'} 作为 props 传给 Detail组件。

6.历史记录模式

在创建路由器实例时,history 配置允许我们在不同的历史模式中进行选择。

6.1 Hash模式

hash 模式是用 createWebHashHistory() 创建的,我们上面的示例便是采用了这种模式。

js

import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
  history: createWebHashHistory(),
  routes
})

它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式。

6.2 HTML5 模式

用 createWebHistory() 创建 HTML5 模式,推荐使用这个模式:

js

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
})

当使用这种历史模式时,URL 会看起来很 "正常",没有了那个多余的#。

不过,问题来了(这个问题一般都是后端运维来解决)。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id,就会得到一个 404 错误。这就丑了。

不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。漂亮依旧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值