如何使用 JSON 动态更改组件的内容?
How to dynamically change content of component with JSON?
我正在使用 Vue CLI 3 创建我的设计作品集。我网站的架构非常简单。我有一个主页、关于页面、工作页面和几个单独的项目页面:
- 首页
- 关于
- 工作
- 项目
- 项目
- 项目
工作页面包含几个链接,单击这些链接可进入各个项目页面。 工作组件设置如下:
<template>
<div>
<projectLink v-for="data in projectLinkJson" />
</div>
</template>
<script>
import projectLink from '@/components/projectLink.vue'
import json from '@/json/projectLink.json'
export default {
name: 'work',
data(){
return{
projectLinkJson: json
}
},
components: {
projectLink
}
}
</script>
如您所见,我正在导入 JSON 以动态呈现内容。 接下来,可以在下面的代码块中看到 projectLink 组件。 在这个组件中,我将一个参数传递给 <router-link>
,称为 projectName
<template>
<router-link :to="{ name: 'projectDetails', params: { name: projectName }}">
<h1>{{ title }}</h1>
</router-link>
</template>
<script>
export default {
name: 'projectLink',
props: {
title: String,
projectName: String
}
}
</script>
我的 routes.js 文件是这样设置的:
const routes = [
{ path: '/', component: home },
{ path: '/about', component: about },
{ path: '/work', component: work },
{
path: "/work/:name",
name: "projectDetails",
props: true,
component: projectDetails
},
];
我的JSON是这样的:
{
"0": {
"title": "test",
"projectName": "test"
}
}
最后,我的 projectDetails 组件是我遇到此问题的组件:
<template>
<div>
<div
v-for="(data,index) in projectDetailsJson" v-if="index <= 1">
<h1>{{ data.title }}</h1>
<p>{{ data.description }}</p>
</div>
</div>
</template>
<script>
import json from '@/json/projectDetails.json'
export default {
name: 'projectDetails',
data(){
return{
projectDetailsJson: json
}
},
props: {
description: String,
title: String
}
}
</script>
我成功路由到我想要的 URL,即 /project/'name'。我想使用 projectDetails 组件作为我的每个项目页面的框架。但是我如何动态地做到这一点?我想从 JSON 文件中检索数据,并根据传递给 URL 的名称从数组中显示正确的对象。我不想迭代并在页面上显示所有数组。我只想展示一个项目。
Austin,到目前为止做得很好!你非常接近这个工作。有几种不同的方法可以将 JSON 文件中的正确数据解析到 projectDetails
组件中,但我只演示我的首选方法。
首先,您将需要一些 vanilla JS 来搜索您的 JSON 文件并且 return 只搜索您想要的行。我会将此作为一种方法来执行,因为数据不会更改或要求组件重新呈现。所以,在你的道具之后,我会添加这样的东西:
methods: {
findProject(projectName) {
return Object.values(json).find(project => project.title === projectName)
}
}
请注意,这将转到 return 与项目名称匹配的 第一个 项目。如果您的项目具有完全相同的项目名称,这将不起作用。
接下来,您只需更新 projectDetailsJson
的默认值即可调用此方法并传递路由的项目名称。用这样的东西更新数据:
data() {
return {
projectDetailsJson: this.findProject(this.$route.params.name)
}
}
如果这不起作用,我们可能需要在 created
生命周期挂钩中设置 projectDetailsJson
,但请先尝试上面的代码。
如果我没理解错的话,您想保留一个父组件作为您所有页面的布局吗?
如果我一直没理解错的话,一定要用vuerouter的children
属性
https://router.vuejs.org/guide/essentials/nested-routes.html
import layout from 'layout';
const projectRoute = {
path: '/project',
component: Layout, // Load your layout
redirect: '/project/list',
name: 'Project',
children: [
{
path: "list", // here the path become /project/list
component: () => import('@/views/project/List'), // load your components
name: "List of project",
},
{
path: "detail/:id",
component: () => import('@/views/project/Detail'),
name: "Detail of project",
}
],
};
所以你可以创建你的布局并添加你想要的一切,这将在所有子组件上可用,你可以使用 $emit
、$refs
$props
等...
+
您可以创建文件 routes/index.js
并创建文件夹 routes/modules
。在其中,您可以添加 routes/modules/project.js
并加载 routes/index.js
中的模块
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import projectRoutes from "./modules/project";
const routes = [
projectRoutes,
{
// other routes....
},
]
export default new VueRouter({
routes,
mode: 'history',
history: true,
});
@查看同一个文档:https://router.vuejs.org/guide/essentials/nested-routes.html
最后只需要对layout
进行处理,用props
将detail
和[=23=中的值都进行分配];并使用上面描述的过滤方法
希望我已经理解您的要求,如果不是这样,请告诉我,
再见
编辑:这是一个非常好的架构,包含 vue、vuex 和 vuerouter。也许启发你
https://github.com/tuandm/laravue/tree/master/resources/js
快速解决方案:
projectDetails.vue
<template>
<div>
<div>
<h1>{{ projectDetails.title }}</h1>
<p>{{ projectDetails.description }}</p>
</div>
</div>
</template>
<script>
import json from '@/json/projectDetails.json';
export default {
name: 'projectDetails',
props: {
name: String,
},
data() {
return {
projectDetails: Object.values(json).find(project => project.title === this.name),
};
},
};
</script>
我认为更好的解决方案:
我不明白你将项目数据保存在 2 个单独的 JSON 文件中。在编译期间,这两个文件都保存到生成的 JavaScript 文件中。将这些数据保存在 1 个文件中不是更好吗?您不必在一个地方使用所有数据。第二件事,如果您有一个项目列表,那么您可以使用可选段进行路由,并根据该段是否具有值,显示特定项目的列表或数据。然后,您仅将项目数据加载到一个地方,然后选择一个项目时,将其数据传递到该项目的数据渲染组件。您不需要在其他任何地方加载此 JSON 文件。
routes.js
import home from '@/components/home.vue';
import about from '@/components/about.vue';
import work from '@/components/work.vue';
const routes = [
{path: '/', name: 'home', component: home},
{path: '/about', name: 'about', component: about},
{path: '/work/:name?', name: 'work', component: work, props: true},
];
export default routes;
work.vue
<template>
<div>
<project-details v-if="currentProject" :project="currentProject"/>
<projectLink v-else
v-for="project in projects"
v-bind="project"
v-bind:key="project.projectName"
/>
</div>
</template>
<script>
import projectLink from './projectLink';
import projectDetails from './projectDetails';
import json from '@/json/projectLink.json';
export default {
name: 'work',
props: {
name: String,
},
data() {
return {
projects: Object.values(json),
};
},
computed: {
currentProject() {
if (this.name) {
return this.projects.find(
project => project.projectName === this.name,
);
}
},
},
components: {
projectLink,
projectDetails,
},
};
</script>
projectDetails.vue
<template>
<div>
<div>
<h1>{{ project.title }}</h1>
<p>{{ project.description }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'projectDetails',
props: {
project: Object,
},
};
</script>
projectLink.vue(只改了一行)
<router-link v-if="projectName" :to="{ name: 'work', params: { name: projectName }}">
一个完整的工作示例:
Vue.component("navigation", {
template: "#navigation"
});
const Projects = {
template: "#projects",
props: ["projects"]
};
const Project = {
template: "#project",
props: ["project"]
};
const HomePage = {
template: "#home"
};
const AboutPage = {
template: "#about"
};
const WorkPage = {
data() {
return {
projects: [{
slug: "foo",
name: "Foo",
desc: "Fus Ro Dah"
},
{
slug: "bar",
name: "Bar",
desc: "Lorem Ipsum"
}
]
};
},
props: {
slug: String
},
template: "#work",
components: {
Projects,
Project
},
computed: {
currentProject() {
if (this.slug) {
return this.projects.find(project => project.slug === this.slug);
}
}
}
};
const router = new VueRouter({
routes: [{
path: "/",
name: "home",
component: HomePage
},
{
path: "/about",
name: "about",
component: AboutPage
},
{
path: "/work/:slug?",
name: "work",
component: WorkPage,
props: true
}
]
});
new Vue({
router,
template: "#base"
}).$mount("#app");
ul.nav {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
ul.nav>li {
float: left;
}
ul.nav>li>a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
ul.nav>li>a:hover {
background-color: #111;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.3/vue-router.min.js"></script>
<div id="app"></div>
<script type="text/x-template" id="base">
<div id="app">
<div>
<navigation></navigation>
<router-view></router-view>
</div>
</div>
</script>
<script type="text/x-template" id="navigation">
<ul class="nav" id="navigation">
<li>
<router-link :to="{name: 'home'}">Home</router-link>
</li>
<li>
<router-link :to="{name: 'about'}">About</router-link>
</li>
<li>
<router-link :to="{name: 'work'}">Work</router-link>
</li>
</ul>
</script>
<script type="text/x-template" id="home">
<div id="home">This is Home Page</div>
</script>
<script type="text/x-template" id="about">
<div id="about">This is About Page</div>
</script>
<script type="text/x-template" id="work">
<div id="work">
<project v-if="currentProject" :project="currentProject"></project>
<projects v-else :projects="projects"></projects>
</div>
</script>
<script type="text/x-template" id="projects">
<div id="projects">
<ul>
<li v-for="project in projects" :key="project.slug">
<router-link :to="{name: 'work', params:{ slug: project.slug}}">{{project.name}}</router-link>
</li>
</ul>
</div>
</script>
<script type="text/x-template" id="project">
<div id="project">
<h2>{{project.name}}</h2>
<p>{{project.desc}}</p>
</div>
</script>
为了大家,更进一步。您将如何仅显示与当前 URL 匹配的项目链接?因此,如果我有三个不同的 JSON projectTypes:设计、代码、动作。如果 URL 中包含运动,我如何过滤我的 projectLink 组件以仅显示那些具有匹配的 JSON 设计、代码或运动值的组件。本质上我只是想过滤。
我正在使用 Vue CLI 3 创建我的设计作品集。我网站的架构非常简单。我有一个主页、关于页面、工作页面和几个单独的项目页面:
- 首页
- 关于
- 工作
- 项目
- 项目
- 项目
工作页面包含几个链接,单击这些链接可进入各个项目页面。 工作组件设置如下:
<template>
<div>
<projectLink v-for="data in projectLinkJson" />
</div>
</template>
<script>
import projectLink from '@/components/projectLink.vue'
import json from '@/json/projectLink.json'
export default {
name: 'work',
data(){
return{
projectLinkJson: json
}
},
components: {
projectLink
}
}
</script>
如您所见,我正在导入 JSON 以动态呈现内容。 接下来,可以在下面的代码块中看到 projectLink 组件。 在这个组件中,我将一个参数传递给 <router-link>
,称为 projectName
<template>
<router-link :to="{ name: 'projectDetails', params: { name: projectName }}">
<h1>{{ title }}</h1>
</router-link>
</template>
<script>
export default {
name: 'projectLink',
props: {
title: String,
projectName: String
}
}
</script>
我的 routes.js 文件是这样设置的:
const routes = [
{ path: '/', component: home },
{ path: '/about', component: about },
{ path: '/work', component: work },
{
path: "/work/:name",
name: "projectDetails",
props: true,
component: projectDetails
},
];
我的JSON是这样的:
{
"0": {
"title": "test",
"projectName": "test"
}
}
最后,我的 projectDetails 组件是我遇到此问题的组件:
<template>
<div>
<div
v-for="(data,index) in projectDetailsJson" v-if="index <= 1">
<h1>{{ data.title }}</h1>
<p>{{ data.description }}</p>
</div>
</div>
</template>
<script>
import json from '@/json/projectDetails.json'
export default {
name: 'projectDetails',
data(){
return{
projectDetailsJson: json
}
},
props: {
description: String,
title: String
}
}
</script>
我成功路由到我想要的 URL,即 /project/'name'。我想使用 projectDetails 组件作为我的每个项目页面的框架。但是我如何动态地做到这一点?我想从 JSON 文件中检索数据,并根据传递给 URL 的名称从数组中显示正确的对象。我不想迭代并在页面上显示所有数组。我只想展示一个项目。
Austin,到目前为止做得很好!你非常接近这个工作。有几种不同的方法可以将 JSON 文件中的正确数据解析到 projectDetails
组件中,但我只演示我的首选方法。
首先,您将需要一些 vanilla JS 来搜索您的 JSON 文件并且 return 只搜索您想要的行。我会将此作为一种方法来执行,因为数据不会更改或要求组件重新呈现。所以,在你的道具之后,我会添加这样的东西:
methods: {
findProject(projectName) {
return Object.values(json).find(project => project.title === projectName)
}
}
请注意,这将转到 return 与项目名称匹配的 第一个 项目。如果您的项目具有完全相同的项目名称,这将不起作用。
接下来,您只需更新 projectDetailsJson
的默认值即可调用此方法并传递路由的项目名称。用这样的东西更新数据:
data() {
return {
projectDetailsJson: this.findProject(this.$route.params.name)
}
}
如果这不起作用,我们可能需要在 created
生命周期挂钩中设置 projectDetailsJson
,但请先尝试上面的代码。
如果我没理解错的话,您想保留一个父组件作为您所有页面的布局吗?
如果我一直没理解错的话,一定要用vuerouter的children
属性
https://router.vuejs.org/guide/essentials/nested-routes.html
import layout from 'layout';
const projectRoute = {
path: '/project',
component: Layout, // Load your layout
redirect: '/project/list',
name: 'Project',
children: [
{
path: "list", // here the path become /project/list
component: () => import('@/views/project/List'), // load your components
name: "List of project",
},
{
path: "detail/:id",
component: () => import('@/views/project/Detail'),
name: "Detail of project",
}
],
};
所以你可以创建你的布局并添加你想要的一切,这将在所有子组件上可用,你可以使用 $emit
、$refs
$props
等...
+
您可以创建文件 routes/index.js
并创建文件夹 routes/modules
。在其中,您可以添加 routes/modules/project.js
并加载 routes/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import projectRoutes from "./modules/project";
const routes = [
projectRoutes,
{
// other routes....
},
]
export default new VueRouter({
routes,
mode: 'history',
history: true,
});
@查看同一个文档:https://router.vuejs.org/guide/essentials/nested-routes.html
最后只需要对layout
进行处理,用props
将detail
和[=23=中的值都进行分配];并使用上面描述的过滤方法
希望我已经理解您的要求,如果不是这样,请告诉我,
再见
编辑:这是一个非常好的架构,包含 vue、vuex 和 vuerouter。也许启发你 https://github.com/tuandm/laravue/tree/master/resources/js
快速解决方案:
projectDetails.vue
<template>
<div>
<div>
<h1>{{ projectDetails.title }}</h1>
<p>{{ projectDetails.description }}</p>
</div>
</div>
</template>
<script>
import json from '@/json/projectDetails.json';
export default {
name: 'projectDetails',
props: {
name: String,
},
data() {
return {
projectDetails: Object.values(json).find(project => project.title === this.name),
};
},
};
</script>
我认为更好的解决方案:
我不明白你将项目数据保存在 2 个单独的 JSON 文件中。在编译期间,这两个文件都保存到生成的 JavaScript 文件中。将这些数据保存在 1 个文件中不是更好吗?您不必在一个地方使用所有数据。第二件事,如果您有一个项目列表,那么您可以使用可选段进行路由,并根据该段是否具有值,显示特定项目的列表或数据。然后,您仅将项目数据加载到一个地方,然后选择一个项目时,将其数据传递到该项目的数据渲染组件。您不需要在其他任何地方加载此 JSON 文件。
routes.js
import home from '@/components/home.vue';
import about from '@/components/about.vue';
import work from '@/components/work.vue';
const routes = [
{path: '/', name: 'home', component: home},
{path: '/about', name: 'about', component: about},
{path: '/work/:name?', name: 'work', component: work, props: true},
];
export default routes;
work.vue
<template>
<div>
<project-details v-if="currentProject" :project="currentProject"/>
<projectLink v-else
v-for="project in projects"
v-bind="project"
v-bind:key="project.projectName"
/>
</div>
</template>
<script>
import projectLink from './projectLink';
import projectDetails from './projectDetails';
import json from '@/json/projectLink.json';
export default {
name: 'work',
props: {
name: String,
},
data() {
return {
projects: Object.values(json),
};
},
computed: {
currentProject() {
if (this.name) {
return this.projects.find(
project => project.projectName === this.name,
);
}
},
},
components: {
projectLink,
projectDetails,
},
};
</script>
projectDetails.vue
<template>
<div>
<div>
<h1>{{ project.title }}</h1>
<p>{{ project.description }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'projectDetails',
props: {
project: Object,
},
};
</script>
projectLink.vue(只改了一行)
<router-link v-if="projectName" :to="{ name: 'work', params: { name: projectName }}">
一个完整的工作示例:
Vue.component("navigation", {
template: "#navigation"
});
const Projects = {
template: "#projects",
props: ["projects"]
};
const Project = {
template: "#project",
props: ["project"]
};
const HomePage = {
template: "#home"
};
const AboutPage = {
template: "#about"
};
const WorkPage = {
data() {
return {
projects: [{
slug: "foo",
name: "Foo",
desc: "Fus Ro Dah"
},
{
slug: "bar",
name: "Bar",
desc: "Lorem Ipsum"
}
]
};
},
props: {
slug: String
},
template: "#work",
components: {
Projects,
Project
},
computed: {
currentProject() {
if (this.slug) {
return this.projects.find(project => project.slug === this.slug);
}
}
}
};
const router = new VueRouter({
routes: [{
path: "/",
name: "home",
component: HomePage
},
{
path: "/about",
name: "about",
component: AboutPage
},
{
path: "/work/:slug?",
name: "work",
component: WorkPage,
props: true
}
]
});
new Vue({
router,
template: "#base"
}).$mount("#app");
ul.nav {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
ul.nav>li {
float: left;
}
ul.nav>li>a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
ul.nav>li>a:hover {
background-color: #111;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.3/vue-router.min.js"></script>
<div id="app"></div>
<script type="text/x-template" id="base">
<div id="app">
<div>
<navigation></navigation>
<router-view></router-view>
</div>
</div>
</script>
<script type="text/x-template" id="navigation">
<ul class="nav" id="navigation">
<li>
<router-link :to="{name: 'home'}">Home</router-link>
</li>
<li>
<router-link :to="{name: 'about'}">About</router-link>
</li>
<li>
<router-link :to="{name: 'work'}">Work</router-link>
</li>
</ul>
</script>
<script type="text/x-template" id="home">
<div id="home">This is Home Page</div>
</script>
<script type="text/x-template" id="about">
<div id="about">This is About Page</div>
</script>
<script type="text/x-template" id="work">
<div id="work">
<project v-if="currentProject" :project="currentProject"></project>
<projects v-else :projects="projects"></projects>
</div>
</script>
<script type="text/x-template" id="projects">
<div id="projects">
<ul>
<li v-for="project in projects" :key="project.slug">
<router-link :to="{name: 'work', params:{ slug: project.slug}}">{{project.name}}</router-link>
</li>
</ul>
</div>
</script>
<script type="text/x-template" id="project">
<div id="project">
<h2>{{project.name}}</h2>
<p>{{project.desc}}</p>
</div>
</script>
为了大家,更进一步。您将如何仅显示与当前 URL 匹配的项目链接?因此,如果我有三个不同的 JSON projectTypes:设计、代码、动作。如果 URL 中包含运动,我如何过滤我的 projectLink 组件以仅显示那些具有匹配的 JSON 设计、代码或运动值的组件。本质上我只是想过滤。