点击后渲染一个新的 Vue 组件

Posted

技术标签:

【中文标题】点击后渲染一个新的 Vue 组件【英文标题】:Rendering a new Vue component after click 【发布时间】:2019-03-20 01:00:39 【问题描述】:

我正在使用Vue-CLI。我有一个名为 viewGenres.vue 的 Vue 组件。该组件包含 Vuetify 表,它显示了 Vue 商店中所有当前的 genres。我正在尝试为每种类型添加一个新选项,即“编辑”。

我的目标是表格中的每一行都有一个edit 按钮。单击按钮后,应呈现一个名为 editGenre.vue 的新组件。

此组件应包含一个已填写的表格,其中包含特定类型的所有现有详细信息。 我有几个问题:

1) 单击edit 按钮后,浏览器上会出现以下异常:

ReferenceError: Vue 没有在 VueComponent.editGenre 中定义

2) 为了让我从数据库中加载正确的属性,我需要定义 editGenre 组件的“ID”属性。有没有人对这样做的最佳方法有任何建议?

这是 viewGenres.vue:(方法 editGenre 负责渲染新组件)。

<template>
    <div class="root" ref="container">
        <h2>Genres Info</h2>
        <br>
        <v-data-table
            :headers="headers"
            :items="genres"
            hide-actions
            class="elevation-1">
            <template slot="items" slot-scope="props">
                <td class="text-xs-left"> props.item.id </td>
                <td class="text-xs-left"> props.item.name </td>
                <td class="text-xs-left"> props.item.desc </td>
                <td class="text-xs-left"> props.item.artists </td>
            <td class="text-xs-left"><v-btn flat @click="editGenre(props.item.id)">EDIT</v-btn></td>
                <td class="text-xs-left"><v-btn flat @click="deleteGenre(props.item.id)">Delete</v-btn></td>
            </template>
        </v-data-table> 
    </div>
</template>
<script>
import editGenre from '@/components/administratorView/Genres/editGenre.vue'
const firebase = require('../../../firebaseConfig.js')

export default 
    data: function()
        return
            headers: [
             text: 'ID', value: 'id',
             text: 'Name', value: 'name',
             text: 'Description', value: 'desc',
             text: 'Artists', value: 'artists',
       text: 'Edit Genre',
             text: 'Delete From DB'
            ]
        
    ,
    computed: 
    genres: function()
      return this.$store.state.genre.genres
    
    ,
  components: 
    editGenre
  ,
    methods: 
    editGenre: function(id)
      var ComponentClass = Vue.extend(editGenre)
      var instance = new ComponentClass()
      instance.$mount()
      this.$refs.container.appendChild(instance.$el)
    ,
        deleteGenre: function(id)
            console.log("Trying to delete " +id)
            firebase.firestore.collection("genres").doc(id).delete().then(()=>
            this.$store.dispatch('genre/getGenresFromDB')
                alert("Deleted Document Successfully")
            ).catch(function(error)
                alert(error)
            )
        
    ,
  mounted()
    this.$store.dispatch('genre/getGenresFromDB')
  

</script>
<style scoped>
</style>

这是editGenre.vue:

<template>
    <v-dialog v-model="editGenre" persistent max->
        <v-card>
            <v-card-title>
                <h2>Edit Genre genre.name</h2>
            </v-card-title>
            <v-card-text>
                <v-text-field
                        v-model="name"
                        label="Name"
                        :error-messages="nameErrors"
                        @touch="$v.name.$touch()"
                        @blur="$v.name.$touch()"
                />
                <v-textarea
                        v-model="desc"
                        label="Description"
                        box
                />
                <v-combobox
                    v-model="artists"
                    label="Artists"
                    :items="artistNames"
                    :error-messages="artistsErrors"
                    @touch="$v.artists.$touch()"
                    @blur="$v.artists.$touch()"
                    multiple>
                </v-combobox>
                <v-btn
                        color="primary"
                        @click="submit">
                        Submit
                </v-btn>
                <v-btn
                    color="primary"
                    @click="close">
                    Close
                </v-btn>
            </v-card-text>          
        </v-card>   
    </v-dialog>
</template>
<script>
import  required  from 'vuelidate/lib/validators'
const firebase = require('../../../firebaseConfig')

export default
    data: function()
        return
            name: '',
            desc: '',
            artists: []
        
    ,
    props: 
        id: String
    ,
    mounted: function()
        let docRef = firebase.firestore.collection("genres").doc(this.id)
        docRef.get().then(function(doc)
            if(doc.exists)
                this.name = doc.data().name
                this.desc = doc.data().desc
                this.artists = doc.data().artists
            
            else
                console.error("Doc Doesn't Exist!")
            
        ).catch(function(error)
            console.error(error)
        )
    

</script>
<style scoped>
</style>

谢谢! 汤姆

【问题讨论】:

【参考方案1】:

您错过了在viewGenres.vue 组件中导入Vue,因此添加如下:

   ....
   <script>
      import Vue from 'vue'
      import editGenre from '@/components/administratorView/Genres/editGenre.vue'
       const firebase = require('../../../firebaseConfig.js')
      ....

你可以通过这种方式传递道具:

      var ComponentClass = Vue.extend(
              props:
                id:type:String, default ()  return id
               ,editGenre)

并删除它:

     props: 
       id: String
    

尤文

不建议使用 new 手动构造子组件。这是势在必行且难以维护的。您可能希望使您的子组件数据驱动,使用和 v-for 来动态呈现子组件,而不是自己构建它们。

【讨论】:

谢谢它解决了我的第一个问题!你对我的第二个问题有什么建议吗? @TomHarpaz 不客气,我编辑了我的答案,希望对你有所帮助

以上是关于点击后渲染一个新的 Vue 组件的主要内容,如果未能解决你的问题,请参考以下文章

vue3动态组件为啥只能点击切换一次组件

渲染后的Vue组件事件

解决vue开发时子组件数据和组件渲染的异步问题

如何在vue js中从组件渲染组件

为啥 VueJS 组件在导入/组件调用后不渲染标签?

为啥我的 vue 组件不重新渲染?