我有一个Vue组件,该组件执行aJax调用并循环浏览页面。首先,它显示根页面,然后检查每个根是否有任何子代,如果这样,它将使用子代数据创建组件的另一个实例,然后对此进行同样的操作。
因此,它基本上是一个递归菜单。但是,我添加了一些管理控件来显示软删除的页面,当我单击此按钮时,我会再次获取包含软删除的记录的页面。
但是我的视图没有更新,页面数据是一个对象,所以显然我使用this.$set()
是由于Vue内部的反应性。
谁能看到我的问题?
<template>
<div>
<div class="documentation__navigation--loading" v-if="loading">
Loading...
</div>
<div class="documentation__navigation__admin" v-if="root">
<label for="showDeleted" class="documentation__navigation__admin--deleted">
Show Deleted
<input type="checkbox" id="showDeleted" v-model="showDeleted">
</label>
</div>
<ul class="menu-list">
<draggable v-model="pages">
<transition-group name="fade">
<li v-for="page in pages" v-if="page.display" :key="page.id">
<i :class="[{ active: page.expanded }, expandedIcon(page.expanded)]" v-if="nodes[page.id]" @click="page.expanded = !page.expanded"></i><a :class="{ current: page.current, deleted: page.deleted_at != '' }" :href="'/docs/' + page.link">{{ page.title }} <i :class="page.icon"></i></a>
<transition name="fade">
<tree-menu v-if="page.expanded && nodes[page.id]" :root="false" :data="nodes" :page-id="page.id" :key="'sub'+page.id" :pass-editable="editable" :current="page.link"></tree-menu>
</transition>
</li>
</transition-group>
</draggable>
<li v-if="editable" class="add-new"><a :href="[ '/docs/add', current ].filter(Boolean).join('/')">Add New <i class="far fa-plus-circle"></i></a></li>
</ul>
</div>
</template>
<script>
import Axios from 'axios';
import draggable from 'vuedraggable';
export default {
components: {
draggable
},
props: {
data: {},
ajax: {},
token: {},
pageId: {},
current: {},
root: {
default: true,
type: Boolean
},
passEditable: {
default: false,
type: Boolean
},
expandIcon: {
default: 'fal fa-plus-square',
type: String
},
collapseIcon: {
default: 'fas fa-minus-square',
type: String
}
},
data() {
return {
nodes: {},
pages: {},
editable: this.passEditable,
showDeleted: false,
loading: false
}
},
created() {
if (!this.data) {
this.getPages();
}
else {
this.$set(this, 'pages', this.data[this.pageId]);
this.$set(this, 'nodes', this.data);
}
},
methods: {
getPages: function() {
const self = this;
Axios.get(this.ajax, {
params: {
'_token': this.token,
'current': this.current,
'showDeleted': this.showDeleted
}
})
.then(function(response) {
self.$set(self, 'nodes', response.data);
self.$set(self, 'pages', response.data.root);
self.$set(self, 'editable', response.data.editable);
});
},
expandedIcon: function(value) {
if (value) {
return this.collapseIcon;
}
return this.expandIcon;
}
},
watch: {
showDeleted: function() {
this.getPages();
}
}
}
</script>
一些示例数据:
{
"1": [
{
"id": 2,
"title": "Video Frame",
"content": "",
"link": "web-vue\/video-frame",
"name": "video-frame",
"icon": "fas fa-file-video",
"order": 0,
"display": 1,
"parent_id": 1,
"expanded": 0,
"updated_at": "2019-03-13 12:55:03",
"created_at": null,
"deleted_at": null
},
{
"id": 4,
"title": "Favourites",
"content": "",
"link": "web-vue\/favourites",
"name": "favourites",
"icon": "fas fa-heart",
"order": 1,
"display": 1,
"parent_id": 1,
"expanded": 1,
"updated_at": null,
"created_at": null,
"deleted_at": null
}
],
"5": [
{
"id": 6,
"title": "Favourites",
"content": "",
"link": "web-feature-favourites",
"name": "web-feature-favourites",
"icon": "fas fa-heart",
"order": 0,
"display": 1,
"parent_id": 5,
"expanded": 0,
"updated_at": null,
"created_at": null,
"deleted_at": null
}
],
"4": [
{
"id": 7,
"title": "Panel",
"content": "",
"link": "web-vue\/favourites\/favourites-panel",
"name": "favourites-panel",
"icon": "",
"order": 1,
"display": 1,
"parent_id": 4,
"expanded": 1,
"updated_at": null,
"created_at": null,
"deleted_at": null,
"current": true
}
],
"0": [
{
"id": 17,
"title": "Job",
"content": "dsadasfasfas",
"link": "web-vue\/favourites\/test",
"name": null,
"icon": "fas fa-file-video",
"order": 2,
"display": 1,
"parent_id": 0,
"expanded": 0,
"updated_at": "2019-03-19 10:10:36",
"created_at": "2019-03-19 09:29:42",
"deleted_at": "2019-03-19 10:10:36"
}
],
"root": [
{
"id": 3,
"title": "Home",
"content": "",
"link": "web-home",
"name": "web-home",
"icon": "",
"order": 0,
"display": 1,
"parent_id": null,
"expanded": 0,
"updated_at": null,
"created_at": null,
"deleted_at": null
},
{
"id": 1,
"title": "Vue Components",
"content": "",
"link": "web-vue",
"name": "web-vue",
"icon": "fab fa-vuejs",
"order": 1,
"display": 1,
"parent_id": null,
"expanded": 1,
"updated_at": null,
"created_at": null,
"deleted_at": null
},
{
"id": 5,
"title": "Features",
"content": "",
"link": "web-features-home",
"name": "web-features-home",
"icon": "",
"order": 2,
"display": 1,
"parent_id": null,
"expanded": 0,
"updated_at": null,
"created_at": null,
"deleted_at": null
}
],
"editable": true
}
只是做了更多测试,似乎第一个Component实例正在看到此更新,是子组件没有看到此更新,我的印象是,如果我的父组件获取了更新的数据,它将重新呈现子组件,然后将更新的数据当然传递给他们?