代码之家  ›  专栏  ›  技术社区  ›  Adam Robertson

使用Vue访问嵌套JSON

  •  1
  • Adam Robertson  · 技术社区  · 6 年前

    我正在尝试使用Vue访问数组中的嵌套JSON以进行基本搜索。每个学校都被包装在一个“hit”数组中,所以它不返回每个学校的数据,而是认为只有一个“hit”结果。我确定我只需要为每个学校实例添加hit,但我不确定如何添加。谢谢你的帮助。

    我的主应用程序文件:

    <template>
        <div class="app search">
            <!-- Search header -->
            <header id="searchHeader" class="search--header py-2 py-md-4">
                <div class="container">
                    <div class="input-group">
                        <!-- Type filter -->
                        <TypeFilter v-model="type"/>
    
                        <!-- Location filter -->
                        <!--<LocationFilter />-->
    
                        <!-- Search box -->
                        <SearchBox v-model="searchTerm"/>
    
                        <!-- More filters -->
                        <!--<div class="dropdown checkbox-dropdown mx-2">
                            <button class="btn btn-lg btn-white py-3 px-4 dropdown-toggle" type="button" id="dropdownMenuButtonFilters" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">More Filters</button>
                            <div class="dropdown-menu" aria-labelledby="dropdownMenuButtonFilters">
                            </div>
                        </div>-->
    
                        <!-- Search button -->
                        <button v-on:click="searchSubmit(searchTerm)" class="btn btn-lg btn-white ml-2 px-4 search-submit">Search</button>
                    </div>
    
                    <!-- Active filters (hidden for v0) -->
                    <!--<div class="search--header--filters mt-3">
                        <span class="badge">Filter</span>
                        <span class="badge">Filter</span>
                        <span class="badge">Filter</span>
                    </div>-->
                </div>
            </header>
    
            <!-- Main results -->
            <div class="container">
                {{ message }}
    
                <!-- Result count and show/sort -->
                <ResultCount v-model="page" :items="schools.length" :perPage="10"/>
    
                <!-- Results -->
                <SchoolList :schools="pageOfSchools"/>
    
                <!-- Pagination -->
                <Pagination v-model="page" :items="schools.length" :perPage="10"/>
            </div>
        </div>
    </template>
    
    <script>
        import SchoolList from './SchoolList'
        import ResultCount from './ResultCount'
        import Pagination from './Pagination'
        import SearchBox from './SearchBox'
        import TypeFilter from "./TypeFilter";
        import LocationFilter from "./LocationFilter";
        import getArraySection from '../utilities/get-array-section'
        //import {schools as schoolData} from '../data'
    
        export default {
            name: 'app',
            components: {SchoolList, ResultCount, Pagination, SearchBox, TypeFilter, LocationFilter},
            data: () => ({
                searchTerm: '',
                type: '',
                //schools: [],
                schools: [
                    {
                        "hit": [{
                            "title": "State Peter Pan Institute",
                        }, {
                            "title": "State Flatland University",
                        }, {
                            "title": "State Applewood Halls of Ivy",
                        }]
                    }
                ],
                page: 1,
                message: '{}'
            }),
            computed: {
                pageOfSchools: function () {
                    return getArraySection(this.schools, this.page, 10)
                }
            },
            watch: {
                /*searchTerm: function () {
                    this.filterSchools()
                },
                type: function () {
                    this.filterSchools()
                }*/
            },
            methods: {    
                filterSchools: function () {
                    const searchTerm = this.searchTerm.toLowerCase()
                    const type = this.type
                    let result = schoolData
    
                    if (searchTerm) {
                        result = result.filter(school => {
                            return (
                                school.title.toLowerCase().search(searchTerm) >= 0 ||
                                school.location.toLowerCase().search(searchTerm) >= 0
                            )
                        })
                    }
    
                    if (type) {
                        result = result.filter(school => school.type.indexOf(type) >= 0)
                    }
    
                    this.schools = result
                    this.page = 1
                }
            },
            created: function () {
                this.filterSchools()
            }
        }
    </script>
    

    我的学校名单部分:

    <template>
        <Transition name="swap" mode="out-in">
            <div class="school-list" :key="schools">
                <div class="row">
                    <div class="col-md-8 search--results">
                        <School class="school row justify-content-between search--results--card my-2 pt-2 pb-3 border-bottom" v-for="school in schools" :item="school" :key="school"/>
                    </div>
    
                    <div class="col-md-4 mt-4 pl-md-6 search--results--featured">
                        <FeaturedList />
                    </div>
                </div>
            </div>
        </Transition>
    </template>
    
    <script>
        import School from './School'
        import FeaturedList from './FeaturedList'
    
        export default {
            name: 'school-list',
            components: {School, FeaturedList},
            props: ['schools']
        }
    </script>
    
    <style scoped>
        .swap-enter-active, .swap-leave-active {
            transition: opacity 0.2s ease-in-out;
        }
    
        .swap-enter, .swap-leave-active {
            opacity: 0;
        }
    
        .swap-enter {
            opacity: 1;
        }
        .swap-leave-to {
            opacity: 0;
        }
    </style>
    

    我的学校部分:

    <template>
        <div>
            <div class="col-9 col-md-auto d-flex align-items-center card-body">
                <img v-bind:src="item.logo" class="logo mr-2 mr-md-4 p-2 bg-white rounded-circle">
                <div>
                    <h5 class="mb-0"><a :href="item.url" class="text-dark">{{ item.title }}</a></h5>
                    <p class="mb-0">{{ item.location }}</p>
                    <TypeLabel class="badge type-label mt-2" v-for="type in item.type" :type="type" :key="type"/>
                    <span class="badge badge-yellow mt-2">Featured</span>
                </div>
            </div>
            <div class="col-3 col-md-auto text-right">
                <button type="button" class="btn btn-link d-inline-flex px-2 save"><i></i></button>
                <button type="button" class="btn btn-link d-inline-flex px-2 share"><i></i></button>
                <a data-placement="top" data-toggle="popoverMoreInfo" data-title="Get More Info" data-container="body" data-html="true" href="#" id="login" class="btn btn-outline-light d-none d-md-inline-block ml-3">Get More Info</a>
                <!-- Get More Info Popover -->
                <div id="popover-content" class="d-none more-info">
                    <form>
                        <div class="form-group mb-2 has-float-label">
                            <input class="form-control" id="your-name" type="text" placeholder="Your name"
                                   aria-label="Your name" aria-describedby="your-name"/>
                            <label for="your-name">Your name</label>
                        </div>
    
                        <div class="form-group mb-2 has-float-label">
                            <input class="form-control" id="your-email" type="email" placeholder="Your email"
                                   aria-label="Your email" aria-describedby="your-email"/>
                            <label for="your-email">Your email</label>
                        </div>
    
                        <div class="form-group mb-2 has-float-label">
                            <input class="form-control" id="your-phone" type="tel" placeholder="Your phone"
                                   aria-label="Your phone" aria-describedby="your-phone"/>
                            <label for="your-phone">Your phone</label>
                        </div>
    
                        <button type="submit" class="btn btn-primary w-100">Request More Info</button>
                    </form>
                </div>
    
            </div>
        </div>
    </template>
    
    <script>
        import TypeLabel from './TypeLabel'
    
        let parser = document.createElement('a')
    
        export default {
            name: 'school',
            props: ['item'],
            components: {TypeLabel},
            methods: {
                domainOf: url => ((parser.href = url), parser.hostname.replace(/^www\./, ''))
            }
        }
    </script>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Zysce myrtle303    6 年前

    要访问每个学校的名称,您应该这样访问:

    const hit = this.schools[0].hit;
    

    然后迭代属性hit

    hit.forEach(function(el) {
      console.log(el.title);
    });
    

    要做到这一点,可能您应该将计算属性中的属性学校展平,以便以后更容易访问。

    computed: {
     // other properties ...
     flattenedSchools: function () {
          const schools = [];
          if (this.schools && this.schools.length) {
              // up to you to check if hit exist and has values
              this.schools[0].hit.forEach(function(el) {
                schools.push((el.title);
              });
          }
          return schools;
       },
    },
    

    要访问扁平化学校,只需使用this.flattendschools并对其进行迭代。