Vue进阶篇

前引

  今天是2018年12月30,虽不是2018年的最后一天,但是却是自己在2018年写的最后一篇博客了,昨天下班在地铁上闲来无事,翻起了关注的一些公众号发的技术博文,里面就提到写博客的重要性,其实这样的内容看了N多了,但是,里面有一句感觉说的很对,现在的博客变了味了,因为我们可以Ctrl+c、Ctrl+v,短短几秒钟就是一遍几千字的博文,真正自己写出的博文需要花费很长的时间。说心里话,自己的博客中也有,大概有三分之一吧,突然莫名的恐慌,因为很可能就是这三分之一的博客,就会掩盖自己花费精力完成的其他的博客,被别人冠上这么一个标签,这人也是一个充数的、装大半蒜的家伙。其实内心已经一万个草泥马了,因为我们都是人,说话说的好,一个人一直做好事,但是突然有一天做了一件坏事,大家就定义这个人是坏人,好人难做啊,同样的,写博客亦如此。

  不感慨了,看到的小伙伴们支持一下,当然欢迎转载,欢迎Ctrl+c,但是有一个请求,在文章的最上方请注明文章来源,非常感谢。

  接下来,说今天的正事,本篇博客的正事,Vue的进阶篇,进阶,谈不上,也算是一点稍微不那么基础的基础吧,更基础的欢迎浏览本人的另一篇博客Vue基础篇

 

老习惯,开始正文之前,先来了解一些必知必会的小知识点

前言

  1,组件和插件的区别(组件是一个项目的必须组成部分,而插件是不必须的,动态的,即插即用)

  2,在一个项目中,一个文件以.开头表示电脑系统的隐藏文件。

  3,在前端中,一个项目中的index文件或main文件,默认为一个项目的入口

  备注:在vue-cli项目中会有一个包含很多包的文件,这个文件的文件名就是node_modules,还有一个.gitignore的文件,这个隐藏文件的意思就是git忽视的一个文件,打开这个文件,里面的有这些内容:

.DS_Store
node_modules
/dist

  在这个文件中,我们可以配置当前项目一些忽略的文件,支持部分正则匹配。比如,node_modules项,如果项目上传git,或者GitHub时,会自动忽略掉这个文件,所以我们上传到GitHub上的项目中是不包含这个node_modules文件的,这也是GitHub的一个局限性,大的文件无法上传,导致我们从GitHub上下载的一些开源的项目,并不能直接使用,对于vue的项目,还需要使用一个命令:npm install  将包含很多包的这个文件下载下来。

  因此,我们从GitHub上下载下来的vue的开源代码,第一步就是运行一个命令:npm install (一般在当前目录下)   

  GitHub中,每个开源文件都有一个文件READMI.md(markdown文件),这个文件中,会告诉我们怎么使用这个项目。

  赠送的小技巧:另外的我们在一个项目名中,看到带有awesome的,表示一个生态系统,里面在这个基础上封装了很多插件和模块。

vue-cli开始

  在vue中,一个.vue文件就是一个vue的组件。

一个标准的可重用的vue组件的格式:

<!--一个组件包含html、css、js-->

<template>
  <!--组件的结构-->

</template>

<script>
    // 处理业务逻辑
  export default {
name: "Vheader",

  } </script> <style> /*页面的样式*/ </style>

  备注

  1,在template模板中,必须有一个包裹的标签。   需要注意的是:template不是一个标签,是vue中的一个模板

  2,在vue中,一个组件的命名规范是:首字母必须大写,比如:所有的组件以“V”开头。一个组件中的data(数据属性)必须是函数,这个函数必须return一个对象。

  3,在一个项目中的MP3文件,由于webpack的打包编译,是无法直接引入到src中,所以导入MP3文件时,必须当做模块来引入

import song1 from './assets/薛之谦 - 一半 [mqms2].mp3'

<audio src="song1" autoplay controls></audio>

  总之,所有的静态资源都可以作为模块导入 。

组件的引入

  组件的引入很简单 ,分三步:

  1,导入组件       import  Vheader  from  './components/Vheader.vue'

  2,挂载组件       在export  default 中  定义一个key为components,值为一个对象,这个对象中放着导入键值对;键为变量名,值为组件名,在es6中,键值相同时,可以缩写为一个单一的值。

  比如:components:{ Vheader }

  3,在template模板中使用组件:     <Vheader> </Vheader>

