admin管理员组文章数量:1026989
I am trying to dynamically create/remove a Vue ponent. I have figured out how to dynamically add the ponent, but I am having some troubles with allowing the users to remove the specific ponent.
Consider below two Vue files:
TableControls.vue
<a v-on:click="addColumn">Add Column</a>
<script>
export default {
methods: {
addColumn: function () {
Event.$emit('column-was-added')
}
}
};
</script>
DocumentViewer.vue
:
<div v-for="count in columns">
<VueDragResize :id="count">
<a @click="removeColumn(count)">Remove Column</a>
</VueDragResize>
</div>
<script>
import VueDragResize from 'vue-drag-resize';
export default {
ponents: {
VueDragResize
},
data() {
return {
columns: [1],
}
},
created() {
Event.$on("column-was-added", () => this.addColumn())
},
methods: {
addColumn: function () {
this.columns.push(this.columns.length + 1)
},
removeColumn: function (id) {
this.columns.splice(id, 1)
}
}
};
</script>
As you can see, whenever a user clicks on <a v-on:click="addColumn">Add Column</a>
, it will submit an event, and the DocumentViewer.vue
file will pick up it, firing the addColumn
method. This will ultimately create a new <VueDragResize></VueDragResize>
ponent.
This works great.
The problem is when I want to remove the ponent again. My removeColumn
method simply removes an id from the columns
array:
removeColumn: function (id) {
this.columns.splice(id, 1)
}
This results in that a column is in fact removed. However, consider below example. When user clicks on the remove icon for the first column, it will remove the 2nd column instead. (And when there is only one column present, it cannot be removed).
I believe this is due to the fact that I splice()
the array, but I cannot see how else I can remove the ponent dynamically?
I am trying to dynamically create/remove a Vue ponent. I have figured out how to dynamically add the ponent, but I am having some troubles with allowing the users to remove the specific ponent.
Consider below two Vue files:
TableControls.vue
<a v-on:click="addColumn">Add Column</a>
<script>
export default {
methods: {
addColumn: function () {
Event.$emit('column-was-added')
}
}
};
</script>
DocumentViewer.vue
:
<div v-for="count in columns">
<VueDragResize :id="count">
<a @click="removeColumn(count)">Remove Column</a>
</VueDragResize>
</div>
<script>
import VueDragResize from 'vue-drag-resize';
export default {
ponents: {
VueDragResize
},
data() {
return {
columns: [1],
}
},
created() {
Event.$on("column-was-added", () => this.addColumn())
},
methods: {
addColumn: function () {
this.columns.push(this.columns.length + 1)
},
removeColumn: function (id) {
this.columns.splice(id, 1)
}
}
};
</script>
As you can see, whenever a user clicks on <a v-on:click="addColumn">Add Column</a>
, it will submit an event, and the DocumentViewer.vue
file will pick up it, firing the addColumn
method. This will ultimately create a new <VueDragResize></VueDragResize>
ponent.
This works great.
The problem is when I want to remove the ponent again. My removeColumn
method simply removes an id from the columns
array:
removeColumn: function (id) {
this.columns.splice(id, 1)
}
This results in that a column is in fact removed. However, consider below example. When user clicks on the remove icon for the first column, it will remove the 2nd column instead. (And when there is only one column present, it cannot be removed).
I believe this is due to the fact that I splice()
the array, but I cannot see how else I can remove the ponent dynamically?
- there are missing parts in your sample. Where is the part that generates the columns ? – y_nk Commented Jun 17, 2019 at 6:24
- @y_nk sorry, I have updated my question. – oliverbj Commented Jun 17, 2019 at 6:31
3 Answers
Reset to default 3I see, Array on Vue does not re render when you modify them.
You need to use the
Vue.set(items, indexOfItem, newValue)
if you want to modify
and use
Vue.delete(target, indexOfObjectToDelete);
If you want to delete an item from an array
You may read the additional info here https://v2.vuejs/v2/api/#Vue-delete
If you want to delete an item from array. Using this will cause the ponent to rerender.
In this case it will be intuitive to do this
removeColumn: function (id) {
Vue.delete(this.columns, id)
}
Note that id should be the index. Vue.delete ensures the re-render of the ponent.
EDIT, you must use the index, instead of the count here.
<div v-for="(count, index) in columns">
<VueDragResize :id="index">
<a @click="removeColumn(index)">Remove Column</a>
</VueDragResize>
</div>
I would remend reshaping your data, each element should be an object with an id and whatever other properties you want. Not simply an id then you would need something like this:
removeColumn(id) {
const elToRemove = this.columns.findIndex(el => el.id === id)
let newArr = [elToRemove, ...this.columns]
this.columns = newArr
}
Also make another puted
property for columns
like this to make sure they change dynamically (when you add/remove):
puted: {
dynColumns(){ return this.columns}
}
I have same problem, and I found the solution of this problem. It is need to set #key with v-for. This is Built-in Special Attributes.
By default, if you do not set "#key", array index is set to#key. So if array length is 3, #key is 0,1,2. Vue identify each v-for elements by key. If you remove second value of array, then array index is 0 and 1, because array length is 2. Then Vue understand that #key==2 element removed, So Vue remove 3rd ponent. So if you remove second value of array, if no #key, third ponent will be removed. To avoid this, need to set #key to identify ponent like this:
let arr = [
{ id: 'a', ...},
{ id: 'b', ...},
{ id: 'c', ...}
];
<div v-for="obj in arr" :key="obj.id">
<someYourComponent>
...
</someYourComponent>
</div>
I am trying to dynamically create/remove a Vue ponent. I have figured out how to dynamically add the ponent, but I am having some troubles with allowing the users to remove the specific ponent.
Consider below two Vue files:
TableControls.vue
<a v-on:click="addColumn">Add Column</a>
<script>
export default {
methods: {
addColumn: function () {
Event.$emit('column-was-added')
}
}
};
</script>
DocumentViewer.vue
:
<div v-for="count in columns">
<VueDragResize :id="count">
<a @click="removeColumn(count)">Remove Column</a>
</VueDragResize>
</div>
<script>
import VueDragResize from 'vue-drag-resize';
export default {
ponents: {
VueDragResize
},
data() {
return {
columns: [1],
}
},
created() {
Event.$on("column-was-added", () => this.addColumn())
},
methods: {
addColumn: function () {
this.columns.push(this.columns.length + 1)
},
removeColumn: function (id) {
this.columns.splice(id, 1)
}
}
};
</script>
As you can see, whenever a user clicks on <a v-on:click="addColumn">Add Column</a>
, it will submit an event, and the DocumentViewer.vue
file will pick up it, firing the addColumn
method. This will ultimately create a new <VueDragResize></VueDragResize>
ponent.
This works great.
The problem is when I want to remove the ponent again. My removeColumn
method simply removes an id from the columns
array:
removeColumn: function (id) {
this.columns.splice(id, 1)
}
This results in that a column is in fact removed. However, consider below example. When user clicks on the remove icon for the first column, it will remove the 2nd column instead. (And when there is only one column present, it cannot be removed).
I believe this is due to the fact that I splice()
the array, but I cannot see how else I can remove the ponent dynamically?
I am trying to dynamically create/remove a Vue ponent. I have figured out how to dynamically add the ponent, but I am having some troubles with allowing the users to remove the specific ponent.
Consider below two Vue files:
TableControls.vue
<a v-on:click="addColumn">Add Column</a>
<script>
export default {
methods: {
addColumn: function () {
Event.$emit('column-was-added')
}
}
};
</script>
DocumentViewer.vue
:
<div v-for="count in columns">
<VueDragResize :id="count">
<a @click="removeColumn(count)">Remove Column</a>
</VueDragResize>
</div>
<script>
import VueDragResize from 'vue-drag-resize';
export default {
ponents: {
VueDragResize
},
data() {
return {
columns: [1],
}
},
created() {
Event.$on("column-was-added", () => this.addColumn())
},
methods: {
addColumn: function () {
this.columns.push(this.columns.length + 1)
},
removeColumn: function (id) {
this.columns.splice(id, 1)
}
}
};
</script>
As you can see, whenever a user clicks on <a v-on:click="addColumn">Add Column</a>
, it will submit an event, and the DocumentViewer.vue
file will pick up it, firing the addColumn
method. This will ultimately create a new <VueDragResize></VueDragResize>
ponent.
This works great.
The problem is when I want to remove the ponent again. My removeColumn
method simply removes an id from the columns
array:
removeColumn: function (id) {
this.columns.splice(id, 1)
}
This results in that a column is in fact removed. However, consider below example. When user clicks on the remove icon for the first column, it will remove the 2nd column instead. (And when there is only one column present, it cannot be removed).
I believe this is due to the fact that I splice()
the array, but I cannot see how else I can remove the ponent dynamically?
- there are missing parts in your sample. Where is the part that generates the columns ? – y_nk Commented Jun 17, 2019 at 6:24
- @y_nk sorry, I have updated my question. – oliverbj Commented Jun 17, 2019 at 6:31
3 Answers
Reset to default 3I see, Array on Vue does not re render when you modify them.
You need to use the
Vue.set(items, indexOfItem, newValue)
if you want to modify
and use
Vue.delete(target, indexOfObjectToDelete);
If you want to delete an item from an array
You may read the additional info here https://v2.vuejs/v2/api/#Vue-delete
If you want to delete an item from array. Using this will cause the ponent to rerender.
In this case it will be intuitive to do this
removeColumn: function (id) {
Vue.delete(this.columns, id)
}
Note that id should be the index. Vue.delete ensures the re-render of the ponent.
EDIT, you must use the index, instead of the count here.
<div v-for="(count, index) in columns">
<VueDragResize :id="index">
<a @click="removeColumn(index)">Remove Column</a>
</VueDragResize>
</div>
I would remend reshaping your data, each element should be an object with an id and whatever other properties you want. Not simply an id then you would need something like this:
removeColumn(id) {
const elToRemove = this.columns.findIndex(el => el.id === id)
let newArr = [elToRemove, ...this.columns]
this.columns = newArr
}
Also make another puted
property for columns
like this to make sure they change dynamically (when you add/remove):
puted: {
dynColumns(){ return this.columns}
}
I have same problem, and I found the solution of this problem. It is need to set #key with v-for. This is Built-in Special Attributes.
By default, if you do not set "#key", array index is set to#key. So if array length is 3, #key is 0,1,2. Vue identify each v-for elements by key. If you remove second value of array, then array index is 0 and 1, because array length is 2. Then Vue understand that #key==2 element removed, So Vue remove 3rd ponent. So if you remove second value of array, if no #key, third ponent will be removed. To avoid this, need to set #key to identify ponent like this:
let arr = [
{ id: 'a', ...},
{ id: 'b', ...},
{ id: 'c', ...}
];
<div v-for="obj in arr" :key="obj.id">
<someYourComponent>
...
</someYourComponent>
</div>
本文标签: javascriptVuejsRemove specific component dynamicallyStack Overflow
版权声明:本文标题:javascript - Vue.js - Remove specific component dynamically - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745658213a2161724.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论