结合Vue路由器使用Vue 2中的可重用组件

Posted

技术标签:

【中文标题】结合Vue路由器使用Vue 2中的可重用组件【英文标题】:Using reusable components in Vue 2 in comination with vue router 【发布时间】:2017-04-26 08:53:01 【问题描述】:

当我尝试使用单击事件定位嵌套路由器视图中的子组件时,我似乎做错了。

目前情况: 我有一个组件一和组件二。两者都有一个名为对话框的子组件。

组件一和二正在通过父组件仪表板中的路由器视图加载。每个视图都有一个按钮来显示其子组件“模态”。

该按钮似乎在页面加载时加载的视图上工作正常。但是一旦我切换路由,showModal 函数就不知道对话元素从哪个视图定位。

我认为组件会在切换路线时被破坏和重建,但显然不是。

这是我的代码,希望有人能够提供帮助:

应用

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

Vue.use(VueRouter)
/**
 * First we will load all of this project's javascript dependencies which
 * include Vue and Vue Resource. This gives a great starting point for
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap')

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the body of the page. From here, you may begin adding components to
 * the application, or feel free to tweak this setup for your needs.
 */

Vue.component('vuetest', require('./components/vuetest.vue'))

const Dashboard = require('./components/dashboard.vue')
const FirstRoute = require('./components/firstroute.vue')
const Second = require('./components/secondroute.vue')

const routes = [
    
        path: '/dashboard',
        component: Dashboard,
        children: [
            
                path: 'firstview',
                name: 'firstview',
                canReuse: false,
                component: FirstRoute
            ,
            
                path: 'secondview',
                name: 'secondview',
                canReuse: false,
                component: Second
            
        ]
    
]

const router = new VueRouter(
    routes // short for routes: routes
)

window.EventHub = new Vue()

const app = new Vue(
    el: '#app',
    router
);

Vuetest

<template>
    <div>
        <h1>Vue Test</h1>
        <router-view></router-view>
    </div>
</template>

<script>
    export default 
        created() 

        ,
        mounted() 
            console.log('Component ready.')
        
    
</script>

仪表板路线

<template>
    <div>
        <h1>Dashboard</h1>
        <navigation></navigation>
        <router-view></router-view>
    </div>
</template>
<script>
    Vue.component('navigation', require('./navigation.vue'))
</script>

导航

<template>
    <div>
        <router-link :to=" name: 'firstview' ">first</router-link>
        <router-link :to=" name: 'secondview' ">second</router-link>
    </div>
</template>

第一条路线

<template>
    <div class="firstroute">
        <h1>First Route</h1>
        <button class="showmodal" v-on:click="showModal">Showmodal</button>
        <modal></modal>
    </div>
</template>
<script>
    export default 
        methods: 
            showModal: function () 
                EventHub.$emit('showModal')
            
        
    
    Vue.component('modal', require('./modal.vue'));
</script>

第二条路线

<template>
    <div class="secondroute">
        <h1>Second Route</h1>
        <button class="showmodal" v-on:click="showModal">Showmodal</button>
        <modal></modal>
    </div>
</template>
<script>
    export default 
        methods: 
            showModal: function () 
                EventHub.$emit('showModal')
            
        
    
    Vue.component('modal', require('./modal.vue'));
</script>

模态

<template>
    <div class="dialog hidden">
        Dialog
    </div>
</template>
<style>
    .hidden 
        display: none;
    
</style>
<script>
    export default
        created() 
            EventHub.$on('showModal', this.showModal);
        ,
        methods: 
            showModal: function() 
                document.querySelector('.dialog').classList.toggle('hidden');
            
        
    
</script>

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

小建议

':class' 指令而不是原生代码:

document.querySelector('.dialog').classList.toggle('hidden');

组件:

import Modal from './modal' 

export default 
  ...
  components:
    Modal
  
  ...

而不是

Vue.component('modal', require('./modal.vue'));

.. Vuex 也是这个案例的一个好点

补充:

https://github.com/vuejs/vue-devtools

https://jsfiddle.net/uLaj738k/2/

【讨论】:

感谢您的回答亚历山大。非常感谢您的帮助。我已根据您的建议进行了重构。我可以问更多关于为什么你认为 Vuex 会是这里的答案的信息吗?目前,它认为状态管理不适合用来跟踪应该在哪条路线上发生动作。我不想在路线之间移动任何数据,我只是想得到一个按钮显示/隐藏当前活动路线中的元素。【参考方案2】:

事实证明,问题出在我调用 querySelector 方法的那一刻。

.dialog 元素分配给mounted() 中的常量解决了我的问题。

【讨论】:

以上是关于结合Vue路由器使用Vue 2中的可重用组件的主要内容,如果未能解决你的问题,请参考以下文章

Vue @click 计数器并为可重用组件更新背景 2 分钟

Vue JS 路由器组件 - 在路由之间导航后无法重用使用 webpack 导入的 JS 文件

如何在 laravel nova 中创建可重用的 vue 组件?

使用 Vue.js 创建可重用的按钮组件

无法使用 Vue.js 在可重用组件之间添加自定义内容

Vue 可重用组件和 Nuxt 应用程序包大小