备注:在父组件中定义的样式类,默认为全局的样式类,所以如果要保证自身元素的样式,在子组件的style标签中加入:scoped即可     <style  scoped><style>

父子传值

父子组件的传值:

父组件向子组件传值

  1,绑定自定义的属性   :  在父组件中对应的子组件的模板上绑定属性。

    比如:<Vcontent  :menu=“menus”><Vcontent>     #menu为定义的属性名   menus为数据属性

  2,在子组件中接收这个自定义的属性,并且属性必须要验证   ,接收的属性放在props中

    比如:props:{ menu:Array }         备注:接收的变量名必须与自定义的变量名保持一致

  3,这时子组件中的数据值就是这个对应的menu变量,我们也可以在数据属性中重新赋值

    比如:data(){ return {  menus:this.menu  }  }    #这时我们在子组件用的值就是menus了

  备注:这里的this是指当前的子组件的Vue对象,Vue创建组件时:Vue.component()

子组件向父组件传值

  1,在子组件中定义一个事件: 比如:在Vheader中定义一个点击事件。     

<template>

    <div class="header">

        //  定义一个点击事件   addOne   
        <button @click="addOne">添加一个菜单</button>
    </div>
</template>

<script>
    export default {
        name: "Vheader",
        data(){
            return {
               
            }
        },
        methods:{
             //  事件触发自定义的事件
            addOne(){
                  this.$emit('addMenu','酸菜鱼');  #this.$emit(“自定义事件名”,“往父组件传的值”)
            }
    }
    }
</script>

<style scoped>

</style>

  2,触发自定义的事件,this.$emit("自定义的事件名","要向父组件传的值")    #备注:固定写法,而且自定义的事件名必须与父组件中自定义的事件名一致

  3,在父组件中对应的子组件模板中,定义好这个自定义事件,比如:<Vheader @addMenu="addHand"></Vheader>

    并在对应的事件中,接收传的值,并做相应处理。

   methods:{
          addHand(value){
              this.menus.push(value);   #接收传的值,并将值添加到父组件的menus数组中
          }
    }    

vue的优势和用途

  

vue主做单页面应用

  比如:饿了么、掘金、网易云音乐、豆瓣、知乎等等

在vue中,可以给每一个单页面(组件)配置一个路由,这个是由vue-router来控制的 

vue-router

首先,要在我们的项目中下载安装这个vue-router   

npm install vue-router

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:

在项目的入口  main.js中

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

接着就可以在这个main.js中配置组件

1. 定义 (路由) 组件。

// 比如:
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 也可以从其他文件 import 进来
import Vhome from './components/Vhome.vue' import Vuser from './components/Vuser.vue'
2. 定义路由每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]
3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
}
4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')
现在,应用可以启动了!

  Tips: 通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由:

console.log(this.$router)   #打印$router的结果:

    []
    app:Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    apps:[Vue]
    beforeHooks:[]
    fallback:false
    history:HashHistory {router: VueRouter, base: "", current: {…}, pending: null, ready: true, …}
    matcher:{match: ƒ, addRoutes: ƒ}
    mode:"hash"
    options:{routes: Array(2)}
    resolveHooks:[]
    currentRoute:(...)
    __proto__:Object

点击打开__proto__(父级中声明的方法,在子级中都可以使用):

        addRoutes:ƒ addRoutes(routes)
        afterEach:ƒ afterEach(fn)
        back:ƒ back()
        beforeEach:ƒ beforeEach(fn)
        beforeResolve:ƒ beforeResolve(fn)
        forward:ƒ forward()
        getMatchedComponents:ƒ getMatchedComponents(to)
        go:ƒ go(n)
        init:ƒ init(app /* Vue component instance */)
        match:ƒ match( raw, current, redirectedFrom )
        onError:ƒ onError(errorCb)
        onReady:ƒ onReady(cb, errorCb)
        push:ƒ push(location, onComplete, onAbort)
        replace:ƒ replace(location, onComplete, onAbort)
        resolve:ƒ resolve( to, current, append )
        constructor:ƒ VueRouter(options)
        currentRoute:(...)
        get currentRoute:ƒ ()
        __proto__:Object

console.log(this.$route)     打印$route的结果:


  1. fullPath:"/marked"
  2. hash:""
  3. matched:[{…}]
  4. meta:{}
  5. name:"marked"
  6. params:
    1. __proto__:Object
  7. path:"/marked"
  8. query:{}
  9. __proto__:
    1. constructor:ƒ Object()
    2. hasOwnProperty:ƒ hasOwnProperty()
    3. isPrototypeOf:ƒ isPrototypeOf()
    4. propertyIsEnumerable:ƒ propertyIsEnumerable()
    5. toLocaleString:ƒ toLocaleString()
    6. toString:ƒ toString()
    7. valueOf:ƒ valueOf()
 

备注:$router中,push方法常用,在$route中,path(获取当前访问的路径)和fullpath(获取当前访问的全路径)方法常用

 

配置好了路由,接下来就该在HTML中使用了

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

备注:路由出口 --> 路由匹配到的组件将渲染在这里 --> <router-view></router-view>  这是路由的出口

使用 router-link 组件来导航. -->通过传入 `to` 属性指定链接. --><router-link> 默认会被渲染成一个 `<a>` 标签

注意:router-link和router-view也可以放置在不同的子组件中

  <router-view></router-view>    可以简写成   <router-view/>

动态路由匹配:

  一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:

模式匹配路径$route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: 123 }

除了 $route.params 外,$route 对象还提供了其它有用的信息,例如,$route.query (如果 URL 中有查询参数)、$route.hash

编程式的导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

router.push(location, onComplete?, onAbort?)

注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。所以通过这个方法我们可以实现重定向的效果,

比如:登录后跳转到首页,可以把首页的路径push到$router中即可

声明式编程式
<router-link :to="..."> router.push(...)

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})


  在使用动态路由或者编程式的路由时,会有这样一个问题,路由切换后,页面不切换,解决方法:
使用watch监听路由的变化,并做数据的覆盖处理
<template>
    //  两种方式触发切换
  <!--方式一:通过点击事件的切换-->
<div v-for="(item,index) in theshow.recommend_courses" @click="toaimcourse(item)"><a href="javascript:vild(0);">{{item.title}}</a></div> <!--方式二:通过动态路由的切换--> <router-link v-for="(item,index) in theshow.recommend_courses" :to="{ name: 'coursedetail', params: { id:item.id }}">{{item.title}}</router-link> </template> <script> export default { name: "vcoursedetail", data(){ return { showdetail:this.$store.state.allCourseDetail, theshow:'', currcourse:'', courseall:this.$store.state.allCourse, descurl:'', charperurl:'' } }, created(){ this.courseshowdetail(this.$route.params.id); this.getcurrentcourse(this.$route.params.id); }, methods:{ courseshowdetail(nid){ for (var i=0;i<this.showdetail.length;i++){ if (this.showdetail[i].course.id === nid){ this.theshow = this.showdetail[i]; return this.showdetail[i] } } }, getcurrentcourse(nid){ for (var i=0;i<this.courseall.length;i++){ if (this.courseall[i].id === nid){ this.currcourse = this.courseall[i].title; this.descurl = "/course/coursedetail/"+nid; this.charperurl = '/course/coursedetail/'+nid+'/charper'; console.log(this.descurl,'文章摘要的url'); return this.courseall[i] } } }, toaimcourse(item){ this.$router.push({ name: 'coursedetail', params: { id:item.id }}) } }, computed:{ }, watch:{ "$route"(to,from){ this.courseshowdetail(to.params.id);   this.getcurrentcourse(to.params.id); } } } </script>

 我们也可以做一个全局的路由操作,比如:在每个组件加载或者路由切换时,判断有没有登录

详情参考:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

拦截过滤认证

单个组件:

  可以在mounted方法中做拦截,通过判断全局变量中的token值,来判断有无登录。

多个组件:可以在全局做拦截

# 在main.js中配置

router.beforeEach(function (to,from,next) {
    //  meta 用于设置一个标识   所以必须在需要验证是否登录的组件中加一个meta参数  meta:{requireAuth:true}
    if (to.meta.requireAuth){
        //  表示此时路径是要判断是否登录的
        if (store.state.token){
            next()
        }else{
            // query  用于给这个重定向路由设置一个参数  用于在登录成功后重定向的路径
            //  设置此参数后需要在登录成功后做一个判断  this.$route.query.backUrl  获取设置的参数
            //  有值,表示是需要跳转回的,然后通过重定向将取的值,定位即可
            next({path:'/login',query:{backUrl:to.fullPath}})
        }
    }else{
        next()
    }
});

  

bootstrap的使用

在项目中,使用bootstrap时,先在package.json中查看开发环境依赖:

  "dependencies": {
    "bootstrap": "^3.3.7",
    "marked": "^0.4.0",
    "vue": "^2.5.16",
    "vue-router": "^3.0.1"
  },

  如果没有,先在当前项目中    npm install xxx

  配置好依赖后,再在需要的地方导入:   导入时,对于node_modules文件下的文件,直接导入即可。比如:import 'bootstrap/dist/css/bootstrap.min.css'     在vue-cli中,已经配置了路径,所以直接导入即可。

  备注:使用vue-router时,路由的切换会在路径前默认加一个#/,显得url很不好看,所以,可以在实例router对象时加一个mode:"history"

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

在使用a标签时,会有一个默认的跳转事件,在vue中,我们可以在相应的事件后加一个.native用来阻止原生的默认事件

  @click.native = "xxxx"

参考Vue提供的生命周期图示

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

Vue 实例生命周期

  在vue的实例的生命周期中,vue为我们提供了八个方法:

  beforeCreate(在创建之前)、created(创建时的初始化操作,创键的是虚拟DOM)、beforeMount、mounted(挂载,将虚拟DOM转化为真实DOM)、beforeUpdate、updated、beforeDestroy、destroyed(销毁)

  我们常用的是 created和mounted这两个方法,其中created方法适用于页面的初始化操作,mounted适用于发送ajax请求数据的操作。

比如:切换路由,页面样式在在此刷新时会出错,可以使用created方法进行一些初始化操作

created(){
            for (var i=0;i<this.routes.length;i++){
                if (this.routes[i].src === this.$route.path){
                    this.current=i;
                    return;
                }

            }
        },

vue-cli中2x版本和3x版本修改端口的方法:

在2x版本中:

 在3x版本中:

 在3x版本中,vue-cli不推荐我们直接在模块中修改配置

推荐这样:在当前项目的目录下直接创建一个js文件   ,文件名必须是    vue.config.js  的形式

在这个js文件中写入:

module.exports = {
devServer: { open: process.platform
=== 'darwin', host: '0.0.0.0', port: 8088 , https: false, hotOnly: false, proxy: null, // 设置代理 before: app => {} } }

 修改完成后重启项目即可。

使用vue-cli打包文件

生产环境中,我们都会讲项目中的文件打包压缩再上线,vue-cli中提供了一种快捷的打包方式。

在我们项目的根目录下运行   npm  run  build     就会将项目打包,打包后会在项目中多处一个文件夹dist,打开这个dist文件夹

备注:在项目中替换文件时,最好是先将原文件删除,在拖进去,不要直接替换,放置文件合并

在打包时,一定要配置压缩文件中的路径参数。比如:前缀加/static/

vue中的全家桶:vue、vue-router、vuex构成了vue的全家桶,vue是MVVM的架构,vuex--->M     vue--->V     vue-router--->VM

vue全家桶之vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

补充:在vue中专门用来发送ajax请求的是axios,详细用法参考:https://www.kancloud.cn/yunye/axios/234845

我们可以在全局的main.js或者store.js中定义一个axios    ,将这个axios挂到vue的实例对象中,这样,在vue的子对象中都可以通过this.$axios调用到axios对象。使用axios时,可以通过返回的参数response.data取得返回的数据

import axios from 'axios'
import Vue from 'vue'

Vue.prototype.axios = axios

特别注意:使用jQuery的$.ajax发送post请求发送数据时,内部会自动转化为json字符串的形式发送到后端,而使用vue中的axios时,则不行,axios   post提交数据时,发送的是普通的值,所有在使用axios发送数据时,如果后端需要json形式的字符串,则需要借助一个模块  qs (npm install qs) 转化或者,JSON.stringfity  

  还有一个值得注意的地方,在vue的中,我们可以通过this拿到vue的实例对象,但是在axios中由于作用域的原因则不行,console.log(this)得到的是一个undefined,所以我们要在axios的外面声明一个变量接收这个this   var  _this = this


vue中的mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

 使用vue-cli时,会在src文件夹下默认创建views、components的两个文件夹,views中存放每一个vue-router(路由)对应的视图,components中存放父子嵌套的组件。

获取v-html指令对应的文本值

  使用v-html指令时,如果我们要获取渲染的文本内容,可以给当前标签绑定一个属性ref="变量名",然后在vue的实例中可以通过this.$refs.变量名取得这个标签,在通过DOM方法.innerText取得内容,this.$refs是一个对象

<div id="show" v-html="currentmsg" ref="mark">

 // 这个div的文本内容为:
var content = this.$refs.mark.innerText;

备注:不要滥用ref,对性能有损耗,多个标签时,可以使用js方法或者jQuery方法获取文本值   $("show").text()

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

备注:mutation是同步的,action是异步的,   action是用来提交的

用法:

mutation的用法:接收一个state参数作为第一个参数,有其他参数可以直接跟在后面,在mutation的方法中可以直接操作state中的数据,有多个参数时,最好可以将其余的参数作为一个对象,作为方法的第二个参数传值。

 在vue的视图中可以直接this.$store.commit("方法名"),唤醒这个方法的执行

action的用法:接收一个context参数作为第一个参数,同样的,后可以跟其他参数,多个参数时,合并为一个object对象。通过context.commit("mutation方法名") 提交, 可以唤醒mutation中的方法

  在vue的视图中可以通过this.$store.dispatch('action方法名'),触发action中的对应方法执行

mutation和action的关系图如下:

过滤器(格式化)

1.价格后面加上符号‘元’。

2.价格后面的单位也要动态的传值。(如:元、¥、$)

代码:

复制代码
<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>过滤器</title>
    <script src="bli/vue.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="price">
    <!-- {{ price | currency }} -->
    {{ price | currency('美元') }}
</div>
</body>
<script src="js/14.main.js"></script>
</html>
复制代码
复制代码
// 过滤器
Vue.filter('currency',function(data,unit){
    data = data || 0;  // data有值就等于data,没值就为0.
    unit = unit || '元';  // unit有值就等于unit,没值就为'元'.
    return data + unit;
    // return data + '元';
});

new Vue({
    el:'#app',
    data:{
        price:10,
    },
});
复制代码

3.毫米与米的转换。

4.毫米与米的转换,保留两位小数。

自定义指令-基础配置

1.自定义指令

2.给只为true的元素定位(固定定位)

3.加一个按钮,切换是否定位。

默认都是没有定住的。点击之后定住,再点击之后就是取消定住。

默认、取消定住

定住

4.可以给很多按钮就加上。

默认、取消定位

定位

自定义指令-配置传参及修饰符

以上例子只能定位到左上角,不够灵活。位置应该动态传参。

1.定位到右下角:

打印 var position = binding.modifiers;

console.log('position',position)  // position {bottom: true, right: true}

运行结果:已定位到右下角

2.定位到左下角,只要改一个值即可。

3.让一些卡片样式有所不同,突出。

获取该值(:true),设置样式。

 

混合 mixins

1.点击切换显示隐藏。

默认不显示div.

点击后显示div,再次点击有隐藏div.

2.鼠标移入、移出切换显示隐藏。

默认、移出

移入:

3.点击显示的div应该有个可以关闭的按钮。

注意:这两个组件有好多重复的代码!

点击后隐藏div

混合 mixins(相同的代表放在一起)

功能是一样的。注意:自己写的会覆盖mixins的。

插槽 slots

1.定义一个样式

2.内容都是相同的。动态传参(插槽)

3.如果头部、底部都要动态传参呢???定义name!!!

4.指定默认值。

在Vue的项目中使用了Vue-Router,当某个路由有子级路由时,如下写法:

Default
export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home,
      children:[
        {
          path:'/',
          name: 'console',
          component: Console,
        }
      ]
    }
  ]
})
如果写法是如上的写法,就会报出如下警告:
[vue-router] Named Route 'home' has a default child route. When navigating to this named route (:to="{name: 'home'"), the default child route will not be rendered. Remove the name from this route and use the name of the default child route for named links instead.

解决办法

因为当某个路由有子级路由的时候,这时候父级路由需要一个默认的路由,所以父级路由不能定义name属性,SO解决办法是:即去除父级的name属性即可。

原文地址:https://www.cnblogs.com/zhaopanpan/p/9236538.html