2017-09-26 73 views
1

我使用vuetify.js并努力创造可以是跨应用可重用的组件。虽然它的工作非常好,但我不确定它是否是正确的方法。试图绑定道具V模型

我创建具有相同的菜单选项,所有的时间抽屉式导航组件,但它可以从UI元素被打开。

以下是代码。

// NavigationBar.vue

<template> 
    <v-navigation-drawer 
    temporary 
    v-model="drawerFlag" 
    light 
    overflow 
    fixed 
    > 
    <v-list> 
     <v-list-tile> 
     <v-list-tile-action @click.stop="toggleDrawer()"> 
      <v-btn icon> 
      <v-icon>close</v-icon> 
      </v-btn> 
     </v-list-tile-action> 
     </v-list-tile> 
    </v-list> 
    <v-list class="pt-0"> 
     <template v-for="item in items"> 
     <v-list-tile :key="item.title" :to="item.link"> 
      <v-list-tile-action> 
      <v-icon>{{ item.icon }}</v-icon> 
      </v-list-tile-action> 
      <v-list-tile-content> 
      <v-list-tile-title>{{ item.title }}</v-list-tile-title> 
      </v-list-tile-content> 
     </v-list-tile> 
     <v-divider></v-divider> 
     </template> 
    </v-list> 
    </v-navigation-drawer> 
</template> 

<script> 
    export default { 
    props: ['drawer'], 
    data() { 
     return { 
     items: [ 
      { title: 'Home', icon: 'home', link: '/home'}, 
      { title: 'History', icon: 'history', link: '/history' }, 
      { title: 'Wallet', icon: 'account_balance_wallet', link: '/wallet' }, 
      { title: 'My Profile', icon: 'person', link: '/profile' }, 
      { title: 'Settings', icon: 'settings', link: '/settings' }, 
      { title: 'About', icon: 'error', link: '/about' }, 
      { title: 'Logout', icon: 'power_settings_new', link: '/logout' }, 
     ] 
     }; 
    }, 
    computed: { 
     drawerFlag: { 
     get: function() { 
      return this.drawer 
     }, 
     set: function() { 

     } 
     } 
    }, 
    methods: { 
     toggleDrawer: function() { 
     this.$emit('emitToggleDrawer'); 
     } 
    } 
    } 
</script> 

//Home.vue

<template> 
    <div class="full-screen"> 
    <navigation-bar :drawer="drawer" v-on:emitToggleDrawer="toggleDrawer"></navigation-bar> 
    <v-btn icon class="mt-3 fixed-position" @click.stop="drawer = !drawer"> 
     <v-icon>menu</v-icon> 
    </v-btn> 
    </div> 
</template> 

<script> 
    export default { 
    name: 'home', 
    data() { 
     return { 
     drawer: null 
     }; 
    }, 

    computed: { 
     user() { 
     return this.$store.getters.user; 
     } 

    }, 

    methods: { 
     toggleDrawer: function() { 
     this.drawer = !this.drawer; 
     } 
    } 
    }; 
</script> 

在上面的代码..

在父组件,我有按钮打开导航抽屉并且导航抽屉的状态保持在称为“抽屉”的父组件中。然后,我将“抽屉”作为子组件传递给一个子组件,并将一个从子组件触发事件的方法传递给名为“emitToggleDrawer”的父组件。

在子组件中,我使用vuetify.js导航抽屉这需要V型=“drawerFlag”,其中drawerFlag是计算属性。当我试图使用v-model =“抽屉”,即绑定到道具时,我得到一个错误。然后,我们可以通过单击导航抽屉内的元素来关闭导航抽屉。为了达到这个目的,我调用了一个组件的方法,它随后发出一个由父组件监听的事件。

+0

为什么您将'抽屉'重新定义为'drawerFlag',因为它已经在Home.vue数据()中注册过,并且您将其作为组件提供给它,您不能直接作为'抽屉'来访问吗? –

+0

问题出在子组件上,当我们尝试使用v-model =“drawer”时,它给出了一个错误,说“避免直接改变一个道具,因为只要父组件重新渲染,值就会被覆盖,而是使用数据或基于道具值的计算属性。正被突变的道具:“抽屉”“。 – Arpit

+0

所以另一种方法是在NavigationBar.vue中可以在data()中定义drawerFlag也是rt? –

回答

1

我解决了类似的问题,像下面。

  • 只需使用drawer,而不是使用drawerdrawerFlag
  • 而不必子组件上额外的按钮
  • 没有从孩子发光event于母公司
  • 在子组件使用watch

首页.Vue

<template> 
    <div class="full-screen"> 
    <navigation-bar :drawer="drawer"></navigation-bar> 
    <v-btn icon class="mt-3 fixed-position" @click.stop="drawer = !drawer"> 
     <v-icon>menu</v-icon> 
    </v-btn> 
    </div> 
</template> 

<script> 
    import NavigationBar from '@/components/NavigationBar'; 
    export default { 
    name: 'home', 
    data() { 
     return { 
     drawer: true 
     }; 
    }, 
    components: { 
     NavigationBar 
    } 
    } 
</script> 

NavigationBar.vue

<template> 
    <v-navigation-drawer 
    temporary 
    v-model="drawer" 
    light 
    overflow 
    fixed 
    > 
    <v-list class="pt-0"> 
     <template v-for="item in items"> 
     <v-list-tile :key="item.title" :to="item.link"> 
      <v-list-tile-action> 
      <v-icon>{{ item.icon }}</v-icon> 
      </v-list-tile-action> 
      <v-list-tile-content> 
      <v-list-tile-title>{{ item.title }}</v-list-tile-title> 
      </v-list-tile-content> 
     </v-list-tile> 
     <v-divider></v-divider> 
     </template> 
    </v-list> 
    </v-navigation-drawer> 
</template> 

<script> 
    export default { 
    props: ['drawer'], 
    data() { 
     return { 
     items: [ 
      { title: 'Home', icon: 'home', link: '/home'}, 
      { title: 'History', icon: 'history', link: '/history' }, 
      { title: 'Wallet', icon: 'account_balance_wallet', link: '/wallet' }, 
      { title: 'My Profile', icon: 'person', link: '/profile' }, 
      { title: 'Settings', icon: 'settings', link: '/settings' }, 
      { title: 'About', icon: 'error', link: '/about' }, 
      { title: 'Logout', icon: 'power_settings_new', link: '/logout' }, 
     ] 
     }; 
    }, 
    watch: { 
     drawer (value) { 
      return value; 
     } 
    } 
    } 
</script> 
+0

您提供的解决方案不是正确的方法。你不应该直接修改道具。通过使用v-model =“抽屉”,你是绑定道具。在开发模式下运行vue.js时,您将在控制台中收到警告。 – Arpit

1

我解决了它这样的:

App.vue

<my-drawer ref="drawer"></my-drawer> 
<my-header @toggle-drawer="$refs.drawer.drawer = !$refs.drawer.drawer"></my-header> 

MyDrawer.vue

<v-navigation-drawer v-model="drawer"> 
... 
data() { 
    drawer: true 
} 

MyHeader.vue

<v-toolbar-side-icon @click.stop="$emit('toggle-drawer')"></v-toolbar-side-icon> 


在我看来,我们需要自定义抽屉组件 v-model="drawer"因此它可以正确地在所有的屏幕尺寸工作。

因此,我们需要以某种方式从父母(或兄弟姐妹)更改它的值,这就是为什么我在抽屉组件上使用ref的原因。 也许而不是改变$refs.drawer.drawer数据,我可以改为调用抽屉功能。我不确定什么是更好的方法。但这是在所有屏幕尺寸上为我工作的唯一简单解决方案。

所以在我的情况下,我只是从头部改变抽屉状态,但我认为你可以根据你的需要使用它并适合它。