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

时间:2017-10-20 09:07:47

标签: html-table vue.js

我是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数据对象,但除了添加唯一的v-之外,我没有看到这样做的方法。文本到每个单独的<TD>单元格,例如

<div v-text="num_of_applications_assigned_1"></div>
<div v-text="num_of_applications_assigned_2"></div>
etc

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

 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不适合这种情况?

2 个答案:

答案 0 :(得分:2)

  

我无法使用v-for,因为表及其行都是生成服务器端

如果你不能使用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实例的基础数据的任何后续更改都将自动呈现。

希望这会有所帮助:)

答案 1 :(得分: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,则可以使assignizedApplications而不是数组成为类似于地图的数据结构,因此您可以通过其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;
            }
        }
    }
}

总之,一个例子看起来像这样:

&#13;
&#13;
<!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>
&#13;
&#13;
&#13;