【问题标题】:Splicing array does not re-render table row Vuejs拼接数组不会重新渲染表格行Vuejs
【发布时间】:2019-01-29 04:57:57
【问题描述】:

我有一个使用来自 ajax 请求的数据生成的用户表。表格大致是这样的:Image of Table

当管理员编辑用户的用户名时,我希望用户的行重新呈现更改(特别是用户的名字和姓氏)。

我很好地创建了表格。模型工作正常。我的父组件在我的 edit() 方法中很好地接收了编辑的数据,但我似乎无法用我更改的数据重新渲染我的目标行。如何使我的目标行更新?

我尝试了以下方法,但没有成功:

这是我的父 vue 组件,内容如下(我去掉了不相关的细节):

模板:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Email Address</th>
            <th>Created</th>
            <th>Stat</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        <tr v-for="(user, index) in listOfUsers" :key="'row' + user._id"> 
            <td>{{user.first_name + ' ' + user.last_name}}</td>
            <td>{{user.email}}</td>
            <td>{{user.created}}</td>
            <td>
                <a v-if="user.confirmed" @click="determineButtonClicked(index, 'confirm')"></a>
                <a v-else @click="determineButtonClicked(index, 'unconfirm')"></a>
            </td>
            <td class="buttonCase">
                <a @click="determineButtonClicked(index, 'info')"></a>

                <a v-if="user.blocked" @click="determineButtonClicked(index, 'blocked')"></a>
                <a v-else @click="determineButtonClicked(index, 'block')"></a>

                <a v-if="user.enforce_info === 'required'" @click="determineButtonClicked(index, 'enforceInfoActive')"></a> 
                <a v-else-if="user.enforce_info === 'done'" @click="determineButtonClicked(index, 'enforceInfoChecked')"></a>
                <a v-else @click="determineButtonClicked(index, 'enforceInfo')"></a>

                <modal v-if="usersList[index]" @toggleClickedState="setState(index)" @editUser="edit(index, $event)" :id="user._id" :action="action"></modal>
            </td>
        </tr>
    </tbody>
</table>

脚本

<script>
    export default {
        created: function() {
            let self = this;
            $.getJSON("/ListOfUsers",
            function(data){
                self.listOfUsers = data;
            });
        },
        data: function() {
            return {
                listOfUsers: [],
            }
        },
        methods: {
            edit(index, update){
                let user = this.listOfUsers[index];
                user.firstName = update.firstName;
                user.lastName = update.lastName;

                // this.listOfUsers.splice(index, 1, user)
                this.listOfUsers.$set(index, user)
            }
        }
    }
</script>

感谢您的宝贵时间和帮助!

【问题讨论】:

  • 什么是&lt;modal&gt;edit(index, $event) 中的$event 如何变成edit(index, update) { ... } 中的update
  • @Phil 是另一个文件中定义的 vue 组件。就像它的名字一样,这个组件定义了一个模态弹出窗口。 $event 是我从模态组件访问发出值的方式。 vuejs.org/v2/guide/…

标签: javascript ajax vuejs2 vue-component vue-router


【解决方案1】:

Vue 没有在你的编辑方法中更新,因为对象本身没有被替换。对象的属性确实发生了变化,但 Vue 只是寻找要更改的对象引用。

要强制数组检测实际对象引用的变化,您需要替换对象,而不是修改它。我不知道你到底想怎么做,但是这个被破解的小提琴应该可以证明这个问题,所以你可以解决它:http://jsfiddle.net/tga50ry7/5/

简而言之,如果您将编辑方法更新为如下所示,您应该会在模板中看到重新渲染:

methods: {
   edit(index, update){
      let currentUser = this.listOfUsers[index];
      let newUser = {
         first_name: update.firstName,
         last_name: update.lastName,
         email: currentUser.email,
         created: currentUser.created
      }

      this.listOfUsers.splice(index, 1, newUser)
   }
}

【讨论】:

  • 谢谢!这行得通。在进行更改之前,我使用 Object.assign() 获取对象的副本。
【解决方案2】:

你可以试试这样

<script>
    export default {
        created: function() {
            let self = this;
            $.getJSON("/ListOfUsers",
            function(data){
                self.listOfUsers = data;
            });
        },
        data: function() {
            return {
                listOfUsers: [],
            }
        },
        methods: {
            edit(index, update){
                let user = this.listOfUsers[index];
                user.firstName = update.firstName;
                user.lastName = update.lastName;

                // this.listOfUsers.splice(index, 1, user)
                this.$set(this.listOfUsers,index, user)
            }
        }
    }
</script>

【讨论】: