【发布时间】:2018-09-01 22:23:19
【问题描述】:
我一直在 SO 和 Vue 论坛上搜索与递归组件相关的任何问题,当我最终尝试解决一个错误的方法时,它会导致另一个错误,所以这里是细分:
我有一个组件 Contents.vue,里面有 Item.vue:
<template>
<div class="content__wrapper wrapper" :class="{'expanded-content': state.expansion}">
<p v-if="liked && items.length === 0" class="title">{{ data.defaults.add_liked }}</p>
<p v-if="!liked && assemble_contents_array.length === 0" class="title">{{ data.defaults.products_missing }}</p>
<Item v-for="(item, index) in liked ? items : assemble_contents_array" :key="`item-${index}`" :full_data="items" :item_data="item" :ind="index"
:expand="state.item_for_expansion === index" :is_expansion="state.expansion" :defaults="data.defaults"
:is_similar_item="false"/>
</div>
</template>
<script>
import Item from './Item'
export default {
props: ["data", "items", "content_categories", "liked"],
data(){
return{
state:{
item_for_expansion: null,
expansion: false
}
}
},
computed:{
assemble_contents_array(){
if(!this.liked){
let contenst_array = []
this.content_categories.sub_categories
.map(type => this.data[this.content_categories.category][type])
.forEach(e => e.forEach(c => contenst_array.push(c)))
return contenst_array
}
}
},
created(){
this.$eventHub.on("expand_item", index => {
if(index === "")
this.state.expansion = false
else
this.state.expansion = true
this.state.item_for_expansion = index
})
},
components:{
Item
}
}
</script>
这是 Item.vue,其中包含 Similar-items.vue:
<template>
<div class="item__wrapper" :class="{'expanded': expand, 'shrink' : !expand && is_expansion}">
<div v-if="expand">
<span class="item__close" @click="expansion">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M23 20.168l-8.185-8.187 8.185-8.174-2.832-2.807-8.182 8.179-8.176-8.179-2.81 2.81 8.186 8.196-8.186 8.184 2.81 2.81 8.203-8.192 8.18 8.192z"/>
</svg>
</span>
<Gallery :main="item_data.img" :images="item_data.images"/>
<Checkout v-if="defaults.shop" :data="item_data" :defaults="defaults" class="right-panel"/>
<Summary v-else :data="item_data" :defaults="defaults" class="right-panel"/>
<div class="item__description">
<p v-if="item_data.type">
{{ defaults.further_reading }}
</p>
<div v-html="item_data.desc">
{{ item_data.desc }}
</div>
</div>
<SimilarItems :data="full_data"/>
</div>
<div v-else>
<svg v-if="!state.liked" @click="add_to_liked" class="item__like" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.653 19.415c-1.162 1.141-2.389 2.331-3.653 3.585-6.43-6.381-12-11.147-12-15.808 0-4.005 3.098-6.192 6.281-6.192 2.197 0 4.434 1.042 5.719 3.248 1.279-2.195 3.521-3.238 5.726-3.238 3.177 0 6.274 2.171 6.274 6.182 0 1.269-.424 2.546-1.154 3.861l-1.483-1.484c.403-.836.637-1.631.637-2.377 0-2.873-2.216-4.182-4.274-4.182-3.257 0-4.976 3.475-5.726 5.021-.747-1.54-2.484-5.03-5.72-5.031-2.315-.001-4.28 1.516-4.28 4.192 0 3.442 4.742 7.85 10 13l2.239-2.191 1.414 1.414zm7.347-5.415h-3v-3h-2v3h-3v2h3v3h2v-3h3v-2z"/></svg>
<svg v-else @click="add_to_liked" class="item__like" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15.582 19.485c-1.141 1.119-2.345 2.287-3.582 3.515-6.43-6.381-12-11.147-12-15.808 0-4.005 3.098-6.192 6.281-6.192 2.197 0 4.434 1.042 5.719 3.248 1.279-2.195 3.521-3.238 5.726-3.238 3.177 0 6.274 2.171 6.274 6.182 0 1.577-.649 3.168-1.742 4.828l-1.447-1.447c.75-1.211 1.189-2.341 1.189-3.381 0-2.873-2.216-4.182-4.274-4.182-3.257 0-4.976 3.475-5.726 5.021-.747-1.54-2.484-5.03-5.72-5.031-2.315-.001-4.28 1.516-4.28 4.192 0 3.442 4.742 7.85 10 13l2.168-2.121 1.414 1.414zm7.418-5.485h-8v2h8v-2z"/></svg>
<div @click="expansion">
<img :src="item_data.img" class="item__image">
<p class="item__title">{{ item_data.name }}</p>
<p class="item__price" v-if="item_data.type">${{ item_data.price }}</p>
</div>
</div>
</div>
</template>
<script>
import Gallery from './utils/gallery'
import Checkout from './utils/checkout'
import Summary from './utils/summary'
import SimilarItems from './utils/similar-items'
export default {
name: "Item",
props: [ "full_data", "item_data", "ind", "expand", "is_expansion", "defaults", "is_similar_item"],
data(){
return{
state:{
get_parent_height: 0,
scrolled_depth: 0,
liked: this.item_data.liked === undefined ? false : this.item_data.liked
}
}
},
methods:{
/*
* Adds item to liked
*/
add_to_liked(){
this.state.liked = !this.state.liked
this.$eventHub.emit("adjust_liked", this.state.liked)
this.$eventHub.emit("add_or_delete_item", this.item_data, this.state.liked, "liked_items")
},
/*
* Expands the item to show detail page
*/
expansion(){
if(this.expand){
this.$eventHub.emit("clear_size")
}
else{
this.state.scrolled_depth = document.querySelector("html").scrollTop
}
this.$eventHub.emit(this.is_similar_item ? "expand_similar_item" : "expand_item", this.expand ? "" : this.ind)
// Scroll to previously scrolled
setTimeout( _ => document.querySelector("html").scrollTop = !this.expand ? this.state.scrolled_depth : 0, 100)
}
},
beforeUpdate(){
this.state.liked = this.item_data.liked === undefined ? false : this.item_data.liked
},
components:{
Gallery,
Checkout,
Summary,
SimilarItems
}
}
</script>
最后,这里是 Similar-items.vue,其中又包含 Item.vue:
<template>
<div class="similar-items">
<Item v-for="(item, ind) in data" :key="'similar-item-'+ind" class="similar-items__item" :data="item" :ind="ind"
:expand="state.item_for_expansion === ind" :is_expansion="state.expansion" :defaults="data.defaults"
:is_similar_item="true" :is_firts="false"/>
</div>
</template>
<script>
import Item from '../Item'
export default {
props: ["data"],
name: "similar-items",
data(){
return{
state:{
item_for_expansion: null,
expansion: false
}
}
},
methods: {
},
created(){
this.$eventHub.on("expand_similar_item", index => {
if(index === "")
this.state.expansion = false
else
this.state.expansion = true
this.state.item_for_expansion = index
})
},
components:{
Item
}
}
</script>
这给了我:
Unknown custom element: <Item> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
所以我尝试添加:
beforeCreate() {
this.$options.components.Item = require('./Item').default
}
到 Contents.vue,我删除了 import Item 和 components: { Item },但我在 Similar-items.vue 中保留了所有内容
这给了我这个错误:Unknown custom element: <Item> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
然后我尝试添加:
beforeCreate() {
this.$options.components.Item = require('../Item')
},
到Similar-items.vue并删除import Item和components: { Item }
这给了我:Failed to mount component: template or render function not defined.
简而言之,Contents.vue 里面有 Item.vue,里面有 Similar-items.vue,这又是里面有 Item.vue,是递归发生的地方。
现在我有点不知所措了。
仅供参考:我已经为 Similar-items.vue 尝试了条件输出 Item.vue,但仍然没有工作。
【问题讨论】:
标签: javascript recursion vue.js