简体   繁体   English

如何防止重新呈现未在我的 vue.js 组件的 HTML 中使用的变量?

[英]how to prevent a re-rendering of a variable that is not being used in the HTML of my vue.js component?

I am trying to recreate a real example of my code.我正在尝试重新创建我的代码的真实示例。 In my real code, this line is actually a component that will fetch an endpoint every few seconds, and fetch a random array of "n" length, myData it will contain these fetch.在我的真实代码中,这一行实际上是一个component ,每隔几秒就会fetch一个端点,并获取一个长度为"n"的随机数组, myData将包含这些获取的内容。

<div v-for="item in addingData(myData)">  <!-- in My real code, "myData" should be the answer of an endpoint, is an setInterval, returns data like [{id:1},{id:2}] -->
  {{ item.id }}
</div>

I am simulating that the response changes in myData with the help of setTimeOut我在setTimeOut的帮助下模拟myData中的响应变化

mounted() {
  setTimeout(() => {
    console.log('First data');
    this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }];
    setTimeout(() => {
      console.log('second data');
      this.myData = [{ id: 4 }, { id: 4 }];
      setTimeout(() => {
        console.log('Third data');
        this.myData = [];
      }, 3000);
    }, 3000);
  }, 2000);
},

I am trying to make that every time I receive data in myData , the list of the concatenation of the received data is shown without having repeated data.我试图做到这一点,每次我在myData中接收数据时,都会显示接收到的数据的串联列表,而不会重复数据。 That's why every time I receive data, that calls the function addingData(myData) that will do this data concatenation.这就是为什么每次我收到数据时,都会调用 function addingData(myData)来执行此数据串联。 I'm using the function v-for="item in addingData(myData) and auxData is the variable that will do this concatenation.v-for="item in addingData(myData)并且auxData是将执行此连接的变量。

why when there is new data, the addingData function is called 2 times and how can I prevent it?为什么当有新数据时,addingData function 被调用了 2 次,我该如何防止呢?

在此处输入图像描述

in terms of performance this should be the output in the console.log :就性能而言,这应该是console.log中的 output:

在此处输入图像描述

what causes this re-rendering and how can I avoid it?是什么导致了这种重新渲染,我该如何避免呢?

this is my live code:这是我的实时代码:

https://stackblitz.com/edit/vue-l7gdpj?file=src%2FApp.vue https://stackblitz.com/edit/vue-l7gdpj?file=src%2FApp.vue

<template>
  <div id="app">
    <div v-for="item in addingData(myData)">
      {{ item.id }}
    </div>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  data() {
    return {
      myData: [],
      auxData: [],
    };
  },
    mounted() {
      setTimeout(() => {
        console.log('First data');
        this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }];
        setTimeout(() => {
          console.log('second data');
          this.myData = [{ id: 4 }, { id: 4 }];
          setTimeout(() => {
            console.log('Third data');
            this.myData = [];
          }, 3000);
        }, 3000);
      }, 2000);
    },
  methods: {
    addingData(getDataFetch) {
      console.log('Entering AddingData', getDataFetch);
      if (getDataFetch.length !== 0) {
        if (this.auxData.length === 0) {
          //Adding initial data
          this.auxData = getDataFetch;
        } else {
          //prevent duplicated values
          getDataFetch.forEach((item) => {
            const isNewItem = this.auxData.find((itemAux) => {
              return item.id === itemAux.id;
            });
            if (!isNewItem) {
              //adding new data 
              this.auxData.unshift(item);
            }
          });
        }
      } else {
        //if there is not data, return []
        return this.auxData;
      }
    },
  },
};
</script>

in terms of performance this should be the output in the console.log就性能而言,这应该是 console.log 中的 output

In terms of performance, you should use as few reactive data as possible, especially if your object has many properties.在性能方面,您应该使用尽可能少的反应数据,尤其是当您的 object 具有许多属性时。 I would modify auxData directly.我会直接修改 auxData。

 this.addingData([{ id: 3 }, { id: 2 }, { id: 1 }]);

Simplified addingData简化添加数据

addingData(getDataFetch) {
  // It's faster to get the id-s first
  let itemDict = new Set(this.auxData.map((m) => m.id));
  getDataFetch.forEach((item) => {
    if (!itemDict.has(item.id)) {
      this.auxData.unshift(item);
      itemDict.add(item.id);
    }
  });
},

And iterate over it并遍历它

<div v-for="item in auxData">
  {{ item.id }}
</div>

Also watching object list can also cause performance issues.同时查看 object 列表也会导致性能问题。 It should be used on primitive values.它应该用于原始值。

Example on StackBlitz StackBlitz 上的示例

Looks like you should be using v-for with auxData as that's what you're updating using the result of your API call (myData).看起来您应该将v-forauxData一起使用,因为这就是您使用 API 调用 (myData) 的结果更新的内容。 As your API sends you new results, use a watcher to run a function whenever a new update is made to then also update auxData当您的 API 向您发送新结果时,每当进行新更新时,使用观察程序运行 function 以同时更新auxData

updated stackblitz更新的堆栈闪电战

watch: {
    myData(newData, oldData) {
      console.log('Entering AddingData', newData);
      if (newData.length !== 0) {
        if (this.auxData.length === 0) {
          this.auxData = newData;
        } else {
          newData.forEach((item) => {
            const isNewItem = this.auxData.find((itemAux) => {
              return item.id === itemAux.id;
            });
            if (!isNewItem) {
              this.auxData.unshift(item);
            }
          });
        }
      }
    },
  },
<div v-for="item in auxData">
  {{ item.id }}
</div>

As per my understanding, You want to combined the unique objects in to an array getting from multiple API calls and show them into the template using v-for .根据我的理解,您想将唯一对象组合到一个数组中,该数组从多个 API 调用中获取,并使用v-for将它们显示到模板中。 If Yes, You can achieve that by using computed property.如果是,您可以通过使用computed属性来实现。

As you are updating the myData every time you are getting response, You can push the unique objects into a separate array and then return that array using a computed property.当您每次收到响应时都更新myData时,您可以将唯一对象推送到一个单独的数组中,然后使用计算属性返回该数组。

Live Demo :现场演示

 new Vue({ el: '#app', data: { combinedData: [], myData: [] }, mounted() { setTimeout(() => { console.log('First data'); this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }]; this.pushData(this.myData) setTimeout(() => { console.log('second data'); this.myData = [{ id: 4 }, { id: 4 }]; this.pushData(this.myData) setTimeout(() => { console.log('Third data'); this.myData = []; this.pushData(this.myData) }, 3000); }, 3000); }, 2000); }, methods: { pushData(data) { data.forEach(obj => { if (.JSON.stringify(this.combinedData).includes(JSON.stringify(obj))) { this.combinedData;push(obj) } }), } }: computed. { finalData() { return this.combinedData } } })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <div v-for="item in finalData"> {{ item.id }} </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM