我正在尝试根据传递到父页面的数据来呈现组件。
我正在尝试使用动态组件基于JSON对象 @type 呈现正确的组件,并在URL的(不带扩展名)中获取文件名该对象然后呈现相关组件,并将数据从 Page.vue 传递到呈现的组件。
如果我设置:is =“ content。@ type” (例如),则输出将渲染名称为 Image 和 Video的子组件(删除URL中所有要求文件名的内容)以呈现正确的组件。
这是否可行,或者有更好的方法吗?
数据:
Content: object
Content [Array]
0:Object
@id: "4effb045"
@type: "http://url/images.json"
_meta: Object
name: "TestingImage"
1:Object
@id: "4effb045"
@type: "http://url/video.json"
_meta: Object
name: "TestingVideo"
数据来自CMS,我无法更改数据。
Page.vue
<template>
<div id="page" v-if="content" class="page-wrapper container" :cid="this.$root.cidItem">
<div class="row">
<div class="page__items">
<component v-for="content in content.content" :is="content.@type" :key="content.id"></component>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import Images from "./components/Images"
import Video from "./components/Video"
import TextType from "./components/TextType"
import Card from "./components/Card"
export default {
name: 'page',
props: ['cid'],
components: {
Images,
Video,
TextType,
Card
},
mounted () {
axios({
method: 'GET',
'url': this.$root.contentDeliveryUrl + this.$root.encodedQuery + this.$root.cidItem + this.$root.store
}).then(result => {
// eslint-disable-next-line
this.content = amp.inlineContent(result.data)[0];
console.log(this.content)
}, error => {
console.error(error)
})
},
data () {
return {
content: []
}
}
}
</script>
<style lang="scss">
@import '../node_modules/bootstrap-css-only/css/bootstrap.min.css';
.container {
max-width: 1366px;
}
</style>
子组件示例 Images.vue
<template>
<div class="images-wrapper container">
<div class="row">
<div class="col">
<div class="images">
{{content.imageAltText}}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Images'
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.images-wrapper {
&__image {
}
}
</style>
答案 0 :(得分:2)
如评论中所述,您可以使用v-bind:is
指令在方法中解析URL。您可能现在已经知道了,但这是我的快速尝试。
const content = {
content: [{
'@id': '4effb045',
'@type': 'http://url/images.json',
_meta: {
name: 'TestingImage'
}
}, {
'@id': '4effb046',
'@type': 'http://url/videos.json',
_meta: {
name: 'TestingVideo'
}
}]
}
new Vue({
el: '#app',
data() {
return {
content
}
},
methods: {
extractName(content) {
const [name] = /[^\/]*(?=\.\w+$)/.exec(content['@type']);
return name;
}
},
components: {
Images: {
template: '<img src="https://via.placeholder.com/150x45" />'
},
Videos: {
template: '<div>Some video component</div>'
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component
v-for="content in content.content"
:is="extractName(content)"
:key="content['@id']">
</component>
</div>
顺便说一句,我建议不要使用 HTML保留字作为组件名称(例如您的情况<video>
),因为它可能无法编译。在GitHub上查看此related issue。
[Vue警告]:请勿将内置或保留的HTML元素用作组件ID:对话框
答案 1 :(得分:1)
Your approach is correct. You can use the is
directive to call your components. It is the best way.
As you asked, you need a method in your Page.vue
to parse your @type
.
methods: {
parseType: function(type) {
let typeParts = type.split("/")
let filenameParts = typeParts[typeParts.length - 1].split('.')
let parsedType = filenameParts[0]
return parsedType
}
}
Now you can use this function in your template.
<component v-for="content in content.content" :is="parseType(content.@type)" :key="content.id"></component>