Перебрать динамический массив в Vue.js, а затем добавить каждый компонент объекта в div в отдельном компоненте на основе соответствующего значения? - PullRequest
0 голосов
/ 12 июня 2019

Я пытаюсь создать приложение Vue, в котором перечислены офисы компании в зависимости от региона. У меня есть основной домашний вид, офисные компоненты и офисные элементы. Я использую v-for в компоненте office для циклического просмотра элементов office и их отображения. Это работает, чтобы перечислить их всех. Тем не менее, мне нужно отсортировать элементы офиса в отдельные элементы div на основе значения «Регион». Есть 5 регионов. Я не могу понять, как пройти через них на основе этого единственного значения.

Я знаю, как импортировать компоненты друг в друга, но я пытаюсь перебрать все элементы office внутри компонента office. Я предполагаю сделать цикл внутри цикла, но нужен ли мне другой компонент, который мне не хватает?

компонент офисного предмета:

<div class="office" :class="office.Region">
  <p>{{office.Name}}</p>
  <p>{{office.Address}}</p>
  <p>{{office.Country}}</p>
  <p>{{office.Region}}</p>
  <p>{{office.Email}}</p>
  <p>{{office.Phone}}</p>
</div>

офисная составляющая:

<div>
  <div v-for="office in offices" :key="office.name">
    <div class="office-container global" v-if="office.Region === 'Global'">
      <ul>
        <li><OfficeItem v-bind:office="office"/></li>
      </ul>
    </div>
    <div class="office-container north" v-if="office.Region === 'North America'">
      <ul>
        <li><OfficeItem v-bind:office="office"/></li>
      </ul>
    </div>
    <div class="office-container europe" v-if="office.Region === 'Europe, Middle East and Africa'">
      <ul>
        <li><OfficeItem v-bind:office="office"/></li>
      </ul>
    </div>         
    <div class="office-container asia" v-if="office.Region === 'Asia Pacific'">
      <ul>
        <li><OfficeItem v-bind:office="office"/></li>
      </ul>
    </div>
    <div class="office-container latin" v-if="office.Region === 'Latin America'">
      <ul>
        <li><OfficeItem v-bind:office="office"/></li>
      </ul>
    </div>
  </div>
</div>

жестко закодированный массив объектов:

offices: [
    {
      Name: "Corporate Headquarters",
      Address: "Suite 500, 698 West 10000 South, South Jordan, Utah 84095",
      Country: "USA",
      Region: "Global",
      Email: "contact@ivanti.com",
      Phone: "+1-888-253-6201"
    },
    {
      Name: "EMEA Headquarters",
      Address: "First Floor Europa House, Harcourt Street Dublin 2, D02 WR20",
      Country: "Ireland",
      Region: "Europe, Middle East and Africa",
      Email: "contact@ivanti.me",
      Phone: "+ 353 1 411 7100"
    },
    {
      Name: "India",
      Address: "Bagmane Tech Park, Unit No. 4A, Level 2 , Bangalore",
      Country: "India",
      Region: "Asia Pacific",
      Email: "contact@ivanti.com",
      Phone: ""
    },
    {
      Name: "Brazil",
      Address: "Borges de Figueiredo, 303 - 4th floor, Bairro Mooca, São Paulo, SP 03110-010",
      Country: "Brazil",
      Region: "Latin America",
      Email: "contact-brazil@ivanti.com",
      Phone: "+55 11 9 8136 0343"
    },
    {
      Name: "United States (Seattle)",
      Address: "1011 Western Ave SW #700, Seattle, WA 98104",
      Country: "United States",
      Region: "North America",
      Email: "contact@ivanti.com",
      Phone: "+1-206-274-4280"
    }
]

Я хочу, чтобы было только 5 делений office-container со списком соответствующих офисов в каждом. тем не менее, я получаю несколько офисных контейнеров (то есть два дива в Северной Америке) и несколько пустых дивов внутри этих

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Похоже, единственное, что меняется в вашем шаблоне, это классы, окружающие OfficeItem Компонент

Чтобы сохранить ваш код менее СУХИМ, попробуйте применить эту условную логику в OfficeItem Компонент, как показано ниже.

// OfficeItem.vue
<template>
  <li :class="['office-container', getRegionClass(office.Region)]">{{office.Region}}</li>
</template>

<script>
const regional_classes = {
  A: 'class_a and-another-A-class',
  B: 'class_b and-another-B-class',
  C: 'class_c and-another-C-class',
  D: 'class_d and-another-D-class',
  Z: 'class_z and-another-Z-class'
}

export default {
  name: "OfficeItem",
  props: {
    office: Object
  },
  methods: {
    getRegionClass(region) {
      return regional_classes[region] || ''
    }
  }
};
</script>
В качестве альтернативы, есть оператор switch , который принимает Region и возвращает строку любого случая, встреченного в пределах switch.

в этом Сценарии, хотя я чувствую, что объект regional_class более читабелен / удобен в обслуживании.

А в вашем Offices компоненте просто передайте объект officeна ваш Officeitem как показано ниже

