admin管理员组

文章数量:1290959

I was wondering about using filters in vue

I know puted and when i use it but my question is

i used this code to sort fruits array instead of using puted

<li v-for="fruit in fruits.sort() ">{{fruit }}</li>

it run and i got the result correctly

but console notified me for error

[Vue warn]: You may have an infinite update loop in a ponent render function. 
(found in <MyFilter> at C:\xampp\htdocs\projects\max\___explaning\169_filters_mixins\src\MyFilter.vue)
warn @ VM6599:564
flushSchedulerQueue @ VM6599:2340
(anonymous) @ VM6599:511
nextTickHandler @ VM6599:460

when i removed .sort() the warn disappeared

the question : why this warn appeared and is there any way to add .sort() to v-for array without using puted values

I was wondering about using filters in vue

I know puted and when i use it but my question is

i used this code to sort fruits array instead of using puted

<li v-for="fruit in fruits.sort() ">{{fruit }}</li>

it run and i got the result correctly

but console notified me for error

[Vue warn]: You may have an infinite update loop in a ponent render function. 
(found in <MyFilter> at C:\xampp\htdocs\projects\max\___explaning\169_filters_mixins\src\MyFilter.vue)
warn @ VM6599:564
flushSchedulerQueue @ VM6599:2340
(anonymous) @ VM6599:511
nextTickHandler @ VM6599:460

when i removed .sort() the warn disappeared

the question : why this warn appeared and is there any way to add .sort() to v-for array without using puted values

Share Improve this question asked Apr 23, 2017 at 18:04 Mustafa AgameyMustafa Agamey 5132 gold badges9 silver badges21 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

You're getting the error because you are creating an infinite loop when calling fruit.sort() in the v-for statement.

fruit.sort() causes the array of be mutated (updated) and when Vue gets notified of this update, it attempts to update the DOM and then evaluate the v-for statement. This again will call fruit.sort() and then trigger an update.

Naive answer:

Instead you could use v-for="fruit in fruits.map(f => f).sort()", although this may bee quite heavy if the list is somewhat large. What this does is two things: 1) fruits.map(f => f) creates a new array containing the same values as fruits, and then 2) it sorts the newly created one.

Better answer:

Rather than inlining the copying and sorting inside the template (where it shouldn't be, you could use a method which does the same. You want to put as much logic as possible outside of the templates.

{
    ...Other ponent properties...

    methods: {
        sorted(arr) {
            // Return a copy of the sorted array
            return arr.map(e => e).sort()
        }
    }
    
    ...Other ponent properties...
}

Also better answer:

If you'd been using Vue 1.x, you could have used filters for this (v-for="fruit in fruits | orderBy", but using filters outside of text interpolation ({{ }}) has been removed from Vue 2.x and instead Vue's official migration guide suggests using puted properties for this exact thing.

Now, I'd still suggest not mutating the array inside the puted properties, but instead copy the array first and then sorting it, or perhaps even follow their guide and use lodash's orderBy(...) function for this.

{
    ...Other ponent properties...

    puted: {
        sortedFruits() {
            // Return a copy of the sorted array
            return this.fruits.map(f => f).sort()
        }
    }
    
    ...Other ponent properties...
}

Hope this helps.

Edit: Here's a pen displaying this.

Based on the documentation, array mutations methods also cause updates this is why you run in to an infinite loop. In other words, you are rendering the items in the list with the v-for directive, but then again with the sort mutation method.

本文标签: javascriptvuejs filters in vforStack Overflow