javascript - vue.js:HTML 元素显示-如果不切换更改

标签 javascript vue.js

我最初通过 API 调用渲染一些对象到我的数据库,它们被序列化,最初看起来像这样:

<h3>Messages on Database</h3>
    <p v-if="messages.length ===0">No Messages</p>
    <div class="msg" v-for="(msg, index) in messages" :key="index">
        <p class="msg-index">[{{index}}]</p>

        <p class="msg-subject" v-html="msg.subject" v-if="!msg.editing"></p>
        <p><input type="text" v-model="msg.subject" v-if="msg.editing" ></p>
        <p>{{msg.editing}}</p>
        <p class="msg-body" v-html="msg.body" v-show="!messages[index].editing"></p>
        <p><input type="text" v-model="msg.body" v-show="messages[index].editing" ></p>

        <input type="submit" @click="deleteMsg(msg.pk)" value="Delete" />
        <input type="submit" @click="EditMsg(index)" value="Edit" />
        <input type="submit" @click="updateMsg(msg.pk)" value="Update" />
    </div>
  </div>
</template>

<script>
export default {
  name: "Messages",
  data() {
    return {
      subject: "",
      msgBody: "",
      messages: [],
    };

},

每条消息如下所示:

enter image description here

请注意,bodypksubject 是 Django 模型字段。数组中的每一项代表一个数据库对象。

我想要使用 vue.js 做的是允许用户编辑每个项目。如果用户单击某个项目的 edit 按钮,我想将其元素从 p 转换为 input,并将其提交到数据库。

为了允许编辑单个项目,我需要在数组中的每个项目中都有一个editing字段,所以我在我的mounted中执行此操作() 属性:

  mounted() {
    this.fetchMessages();
  },
  methods: {
    fetchMessages() {
      this.$backend.$fetchMessages().then(responseData => {
        this.messages = responseData;
        this.messages.forEach(function (value) {
           value['editing'] = false;
        });
        console.log(this.messages);
      });
    }, 

现在,当我在控制台中加载数组时,我会看到以下内容:

enter image description here

所以我假设现在,当用户单击Edit按钮时,EditMsg被调用,并且字段将根据v-if<进行转换/v-show 指令:

EditMsg(msgIdx) {
        this.messages[msgIdx].editing = true;
        console.log(this.messages);
    },

但这并没有发生。实际发生的情况是这样的:在 console/vue-developer-tools 窗口中,项目的 editing 标志更改为 true,但 HTML 中没有任何变化。

我错过了什么?

完整代码:

<template>
  <div class="hello">
    <img src='@/assets/logo-django.png' style="width: 250px" />
    <p>The data below is added/removed from the Postgres Database using Django's ORM and Restframork.</p>
    <br/>
    <p>Subject</p>
    <input type="text" placeholder="Hello" v-model="subject">
    <p>Message</p>
    <input type="text" placeholder="From the other side" v-model="msgBody">
    <br><br>
    <input type="submit" value="Add" @click="postMessage" :disabled="!subject || !msgBody">

    <hr/>
    <h3>Messages on Database</h3>
    <p v-if="messages.length ===0">No Messages</p>
    <div class="msg" v-for="(msg, index) in messages" :key="index">
        <p class="msg-index">[{{index}}]</p>

        <p class="msg-subject" v-html="msg.subject" v-if="!msg.editing"></p>
        <p><input type="text" v-model="msg.subject" v-if="msg.editing" ></p>
        <p>{{msg.editing}}</p>
        <p class="msg-body" v-html="msg.body" v-show="!messages[index].editing"></p>
        <p><input type="text" v-model="msg.body" v-show="messages[index].editing" ></p>

        <input type="submit" @click="deleteMsg(msg.pk)" value="Delete" />
        <input type="submit" @click="EditMsg(index)" value="Edit" />
        <input type="submit" @click="updateMsg(msg.pk)" value="Update" />
    </div>
  </div>
</template>

<script>
export default {
  name: "Messages",
  data() {
    return {
      subject: "",
      msgBody: "",
      messages: [],
    };
  },
  mounted() {
    this.fetchMessages();
  },
  methods: {
    fetchMessages() {
      this.$backend.$fetchMessages().then(responseData => {
        this.messages = responseData;
        this.messages.forEach(function (value) {
           value['editing'] = false;
        });
        console.log(this.messages);
      });
    },
    postMessage() {
      const payload = { subject: this.subject, body: this.msgBody };
      this.$backend.$postMessage(payload).then(() => {
        this.msgBody = "";
        this.subject = "";
        this.fetchMessages();
      });
    },
    deleteMsg(msgId) {
        this.$backend.$deleteMessage(msgId).then(() => {
            this.messages = this.messages.filter(m => m.pk !== msgId);
            this.fetchMessages();
        });
    },
    EditMsg(msgIdx) {
        this.messages[msgIdx].editing = true;
        console.log(this.messages);
    },
    updateMsg(msgId) {
        console.log(this.subject, this.msgBody);
        const payload = { subject: this.subject, body: this.msgBody };
        this.$backend.$putMessage(msgId, payload).then(() => {
            this.fetchMessages();
            }
        )
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
hr {
  max-width: 65%;
}

.msg {
  margin: 0 auto;
  max-width: 30%;
  text-align: left;
  border-bottom: 1px solid #ccc;
  padding: 1rem;
}

.msg-index {
  color: #ccc;
  font-size: 0.8rem;
  /* margin-bottom: 0; */
}

img {
  width: 250px;
  padding-top: 50px;
  padding-bottom: 50px;
}

</style>

最佳答案

根据Vue internals :

Vue observes data by converting properties with Object.defineProperty. However, in ECMAScript 5 there is no way to detect when a new property is added to an Object, or when a property is deleted from an Object.

因此,当您将响应数据绑定(bind)到 this.messages 时,Vue 不再将数组属性的任何突变视为 react 性的。

相反,如果您在将 responseData 属性绑定(bind)到 Vue 数据属性之前对其进行丰富,则所有数组都会保持响应式。我的意思是这样的:

fetchMessages() {
 this.$backend.$fetchMessages().then(responseData => {
        let editableMessages = responseData;
        editableMessages.forEach(function (value) {
           value['editing'] = false;
        });
        this.messages = editableMessages;
      });
}

这里有一个small example基于您的域。

关于javascript - vue.js:HTML 元素显示-如果不切换更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52622907/

相关文章:

php - 在 html 标签中的鼠标悬停中的 setTimeOut 函数中使用 php 变量

javascript - JS : how to get FIrst N elements of associative array

javascript:从字符串中替换↵

php - Tinymce Enter 键

javascript - 如何将类 ="active"放入 vuejs for 循环中的第一个元素

vue.js - 错误 : vue-loader requires @vue/compiler-sfc to be present in the dependency tree

javascript - 如何在存储在数据库中的 vue.js 中呈现 blob 图像

javascript - 如何使用 javascript 删除 <a> 之间的文本

javascript - 正确使用 Vue $refs

javascript - 运行 Jest 时替换 `require.context`