Vue - 如何将表格列绑定到数据对象?

3

我是一名新手,刚开始接触Vue。以下是我的情况,请多多关照!在这里,必须有比我现在所做的更好的方式。

我有一个简单的2列HTML表格:

<table id="contacts">
<tbody>
    <tr>
        <th class="column-1">
            Contact Id
        </th>
        <th class="column-2">
            Applications assigned count
        </th>       
    </tr>
      <tr class="odd" id="contacts_tr_1">
 <td class="column-1">
      1
      </td>
 <td class="column-2">
      247
      </tr>
      <tr class="even last" id="contacts_tr_2">
 <td class="column-1">
      2
      </td>
 <td class="column-2">
     0
      </td>
  </tr>
      <tr class="even last" id="contacts_tr_2">
 <td class="column-1">
      3
      </td>
 <td class="column-2">
     44
      </td>
  </tr>
        <tr class="even last" id="contacts_tr_2">
 <td class="column-1">
      .........
      </td>
 <td class="column-2">
     .........
      </td>
  </tr>

      <tr class="even last" id="contacts_tr_2">
 <td class="column-1">
      10
      </td>
 <td class="column-2">
     76
      </td>
  </tr>
 </tbody>
 </table>

我想更新“应用分配计数”列(但仅适用于特定行),由AJAX调用的结果确定。因此,假设该表有10行,则AJAX调用可能会说需要更新第1、4和7行的“应用程序分配计数”列的值,例如分别为247、80和356。我考虑使用像这样的JSON对象作为我的Vue数据对象,因为AJAX响应将如下所示。
  data: {
    num_of_applications_assigned: [
        {
            "party_id": "1",
            "num": "247"},
        {
            "party_id": "4",
            "num": "80"},
        {
            "party_id": "7",
            "num": "356"}

    ]
  },

我认为可能有一种方法可以将“分配的应用程序计数”列绑定到由AJAX调用更新的Vue数据对象,但我没有看到除了为每个单独的<TD>单元格添加唯一的v-text之外的其他方法。
<div v-text="num_of_applications_assigned_1"></div>
<div v-text="num_of_applications_assigned_2"></div>
etc

然而,这导致我在使用 AJAX 响应结果更新那些 v-text 时编写了一些非常复杂的代码,因为我必须动态构造引用。

 let vm = this;
    jQuery.ajax({
            url: myurl
        }).then(function(response) {                
           for (var i = 0, len = vm.num_of_applications_assigned.length; i < len; i++) {
            var party_id = vm.num_of_applications_assigned[i].party_id;
            var dref = 'vm.num_of_applications_assigned_'+party_id;
            var dnum = vm.num_of_applications_assigned[i].num;
            eval(dref + ' = ' + dnum + ';');
           }           
    });

是的,我知道 eval 不好 - 这就是我在这里寻求帮助的原因!有没有更好的方法来完成这个任务,或者 Vue 并不适合这种情况?


1
使用v-for指令,是的,Vue是响应式的,你只需要让你的数据更新为Ajax调用的结果,表格就会重新渲染更新后的内容。 - Ewomazino Ukah
我认为在这种情况下我不能使用v-for,因为表格行已经在服务器上预先创建。不过我可以向单个行或单元格添加内容。你有什么建议? - J Dor
2个回答

3
如果您无法使用`v-for`,您仍然可以使用Vue来渲染数据。如果您决定在服务器端做一些额外的工作,并以略微不同的方式塑造数据,这将比`v-for`的解决方案略显不够优雅但应该是直截了当的。
例如,如果您想要创建一个两列表格,其中Vue将渲染/更新第二列的单元格值,则可以在服务器端生成类似于以下内容:
<table id="app">
    <tr>
        <td>1</td> 
        <td>{{ applications.party_1.num }}</td>
    </tr>
    <tr>
        <td>2</td> 
        <td>{{ applications.party_2.num }}</td>
    </tr>
</table>

您可以使用喜欢的服务器端语言动态生成值party_1party_2party_3。这意味着存在一个类似以下结构的基础数据:

applications: {
  party_1: { num: 1 },
  party_2: { num: 2 }
}

在服务器端动态创建这种结构应该很容易。然后,只需创建一个Vue实例并使用该数据结构填充其初始的data对象:

new Vue({
  el: '#app',
  data: {
    applications: {
      party_1: { num: 1 },
      party_2: { num: 2 }
    }
  }
});

当HTML在浏览器中呈现时,Vue实例会被挂载并更新绑定到其data对象的单元格值。这些值是响应式的,因此Vue实例底层数据的任何后续更改都将自动呈现。
希望这有所帮助 :)

谢谢!这正是我在寻找的! - J Dor

1
Vue的思想是让所有数据准备好,让Vue.JS进行渲染。因此,您的数据应该像这样:
data: {
   assignedApplications: [
    { party_id: 1, num: 247 },
    { party_id: 2, num: 0 },
    { party_id: 3, num: 44 },
    { party_id: 4, num: 76 },
    { party_id: 5, num: 9 },
   ]
  },
}

然后,你可以让Vue渲染它:
<table>
    <tr>
        <th class="column-1">Contact Id</th>
        <th class="column-2">Applications assigned count</th>       
    </tr>
    <tr v-for="a in assignedApplications">
        <td>{{a.party_id}}</td>
        <td>{{a.num}}</td>
    </tr>
</table>

问题仍然存在,如何更新它。在获取新数据后,您必须修改数组this.assignedApplications,然后Vue将正确地重新呈现表格。如果您的行具有唯一的id,则可以将assignedApplications替换为类似地图的数据结构,以便您可以通过其id轻松访问特定行并更改值。如果没有,则必须搜索整个数组以进行每次更改并进行适应:

mergeInNewData(newData) {
    for (let i = 0; i < newData.length; i++) {
        let changedData = newData[i];
        for (let j = 0; j < this.assignedApplications.length; j++) {
            if (this.assignedApplications[j].party_id === changedData.party_id) {
                this.assignedApplications[j].num = changedData.num;
            }
        }
    }
}

整体而言,一个示例可能看起来像这样:

<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/vue"></script>
</head>
<body>
  <div id="app">
   <table>
   <tr>
    <th class="column-1">Contact Id</th>
    <th class="column-2">Applications assigned count</th>       
   </tr>
   <tr v-for="a in assignedApplications">
    <td>{{a.party_id}}</td>
    <td>{{a.num}}</td>
   </tr>
  </table>
  <a href="#" v-on:click.prevent="update">Update</a>
 </div>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        assignedApplications: [
         { party_id: 1, num: 247 },
         { party_id: 2, num: 0 },
         { party_id: 3, num: 44 },
         { party_id: 4, num: 76 },
         { party_id: 5, num: 9 },
        ]
      },
      methods: {
       update: function() {
        let newData = [
         { party_id: 1, num: 243},
         { party_id: 2, num: 80},
         { party_id: 4, num: 0},
        ];
        this.mergeInNewData(newData);
       },
       mergeInNewData(newData) {
        for (let i = 0; i < newData.length; i++) {
         let changedData = newData[i];
         for (let j = 0; j < this.assignedApplications.length; j++) {
          if (this.assignedApplications[j].party_id === changedData.party_id) {
           this.assignedApplications[j].num = changedData.num;
          }
         }
        }
       }
      }
    })
  </script>
</body>
</html>


非常感谢您提供详细的答案,我真的很感激。不幸的是,我真的认为我不能使用v-for,因为表格及其行都是在服务器端生成的(我将使用的实际表格比此示例复杂得多)。正如我在问题中所说的那样,我真的认为Vue不适合我的情况。我可能不得不退回到jQuery来更新这些列值。 - J Dor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接