1

我正在尝试根据我的需要通过实施 axios 来使用我的 api 来调整 vuetify 网站本身的示例数据表。GET AND DELETE方法运行良好,但是我对 POST AND PUT 方法很困惑,使用 2 个模型作为客户端,并且与流派的关系遵循部分代码:

<template>
    <v-data-table
      :headers="headers"
      :items="clients"
      sort-by="firstName"
      class="elevation-2"
    >
      <template v-slot:top>
        <v-toolbar flat color="white">
          <v-icon medium>mdi-account-supervisor</v-icon>
            <v-toolbar-title> Clients</v-toolbar-title>
          <v-divider
            class="mx-4"
            inset
            vertical
          ></v-divider>
          <v-spacer></v-spacer>
          <v-dialog v-model="dialog" max-width="600px">
            <template v-slot:activator="{ on }">
                <v-btn 
                color="blue" 
                dark class="mt-6 mb-4" 
                v-on="on"
                rounded
                ><v-icon medium>mdi-plus</v-icon>Add new</v-btn>
            </template>
            <v-card>
              <v-card-title>
                <span class="headline">{{ formTitle }}</span>
              </v-card-title>

              <v-card-text>
                <v-container>
                  <v-form>
                    <v-row>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.firstName" label="First Name"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.lastName" label="Last Name"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.email" label="E-Mail"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.phone" label="Phone"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.mobilePhone" label="Mobile Phone"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <!-- select options-->
                        <v-select
                          label='Gender'
                          v-model='editedItem.gender.name'
                          :items='genders'
                          item-value='name'
                          item-text='name'
                        >
                        </v-select>
                      </v-col>
                    </v-row>
                  </v-form>
                </v-container>
              </v-card-text>

              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="error" rounded @click="close">Cancel</v-btn>
                <v-btn color="primary" rounded @click="save">Save</v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </v-toolbar>
      </template>
      <template v-slot:item.action="{ item }">
        <v-icon
          small
          color="green"
          class="mr-2"
          @click="editItem(item)"
        >
          mdi-pencil
        </v-icon>
        <v-icon
          small
          color="red"
          @click="deleteItem(item)"
        >
          mdi-delete
        </v-icon>

      </template>
      <template v-slot:no-data>
        <v-btn color="primary" @click="initialize">Reset</v-btn>
      </template>
    </v-data-table>
</template>

<script>
import axios from 'axios'
import Client from '../../services/clients';
import Gender from '../../services/genders';

  export default {
    data: () => ({
      dialog: false,
      headers: [
        {
          text: 'First Name',
          align: 'start',
          sortable: false,
          value: 'firstName',
        },
        { text: 'Last Name', value: 'lastName' },
        { text: 'Email', value: 'email' },
        { text: 'Phone', value: 'phone' },
        { text: 'Mobile Phone', value: 'mobilePhone' },
        { text: 'Gender', value: 'gender.name' },
        { text: 'Actions', value: 'action', sortable: false },
      ],
      clients: [],
      genders: [],
      errors: [],
      editedIndex: -1,
      editedItem: {
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        mobilePhone: '',
        gender: '',
      },
      defaultItem: {
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        mobilePhone: '',
        gender: '',
      },
    }),
    computed: {
      formTitle () {
        return this.editedIndex === -1 ? 'New Item' : 'Edit Item'
      },
    },
    watch: {
      dialog (val) {
        val || this.close()
      },
    },
    created () {
      this.initialize()
    },
    methods: {
      initialize () {
        Client.list().then(response => {
          this.clients = response.data
        }).catch(e => {
          console.log(e)
        });
        Gender.list().then(response => {
          this.genders = response.data
        }).catch(e => {
          console.log(e)
        });

      },
      editItem (item) {
        axios.put('http://192.168.26.130:3000/client/' + item.id)
          .then(response => {
            this.editedIndex = this.clients.indexOf(item)
            this.editedItem = Object.assign({}, item)
            this.editedID = this.editedItem.id
            this.dialog = true
            this.response = response
        }).catch(e => {
          console.log(e)
        });
      },

      deleteItem (item) {
        if (confirm("Do you really want to delete?")) {
          axios.delete('http://192.168.26.130:3000/client/' + item.id)
          .then(response => {
            const index = this.clients.indexOf(item)
            this.deletedItem = Object.assign({}, item)
            this.deletedID = this.deletedItem.id
            this.clients.splice(index, 1);
            this.response = response
          }).catch(e => {
          console.log(e)
        });
        }
      },

      close () {
        this.dialog = false
        setTimeout(() => {
          this.editedItem = Object.assign({}, this.defaultItem)
          this.editedIndex = -1
        }, 300)
      },

      save () {
        if (this.editedIndex > -1) {
          axios.post('http://192.168.26.130:3000/client/')
          .then(response => {
            Object.assign(this.clients[this.editedIndex], this.editedItem)
            this.response = response.data
          }).catch(e => {
          console.log(e)
        });
        } else {
            this.clients.push(this.editedItem)
        }
        this.close()
      },

    },
  }
