json - 如何使用 JSON 动态更改组件的内容?

标签 json vue.js components vue-router routerlink

我正在使用 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 的名称从数组中显示正确的对象。我不想迭代并在页面上显示所有数组。我只想展示一个项目。

    最佳答案

    快速解决方案:

    项目详情.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 文件。

    路由.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;
    

    工作.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>
    

    项目详情.vue

    <template>
        <div>
            <div>
                <h1>{{ project.title }}</h1>
                <p>{{ project.description }}</p>
            </div>
        </div>
    </template>
    
    <script>
    
        export default {
            name: 'projectDetails',
            props: {
                project: Object,
            },
        };
    </script>
    

    项目链接.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>

    关于json - 如何使用 JSON 动态更改组件的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59312469/

    相关文章:

    javascript - 使用 $http.get 获取嵌套 JSON 中的数组(mongoose 和 nodejs)

    java - JLabel 文本在窄列中而不是展开

    java - Swing GUI 在数据处理期间不会更新

    java - 获取 JPanel 中组件的类型

    twitter-bootstrap - 在 Vuejs 单文件组件中包含 bootstrap.js 外部脚本

    javascript - Nuxt.js-共享持久数据的链接: how the receiver can view the data?

    java - ContentValue 对未从 RAW JSON 插入 SQLite 数据库

    json - 将 'pretty printed' JSON 字符串转换为紧凑格式表示的最简单方法是什么?

    ios - 为 JSON 创建数据模型 - IOS/Objective-C

    javascript - 在 Vuex 中存储 JavaScript 对象并对其进行修改 - 概念