// Offices.vue
<template>
  <div>
    <ul :key="`${regionName}_${index}`" v-for="(region, regionName, index) in officesByRegion">
      <h1>Region {{regionName}}</h1>
      <OfficeItem v-for="office in region" :key="office.Region" :office="office"/>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Offices",
  data() {
    return {
      offices: [
        { Region: "A" },
        { Region: "B" },
        { Region: "C" },
        { Region: "D" },
        { Region: "Z" },
        { Region: "A" },
        { Region: "B" },
        { Region: "A" },
        { Region: "B" },
        { Region: "A" },
        { Region: "Z" },
        { Region: "C" },
        { Region: "D" },
        { Region: "E" }
      ]
    };
  },
  computed: {
    officesByRegion() {
      const obj = {};
      this.offices.forEach(o => {
        if (o.Region in obj) obj[o.Region].push(o);
        else obj[o.Region] = [o];
      });
      return obj;
    }
  }
};
</script>

Надеюсь, это поможет.Или, по крайней мере, пролить свет на динамическое применение класса CSS.: -)

0 голосов
/ 12 июня 2019

[...new Set(this.offices.map(o => o.Region))] дает вам список всех ваших регионов.

Вы можете просмотреть этот список и просмотреть офисы, имеющие этот регион, используя метод фильтрации:

officesOfRegion(region) {
  return this.offices.filter(o => o.Region === region)
},

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#hook',
  template: '#appTemplate',
  data: ({
    offices: [{
        Name: "Corporate Headquarters",
        Address: "Suite 500, 698 West 10000 South, South Jordan, Utah 84095",
        Country: "USA",
        Region: "Global",
        Email: "contact@ivanti.com",
        Phone: "+1-888-253-6201"
      },
      {
        Name: "EMEA Headquarters",
        Address: "First Floor Europa House, Harcourt Street Dublin 2, D02 WR20",
        Country: "Ireland",
        Region: "Europe, Middle East and Africa",
        Email: "contact@ivanti.me",
        Phone: "+ 353 1 411 7100"
      },
      {
        Name: "India",
        Address: "Bagmane Tech Park, Unit No. 4A, Level 2 , Bangalore",
        Country: "India",
        Region: "Asia Pacific",
        Email: "contact@ivanti.com",
        Phone: ""
      },
      {
        Name: "Brazil",
        Address: "Borges de Figueiredo, 303 - 4th floor, Bairro Mooca, São Paulo, SP 03110-010",
        Country: "Brazil",
        Region: "Latin America",
        Email: "contact-brazil@ivanti.com",
        Phone: "+55 11 9 8136 0343"
      },
      {
        Name: "United States (Seattle)",
        Address: "1011 Western Ave SW #700, Seattle, WA 98104",
        Country: "United States",
        Region: "North America",
        Email: "contact@ivanti.com",
        Phone: "+1-206-274-4280"
      }
    ]
  }),
  computed: {
    regions() {
      return [...new Set(this.offices.map(o => o.Region))]
    }
  },
  methods: {
    officesOfRegion(region) {
      return this.offices.filter(o => o.Region === region)
    },
    displayJson(o) {
      return JSON.stringify(o, null, 2);
    }
  },

})


  
    
      
      
        
          

Я не смотрел на вашу разметку, поскольку она не имеет значения.Вы можете использовать любую разметку, когда захотите, после того, как данные правильно отсортированы.

Вот с вашей разметкой:

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#hook',
  template: '#appTemplate',
  data: ({
    offices: [{
        Name: "Corporate Headquarters",
        Address: "Suite 500, 698 West 10000 South, South Jordan, Utah 84095",
        Country: "USA",
        Region: "Global",
        Email: "contact@ivanti.com",
        Phone: "+1-888-253-6201"
      },
      {
        Name: "EMEA Headquarters",
        Address: "First Floor Europa House, Harcourt Street Dublin 2, D02 WR20",
        Country: "Ireland",
        Region: "Europe, Middle East and Africa",
        Email: "contact@ivanti.me",
        Phone: "+ 353 1 411 7100"
      },
      {
        Name: "India",
        Address: "Bagmane Tech Park, Unit No. 4A, Level 2 , Bangalore",
        Country: "India",
        Region: "Asia Pacific",
        Email: "contact@ivanti.com",
        Phone: ""
      },
      {
        Name: "Brazil",
        Address: "Borges de Figueiredo, 303 - 4th floor, Bairro Mooca, São Paulo, SP 03110-010",
        Country: "Brazil",
        Region: "Latin America",
        Email: "contact-brazil@ivanti.com",
        Phone: "+55 11 9 8136 0343"
      },
      {
        Name: "United States (Seattle)",
        Address: "1011 Western Ave SW #700, Seattle, WA 98104",
        Country: "United States",
        Region: "North America",
        Email: "contact@ivanti.com",
        Phone: "+1-206-274-4280"
      }
    ]
  }),
  computed: {
    regions() {
      return [...new Set(this.offices.map(o => o.Region))]
    }
  },
  methods: {
    officesOfRegion(region) {
      return this.offices.filter(o => o.Region === region)
    },
    propsOf(o) {
      return Object.keys(o);
    }
  },
  
})
.office p {
  display: flex;
}
.office p strong {
  width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type="text/template" id="appTemplate">
  <div id="app">
    <div class="region" v-for="region in regions" :key="region">
      <h3>{{region}}</h3>
      <div v-for="(office, i) in officesOfRegion(region)" :key="i" class="office">
        <p v-for="prop in propsOf(office)"><strong>{{prop}}:</strong> {{office[prop]}}</p>
      </div>
    </div>
  </div>
</script>
<div id="hook"></div>
...