在vuejs中处理模态:v-model或将每个元素绑定到值?

时间:2017-10-03 19:10:08

标签: vue.js vuejs2

几周前我刚刚开始使用Vuejs并且很享受它。

我正在渲染一个项目列表并有一个模态,我需要编辑项目并保存它。

我有这样的事情:

export default {
  data: function () {
    return {
      inventoryItems: null,
      showInventoryItemModal: false,
      selectedInventoryItem: null
    }
  },
  methods: {
    willShowInventoryItemModal: function(item){
      this.showInventoryItemModal = true;
      this.selectedInventoryItem = item;
    },

并在我的模板中:

<div class='bld'>header:</div><input v-model="selectedInventoryItem.header" type='text' size='80' class='ib span12' />
<button class='btn btn-outline-dark' @click.prevent="saveInventoryItem()">save</button>

问题在于,如果用户关闭模式,则基础列表的更改不准确。另一种选择(这是我一直在使用的)     是将中间项设置为所选项,然后在模板中呈现如下内容:

<div class='bld'>header:</div><input name='inventory_item[header]' :value="inventoryItem.header"  type='text' size='80' class='ib span12' />
<button class='btn btn-outline-dark' @click.prevent="saveInventoryItem()">save</button>

然后序列化表单并发布到服务器。这感觉不对(在几个层面上)但确实有效。我如何获取selectedInventoryItem和     将它与底层表示形式分离,以便它在服务器上更新之前不会更新支持列表?

编辑1

保存代码: 完整的模板代码:

  <form id="inventory_item_form">
    <input type='text' size='80' name="inventory_item[header]" :value="inventoryItem.header" class='ib span12' />
    <button class='btn btn-outline-dark' @click.prevent="saveInventoryItem()">save</button>
  </form>

并显示项目和保存功能:

willShowInventoryItemModal: function(item){
  this.showInventoryItemModal = true;
  this.inventoryItem = item;

},
saveInventoryItem: function(item){
  var method = 'post';
  var inventory_item_id = ''; // edit/add
  if(this.inventoryItem.id){
    method = 'put';
    inventory_item_id = this.inventoryItem.id;
  }
  var data_string = $('#inventory_item_form').serialize();  // jquery????

  axios({
    method: method,
    url:'/arc/api/v1/inventory_items/' + inventory_item_id,
    //data: {inventory_item: this.inventoryItem }  // this doesn't appear to update
    data: data_string
  })

1 个答案:

答案 0 :(得分:1)

这就是我通常处理这种情况的方式:

  1. created方法中初始化涉及异步的所有内容。在这种情况下,例如,从API获取数据。
  2. 使用占位符在用户编辑时存储要编辑的项目。
  3. 将编辑内容保存在占位符变量中。
  4. 将已修改的项目保存到API
  5. 成功后,使用inventoryItemscaveat)将最终数据保存回原始数据(即Vue.set)。
  6. 您可以看到我使用的是fetch而不是ajax,我建议这只是个人偏好,而且我已尽可能少地修改代码以适应占位符API I使用(JSON Placeholder)。

    &#13;
    &#13;
    const app = new Vue({
        el: '#app',
        data: {
          inventoryItems: null,
          showInventoryItemModal: false,
          selectedInventoryItem: null
        },
        created() {
          this.getPostData()
        },
        mounted() {
            
        },
        methods: {
            getPostData() {
              fetch("https://jsonplaceholder.typicode.com/posts")
                .then((res) => res.json())
                .then((result) => {
                  this.inventoryItems = result
                })
            },
            willShowInventoryItemModal(item) {
              // clone the variable
              this.selectedInventoryItem = JSON.parse(JSON.stringify(item))
            
              this.showInventoryItemModal = true
            },
            saveInventoryItem() {
              let data = new FormData();
              data.append( "json", JSON.stringify( this.selectedInventoryItem ) );
    
              fetch("https://jsonplaceholder.typicode.com/posts/"+this.selectedInventoryItem.id,
              {
                  method: "PUT",
                  body: data
              })
              .then((res) => res.json())
              .then((data) => { 
                console.log( JSON.stringify( data ) )
                    
                const indexOfItem = (this.inventoryItems.map((item)=>item.id)).indexOf(this.selectedInventoryItem.id) 
                Vue.set(this.inventoryItems, indexOfItem, JSON.parse(JSON.stringify(this.selectedInventoryItem)))
                this.selectedInventoryItem = null
                this.showInventoryItemModal = false
               })
            },
            cancelInventoryItem() {
              this.showInventoryItemModal = false
              this.selectedInventoryItem = null
            }
        }
    })
    &#13;
    #inventory_item_form {
        border: 2px black solid;
        padding: 20px;
    }
    
    table {
        font-family: arial, sans-serif;
        border-collapse: collapse;
        width: 100%;
    }
    
    td, th {
        border: 1px solid #dddddd;
        text-align: left;
        padding: 8px;
    }
    
    tr:nth-child(even) {
        background-color: #dddddd;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
    <div id="app">
        
        <form id="inventory_item_form" v-if="showInventoryItemModal">
          <h3>Edit:</h3>
          <div class='bld'>header: {{selectedInventoryItem.id}}</div>
          <input 
              v-model="selectedInventoryItem.title" 
              type='text' 
              size='80' 
              class='ib span12' />
          <button class='btn btn-outline-dark' @click.prevent="saveInventoryItem()">Save</button>
          <button class='btn btn-outline-dark' @click.prevent="cancelInventoryItem()">Cancel</button>
        </form>
        
        <table>
          <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Button</th>
          </tr>
          <tr v-for="item in inventoryItems">
            <td>{{item.id}}</td>
            <td>{{item.title}}</td>
            <td><button v-on:click="willShowInventoryItemModal(item)">Edit</button></td>
          </tr>
        </table>
        
        
        
    </div>
    &#13;
    &#13;
    &#13;