</script>

打开模态添加项目时,只有在打开选择并修改流派时,甚至在保存之前就已经出现此错误,如图所示:

点击保存时只保存在前面,更新页面时记录消失,有人可以给我一个灯吗?

更新编辑。

经过一些更改,我认为我更接近解决方案,但我遇到了以下障碍,保存客户端项目时,性别存储为空。

图片console.log 和保存在前端但在数据库中性别为空的项目

文件 DataTable.vue:

<template>
    <v-data-table
      :headers="headers"
      :items="clients"
      sort-by="firstName"
      class="elevation-2"
    >
      <template v-slot:top>
        <v-toolbar flat color="white">
          <v-icon medium>mdi-account-supervisor</v-icon>
            <v-toolbar-title> Clients</v-toolbar-title>
          <v-divider
            class="mx-4"
            inset
            vertical
          ></v-divider>
          <v-spacer></v-spacer>
          <v-dialog v-model="dialog" max-width="600px">
            <template v-slot:activator="{ on }">
                <v-btn 
                color="blue" 
                dark class="mt-6 mb-4" 
                v-on="on"
                rounded
                ><v-icon medium>mdi-plus</v-icon>Add new</v-btn>
            </template>
            <v-card>
              <v-card-title>
                <span class="headline">{{ formTitle }}</span>
              </v-card-title>

              <v-card-text>
                <v-container>
                  <v-form>
                    <v-row>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.firstName" label="First Name"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.lastName" label="Last Name"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.email" label="E-Mail"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.phone" label="Phone"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <v-text-field v-model="editedItem.mobilePhone" label="Mobile Phone"></v-text-field>
                      </v-col>
                      <v-col cols="12" sm="6" md="12">
                        <!-- select options-->
                        <v-select
                          label='Gender'
                          v-model='editedItem.gender'
                          :items='genders'
                          item-value='name'
                          item-text='name'
                        >
                        </v-select>
                      </v-col>
                    </v-row>
                  </v-form>
                </v-container>
              </v-card-text>

              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="error" rounded @click="close">Cancel</v-btn>
                <v-btn color="primary" rounded @click="save">Save</v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </v-toolbar>
      </template>
      <template v-slot:item.action="{ item }">
        <v-icon
          small
          color="green"
          class="mr-2"
          @click="editItem(item)"
        >
          mdi-pencil
        </v-icon>
        <v-icon
          small
          color="red"
          @click="deleteItem(item)"
        >
          mdi-delete
        </v-icon>

      </template>
      <template v-slot:no-data>
        <v-btn color="primary" @click="initialize">Reset</v-btn>
      </template>
    </v-data-table>
</template>

<script>
import axios from 'axios'
import Client from '../../services/clients';
import Gender from '../../services/genders';

  export default {
    data: () => ({
      dialog: false,
      headers: [
        {
          text: 'First Name',
          align: 'start',
          sortable: false,
          value: 'firstName',
        },
        { text: 'Last Name', value: 'lastName' },
        { text: 'Email', value: 'email' },
        { text: 'Phone', value: 'phone' },
        { text: 'Mobile Phone', value: 'mobilePhone' },
        { text: 'Gender', value: 'gender.name' },
        { text: 'Actions', value: 'action', sortable: false },
      ],
      clients: [],
      genders: [],
      errors: [],
      editedIndex: -1,
      editedItem: {
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        mobilePhone: '',
        gender: '',
      },
      defaultItem: {
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        mobilePhone: '',
        gender: '',
      },
    }),
    computed: {
      formTitle () {
        return this.editedIndex === -1 ? 'New Item' : 'Edit Item'
      },
    },
    watch: {
      dialog (val) {
        val || this.close()
      },
    },
    created () {
      this.initialize()
    },
    methods: {
      initialize () {
        Client.list().then(response => {
          this.clients = response.data
        }).catch(e => {
          console.log(e)
        });
        Gender.list().then(response => {
          this.genders = response.data
        }).catch(e => {
          console.log(e)
        });

      },
      editItem (item) {
        axios.put('http://192.168.26.130:3000/client/' + item.id)
          .then(response => {
            this.editedIndex = this.clients.indexOf(item)
            this.editedItem = Object.assign({}, item)
            this.editedID = this.editedItem.id
            this.dialog = true
            this.response = response
        }).catch(error => {
          console.log(error.response)
        });
      },

      deleteItem (item) {
        if (confirm("Do you really want to delete?")) {
          axios.delete('http://192.168.26.130:3000/client/' + item.id)
            .then(response => {
              const index = this.clients.indexOf(item)
              this.deletedItem = Object.assign({}, item)
              this.deletedID = this.deletedItem.id
              this.clients.splice(index, 1);
              this.response = response
            }).catch(error => {
                console.log(error.response)
              });
        }
      },

      close () {
        this.dialog = false
        setTimeout(() => {
          this.editedItem = Object.assign({}, this.defaultItem)
          this.editedIndex = -1
        }, 300)
      },

      save () {
        if (this.editedIndex > -1) {
          Object.assign(this.clients[this.editedIndex], this.editedItem)
        } else {
            this.clients.push(this.editedItem)
            axios.post('http://192.168.26.130:3000/client/', this.editedItem)
              .then(response => {
                console.log(response)
              }).catch(error => {
              console.log(error.response)
            });

        }
        this.close()
      },

    },
  }
</script>

请有人帮助我吗?

4

1 回答 1

1

有几个问题。首先,您没有将任何数据传递给您的PUTPOST请求。它们应该看起来像:

editItem (item) {
  // YOU NEED TO PASS AN OBJECT TO THE PUT REQUEST         ▼▼HERE▼▼
  axios.put('http://192.168.26.130:3000/client/' + item.id , item)
    .then(response => {
      // handle response...
    })
    .catch(err => { console.log(error) })
},
save () {
  if (this.editedIndex > -1) {
    // YOU NEED TO PASS AN OBJECT TO THE POST REQUEST  ▼▼HERE▼▼
    axios.post('http://192.168.26.130:3000/client/', this.editedItem)
      .then(response => {
        // handle response...
      })
      .catch(err => { console.log(error) })
  } else { /* ... */ }
},

其次,在后台,<v-select>使用 av-for来遍历所有应该进入下拉菜单的选项。如果这是一个普通的 HTML<select>元素,它看起来像这样:

<select name="gender">
  <option value="">Select a gender...</option>
  <option
    v-for="gender in genders"
    :key="gender"
    value="gender.value"
  >
    {{ gender.text }}
  </option>
</select>

Vuetify 期望性别数组采用以下两种格式之一,字符串数组或具有textvalue属性的对象数组:

const genders = ['male', 'female', 'other']
// OR
const genders = [
  { value: 1, text: 'male' }, // `value` can be anything you want
  { value: 2, text: 'female' },
  { value: 3, text: 'other' },
]

或者,如果您的genders数组具有不同的数据结构,您可以告诉 Vuetify 为value和属性使用哪些text属性(这就是您所做的)。因此,如果您的性别数组如下所示:

const genders = [
  { name: 'male' },
  { name: 'female' },
  { name: 'other' },
]

<v-select>应该看起来像这样(在您的情况下,您对文本和值都使用了 SAME 属性,这样做非常好):

<v-select
  v-model="editedItem.gender"
  :items="genders"
  item-text="name"
  return-object
/>

根据您附加的图像,我猜测该genders数组不是其中一种格式,当 Vuetify 尝试将其转换为下拉列表时,这会导致错误。另外,我认为您打算将所选值分配给editedItem.gender而不是editedItem.gender.name. 这是一个代码笔,展示了如何将对象用于v-selectitems

如果items数组是我之前展示的两种格式之一,则不需要指定item-textanditem-value属性。它们将被自动检测到。

希望这可以帮助!

于 2020-04-23T19:43:50.540 回答