[英]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.它应该用于原始值。
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-for
与auxData
一起使用,因为这就是您使用 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
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.