vue路由改变了数据和内容不变的解决办法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue路由改变了数据和内容不变的解决办法相关的知识,希望对你有一定的参考价值。

参考技术A 场景:
1.路由改变了但是数据和内容没变,刷新后才变化
2.动态路由/cate/:id/index.html类似这样只改变id号的场景,由于router-view是复用的,单纯的改变id号并不会刷新router-view

解决办法有两种:【1】【2】

router-view组件复用与否的几种常见情况:
(1)不设置 router-view 的 key 属性
由于 Vue 会复用相同组件, 即 /page/1 跳转到 /page/2 或者 /page?id=1 跳转到 /page?id=2 这类链接跳转时, 将不在执行created, mounted之类的钩子, 只有beforeRouteUpdate钩子
(2)设置<router-view :key ="$route.path">
从/page/1 跳转到 /page/2, 由于这两个路由的$route.path不一样, 所以组件被强制不复用, 相关钩子加载顺序为:
beforeRouteUpdate => created => mounted
从/page?id=1跳转到 /page?id=2, 由于这两个路由的$route.path一样都是/page, 所以和没设置 key 属性一样, 会复用组件, 相关钩子加载顺序为:
beforeRouteUpdate
(3)设置<router-view :key ="$route.fullPath">
从/page/1跳转到/page/2, 由于这两个路由的$route.fullPath不一样, 所以组件被强制不复用, 相关钩子加载顺序为:
beforeRouteUpdate => created => mounted
从/page?id=1跳转到/page?id=2, 由于这两个路由的$route.fullPath也不一样, 所以组件被强制不复用, 相关钩子加载顺序为:
beforeRouteUpdate => created => mounted

vue-router

在研究vue的路由前,先说说什么是路由

路由是指 当地址栏的改变时页面做出改变

路由分为前端路由 和 后端路由

  • ==后端路由==就是指访问和相应了,地址栏是百度,当前的路由就是百度,如果跳转到淘宝,路由就是淘宝,后端路由会带来页面刷新
  • ==前端路由==是自己通过API改变地址栏的内容,再判断地址栏的值修改页面的内容,最重要的是前端路由是可以被浏览器的history记录,history记录的意思就是点击返回是返回上一个路由,到了最后一个路由关闭页面,完美的模拟后端路由的效果

为什么要用前端路由,前端路由带来了什么

  • 漂亮的路由地址,去看看网易云音乐的网页版地址和哔哩哔哩的网站地址
  • 减少页面请求,只需要ajax修改数据,只需要第一次进入请求一次页面数据就行,称为单页面应用,简称SPA

起步
如果没有安装vue-router
自己去看开发文档

  1. 先npm下载
  2. 然后在创建配置文件和基础配置文件的模板
  3. 最后在main.js引入

vue的路由是用什么API historyhash

window.history
// 方法有
history.pushState
history.replaceState

window.hash
// 方法有
window.hashchange = function(){ ... }

这两个路由对应的就是vue-router的配置的参数mode,默认是hash

new Router({
  mode: 'history', // history 和 hash
  routes: [{
    path: '/',
    component: () => import('page/home'),
    children: [{
      path: 'list',
      component: () => import('page/list'),
    }]
  },{
    path: '/404',
    component: () => import('page/error')
  }]
})

mode的参数有什么区别
history模式,这是个新API,所以兼容性不好,地址栏没有【#】,哔哩哔哩就是没带【#】号的,更好看,而且在微信的分享等地方是禁止用【#】的
hash模式,地址栏带有【#】,网易云音乐就是带【#】号的,我不喜欢这个模式

routes参数是一个数组,这个数组需要学的有==子路由的配置==和==参数路由的配置==
在配置之前了解一下vue怎么把路由进行显示出来的,看路由的component参数,这个是指当有人访问这个路由,我就给他看哪个页面的传参,参数是一个页面的地址,首先找到这个路径下的地址,是 ==.vue==后缀文件,打开后是这样的

<template>
   <div>
     <div>HOME</div>
     <div>{{ msg }}</div>
   </div>
</template>
<script>
export default {
  // 这个name是无意义的,只是为了好看,是代码规范,但不是代码规定
  name: 'HOME',
  data(){
     return {
       msg:"helloword"
     }
  }
}
</script>
<style scoped>
// 这是写样式的
// scoped属性的意思是这里的样式只服务这个vue文件
</style>

那这个文件被显示到哪里了呢

vue格式文件显示在<router-view />标签里,这也是子路由的配置理解,比如上面的路由配置,当路由是【/】时,页面显示的是home.vue这个文件,如果路由是【/404】就显示的是error.vue文件,home和error是展示在同一个<router-view />里的,因为他们属于同一级,把这个<router-view />理解成div的innerHTML也行,所以当我们要给路由【/】添加子路由时,就需要在home.vue文件里放置一个<router-view />标签,如下

<div>我是HOME.vue</div>
<router-view />

当路由是【/】时,我们会看到我是HOME.vue,看不到<router-view />,当我们访问【/list】时,<router-view />会绘制上list.vue文件的代码,就能看到页面显示,我是HOME.vue,我是List.vue,应该很好理解吧

那么问题来了,一级配置,也就是上面的【/】和【/404】是显示在哪个<router-view />里的,在文件列表有个APP.vue文件,这个才是一级路由显示的地方,这个文件又显示在哪呢,显示在public文件夹的index.html,打开index.html,会看见一个id为app的div,跟srcipt引入插件的方式一样,vue脚手架最后也只是把vue给new一下,显示到#app里而已,查看main.js

import App from './App'
import store from './store'
import router from './router'

new Vue({
  // 这个就是路由
  router,
  // 这个是vuex
  store,
  // render渲染,$mount是代表index.html的id
  // 即我把App.vue渲染到id为app的div里
  render: h => h(App)
}).$mount('#app')

现在应该知道怎么配子路由了吧,接下来参数路由【/:】

new Router({
  mode: 'history', // history 和 hash
  routes: [{
        path: '/:type/:id',
        component: () => import('page/type'),
    },{
        path: '/home/test',
        component: () => import('page/ceshi'),
    }]
})

上面的路由是要干什么呢,是想实现根据类型和id去返回页面的功能,比如【/book/0001】,是指找一个编号是0001的书,【/movie/123】是找一部编号123的电影,所以我才说前段路由是那么的好看,如果是后端路由应该是【xxx.com/index.html?type=movie&id=123】

在上面有个【/home/test】的配置,如果有人访问这个,会跳转到上面去吗,==这是不会的==,==参数路由是最后被判断的==,这个插件是非常智能的,先把固定的判断完,没合适的再去找参数路由

问题来了,我怎么去知道当前的type是什么,id是什么,去到type.vue这个文件里

mounted(){
   // 把当前页面的路由打印出来
   console.log(this.$route)
   // 里面有个params属性,是个对象
   // 把这个对象取值判断就行
   console.log(this.$route.params)
}

除了params对象,路由还有一个query对象,就是正常的问号传参,试一下在地址栏上路由的最后面加上【?name=name&age=age】,就会在路由里看到query对象,很好理解,不写栗子了

总结下路由的配置
路由的配置就是复制黏贴,没什么可玩性,按照文档设置好就行

路由的监控
如果我想根据路由的整体的变化做一些判断呢,如果我想控制一些权限呢
在路由的配置页面加上这个方法

new Router({
  mode: 'history', // history 和 hash
  routes: [{
        path: '/:type/:id',
        // 先配置一个title属性,你想写什么属性都行
        title: "我是title",
        component: () => import('page/type'),
    }]
})

下面这个监听的代码可以写在router.js里,最好还是单独拆一个文件出来

router.beforeEach((to, from, next) => {
  // 这个to就是当前页面的路由的对象,也就是this.$route
  console.log(to)
  if(to.title){ document.title = to.title } 
  else{ document.title = "pdt-1997" }
  if(user=="pdt"){
     console.log("没资格访问")
     // 重定向到主页
     next({path:'/'})
  }else{
     // next一定要有,不然路由不执行
     next()
  }
})

router.afterEach(() => {
  
})

怎么跳转
上面的测试都是手动去改路由,再刷新页面
首先就是用标签去跳转,理解为a标签,一般不用标签跳转

<router-link to="/">去到主页</router-link>
<router-link :to="{path:'/index',query:{id:'xxx',name:'xxx'}}">

push和replace
push是把当前路由A存起来,然后跳转B,如果点击返回会到A
replace是跳转B,然后把B替换A,如果点击返回A之前的路由或者关闭页面

this.$router.push({ path:"/it/"+data.id ,query:{ page:this.pageNo }})
this.$router.replace({ path:"/it/"+data.id ,query:{ page:this.pageNo }})

应该注意的点

vue文件的template标签的子标签只能有一个

<template>
   <div>
     <div>HOME</div>
     <div>{{ msg }}</div>
   </div>
   <div> 如果再加上这个会报错 </div>  
</template>

hash的实现原理

<a href="#/home">首页</a>
<a href="#/about">关于</a>
<div id="html"></div>

<script>
    window.addEventListener('load',()=>{
        html.innerHTML = location.hash.slice(1);
    });
    window.addEventListener('hashchange',()=>{
        html.innerHTML = location.hash.slice(1)
    })
</script>

history的实现原理

<a onclick="go(/home)">首页</a>
<a onclick="go(/about)">关于</a>
<div id="html"></div>

<script >
    function go(pathname) {
        history.pushState({},null,pathname)
        html.innerHTML = pathname;
    }
    window.addEventListener('popstate',()=>{
        go(location.pathname);
    })
</script>

以上是关于vue路由改变了数据和内容不变的解决办法的主要内容,如果未能解决你的问题,请参考以下文章

vue项目中的一些问题

vue-router动态路由添加及路由刷新后消失的解决办法

json文件中文字改变但是网页却不变

NO17--vue父子组件间单向数据流的解决办法

路由器不重启,是不是ip就永远不变

vue中类名和组件经过刷新不对应的解决办法