-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v-for, refs and access to refs.<array of components> by array index after Array.unshift #4952
Comments
https://jsfiddle.net/z11fe07p/773/ |
@Kingwl thanks for simple version! i can iterate $refs.items and search component by data, but not sure this right way |
Note that v-for refs do not guarantee the same order as your source Array. In the next release you can determine how to register refs yourself by passing a function to |
Sorry to respond to a closed issue - Is the list behavior documented anywhere? I did not see in for example: https://vuejs.org/v2/guide/list.html#key Seems to snag others, occasionally, as seen here and in: seems a quick note might be beneficial to save headaches.. thanks for a great framework either way :) |
"Note that v-for refs do not guarantee the same order as your source Array" Well this is a huge bummer. |
In the document https://vuejs.org/v2/guide/components.html#Child-Component-Refs, it says
But i really have the requirement for a dynamic ref in v-for for the example @Kingwl https://jsfiddle.net/z11fe07p/773/, i found a solution https://jsfiddle.net/Fmajor/cuay7v1j/2/ just manually clear the old ref array to null, and it works |
For the problem of $refs not being reactive, I'm using this.$nextTick(function () { }) and it works, I get an updated list of $refs. But for the problem of v-for $refs returning an array that does NOT match the order of your source data, I had to code a hack using custom uids, and resetting those uids (0 indexed) just before trying to access $refs, and then filtering that array by that uid property. |
Anyone come up with a solution they think is clean for this yet? It’s currently really hard to answer questions like “what is the bounding box of the element where item x in this array is being rendered?” since the refs array order is not synchronized with the data source order. Best I’ve come up with is assigning a different unique ref name for each item in the list like Other solution I had was adding a |
@yyx990803 |
This comment has been minimized.
This comment has been minimized.
An approach we just took is to give a |
@yyx990803 |
I needed to find a dom resource of the first element in a v-for using a dynamic component.
|
@zijjj @karljakober The correct approach to get the correct index is just as @adamawang proposed: |
I think this text is misleading as clearly it doesn't "mirror" the sequence.
It took me a few hours to discover that the order in For being complete these are the resources I went through to find this issue:
|
Trying to scroll to a newly added element similar to @adamwathan .. both look fairly bad, but i think the ref approach maybe looks slightly less bad if we look past the The other option would be setting the same ref to get a multi-item array and filtering for the one I want... What would be the recommended approach here? |
I think the best way is that to write vue instance the object of iterating: |
This comment has been minimized.
This comment has been minimized.
I'm late to this party but wouldn't the obvious fix be for vue to publish for-refs as an object keyed with the item :key instead of an array? vue already uses :key to identify the items, why shouldn't we? FWIW, changing vue/src/core/vdom/modules/ref.js Line 20 in 52719cc
This way, with a Yes I understand this is not backward compatible, it's just for the sake of the argument. |
Is this code not guaranteed to work as expected (comes from https://forum.vuejs.org/t/better-method-of-using-refs-inside-a-v-for-based-on-object/21352/2)? <list v-for="(item, key, index) in objectOfItems" :key="key">
<q-popover ref="editor">
<editor :item="item" @cancel="$refs.editor[index].close()"> Or is this code fine and this github issue is actually referring to a different problem? |
To anyone coming to this late, another potential workaround is to reorder your ref onto a parent and use it's children instead. <div ref="listParent">
<div v-for="..." :key="key">
<item />
</div>
</div>
...
this.$refs.listParent.children[index]; But I'm not a huge fan of this loose coupling to the markup as adding another element to the |
It's not amazing, but if it works for anyone else who runs into this problem, I just made a method that does a lookup based on parameters: <template>
<div v-for="item in items" :key="item.key">
<myitem :item="item" ref="items"></myitem>
</div>
</template>
<script>
export default {
methods: {
refItem(item) {
return this.$refs.items.find((refItem) => {
return refItem.item.key === item.key;
})
},
otherMethod(item) {
this.refItem(item).doThing();
}
}
}
</script> For me using it is relatively low incidence so it's not too expensive overall. I don't think this would be great if it was for every render. |
I went with this implementation for when there's a unique identifier for the iterated array/object. Does this make sense?
|
So true. |
It took me 40 minutes to discover and solve the order problem. I solve it by using a helper function <template>
<ul>
<li v-for="item of itemList" :key="item.id" :data-id="item.id"><canvas ref="canvas"></canvas></li>
</ul>
</template>
<script>
export default {
data(){
return {
itemList: []
}
},
mounted(){
this.itemList = [{id:'1'}, {id:'2'}];
this.$nextTick(()=>{
// let canvasArray = this.$refs.canvas;
let canvasArray = syncArrayOrder(this.$refs.canvas || [], (elem)=>elem.parentNode.dataset.id, this.itemList, (item) => item.id);
})
}
};
function syncArrayOrder(elemArray, idFunc, dataArray, keyFunc) {
let map = new Map();
for (let i = 0; i < elemArray.length; i++) {
let elem = elemArray[i];
map.set(idFunc(elem), elem);
}
return dataArray.map((item) => {
let key = keyFunc(item);
return map.get(key);
});
}
</script> |
Could someone take a look at this? I think it might be worth adding some notes on why it does not guarantee the right order |
|
See template Function Refs now in Vue 3: https://vuejs.org/guide/essentials/template-refs.html#function-refs |
here example: https://jsfiddle.net/alekzonder/1zcLkuwq/
vue.js 2.1.10
steps in example:
problem: item with index 1 is bold after Array.unshift in data
if remove
:key=item.id
in template with v-for, all works rightbug or feature?
The text was updated successfully, but these errors were encountered: