Vue路由器将道具传递给动态加载的孩子

Posted

技术标签:

【中文标题】Vue路由器将道具传递给动态加载的孩子【英文标题】:Vue Router passing props to dynamically loaded children 【发布时间】:2018-12-10 23:07:43 【问题描述】:

我正在学习 Vue atm,但我无法通过 Vue 路由在子组件和父组件之间传递道具。我有一个 Layout 组件,它有一个包装器 DIV,如下所示:

<template>
    <div class="container" v-bind:class="cssClass">
      <router-view></router-view>
    </div>
</template>

<script>
export default 
  name: 'Layout',
  props: ['cssClass']

</script>

我已经在我的基础 App JS 中定义了路由,如下所示。所以我对第一次加载的看法是“容器动画”类,世界上一切都很好。

const router = new VueRouter(
    routes: [
       path: '/', component: Layout, props:  cssClass: 'container-animated' ,
        children: [
           path: '', component: Homepage ,
           path: '/hello-world', component: HelloWorldPage, props:  cssClass: ''  
        ]
     ,
    ]
);

但是,一旦我点击 /hello-world 路线,我想将一个空的 cssClass 道具传递给 Layout,(HelloWorldPage 当前嵌套在其中) - 我该怎么做?道具甚至是实现这一目标的机制吗?

【问题讨论】:

为什么要传一个空的prop?这个道具将来应该改变吗?孩子应该用cssClass 做什么?父组件是否应该通知哪个组件处于活动状态并更改相应子组件的cssClass 好吧,在这种情况下,我想删除父级中的 css 修饰符。在另一条路线中,我可能想要添加不同的修饰符,具体取决于通往其他路线的路线。是的,您关于父母知道子组件道具的最后声明。 【参考方案1】:

我想通了,这是否是我的问题的最佳解决方案是任何人的猜测。

在 Vue 路由器上传递时,父级似乎不会自动拾取子级道具。因此,一旦组件被动态构建/注入,它们每个都会调用我的自定义 childinit 事件,该事件会发送回父级(布局)中定义的路由器视图。我将父级中的局部变量设置为发出的子级的值,然后将类绑定到它。

const router = new VueRouter(
    routes: [
      
        path: '/',
        component: Layout,
        children: [
          
            path: '',
            component: Homepage,
            props:  cssClass: 'home' ,
          ,
          
              path: '/helloworld',
              component: HelloWorldPage,
              props:  cssClass: 'helloworld' 
          
        ]
      
    ]
);

我的布局组件:

<template>
    <div class="container" v-bind:class="className">
      <router-view v-on:childinit="onChildInit"></router-view>
    </div>
</template>

<script>
export default 
  name: 'Layout',
  props: ['cssClass'],
  data() 
    return 
      className : ''
    
  ,
  methods: 
    onChildInit( value )
      this.className = value;
    
  

</script>

我的主页组件:

export default 
  name: 'Homepage',
  props: ['cssClass'],
  created() 
    this.$emit('childinit', this.cssClass);
  

HelloWorld 组件也会发出,可能不需要复制创建的方法;可能会尝试看看您是否可以扩展一个基本组件,该组件将始终在两个组件的 init 上发出。

【讨论】:

【参考方案2】:

我知道这是旧的,但你不必担心在组件中创建一个方法来发出你的值。这是我的解决方案。

你的布局:

<template>
<div class="container" v-bind:class="className">
    <router-view></router-view>
</div>
</template>
<script>
export default 
  name: 'Layout',
  props: ['cssClass'],
  data() 
    return 
      className : ''
    
  ,
  // set class initially
  created () 
    this.setClassName(this.$route)
  ,
  // and when route changes
  watch: 
    $route: function (val) 
        this.setClassName(val)
    
  ,
  methods: 
    setClassName( Route )
      // each matched route is checked for cssClass from top to bottom, so you can override
      Route.matched.forEach((route) => 
        if (route.props.default && route.props.default instanceof Object && 'cssClass' in route.props.default) 
          this.className = route.props.default.cssClass
        
      )
    

  

</script>

这样,所有内容都保留在 Layout 组件上。这也不是理想的解决方案。我可以想象使用router.afterEach() 并将值设置为 Vuex 存储。

【讨论】:

【参考方案3】:

让我解释一下 vue 的工作原理:

你得到了你的父组件。布局.vue

<template>
  <div id="app" class="container-fluid">
    <router-view/>
  </div>
</template>
<style>
 .container-fluid 
background-color:blue; //as defined in the parent, everything inside #app will inherit this class

</style>

现在,您的 vue 路由器必须如下所示:


    path: '/',
    name: 'Layout',
    component: Layout,
    children: [
         path: '', component: Create, name: 'Create' ,
    ]

既然你已经定义了 Layout.vue 里面会继承 .container-fluid 里面的所有东西,那么组件 Create 会继承它的父级(Layout)中定义的类

希望这行得通。

问候,

【讨论】:

我不想让他们继承,我想在路由改变的时候改变他们。

以上是关于Vue路由器将道具传递给动态加载的孩子的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 <router-view> 传递动态道具

Vue - 将方法作为道具传递给孩子

Vue 2 将道具传递给孩子 [旧:“调用孩子的方法”]

将道具动态传递给VueJS中的动态组件

将数据从孩子传递给父母,而无需加载事件,这可能在 vue 世界上吗?

页面未呈现;在 react-router-dom 中使用受保护的路由将道具传递给孩子时