Как сделать v-for выпадающий текст с функцией? - PullRequest
1 голос
/ 06 мая 2020

Я хочу сделать исправление текста, где я могу щелкнуть неправильные слова и выбрать исправление из списка (что-то вроде того, что делает Grammarly).

Этот простой пример должен помочь вам понять идею. Предположим, у меня есть список объектов, возвращаемых с сервера:

data: {
 objects: [
  {
   word: "This",
   val:  0.1,
   corrections: {"that", "Those"}
  },
  {
   word: "kat",
   val:  0.9,
   corrections: {"cat", "cats", "dogs", "animals"}
  }
 ]
}

Теперь я хочу написать v-for, который будет:

  • Отображать все слова, как если бы они были обычным текстом (например, "This kat")
  • Для слов с val < 0.5 просто отображать word
  • Для слов с val >= 0.5 отображать word с красным подчеркивание, а также возможность щелкнуть и увидеть раскрывающийся список со всеми corrections
  • , чтобы изменить значение объекта word после выбора параметра в раскрывающемся списке.

Минимально воспроизводимый (не рабочий) пример:

Vue.component('post-list', {
  data: function() {
    return {
        objects: [{
            word: "This",
            val: 0.1,
            corrections: [
              "that",
              "Those"
            ]},
          {
            word: "kat",
            val: 0.9,
            corrections: [
              "cat",
              "cats",
              "dogs",
              "animals"
            ]}
        ]
    }
  },

});

new Vue({
  el: '#vue-app'
});
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="vue-app" class="container">
  <post-list inline-template>
    <div>
      <template class="post" v-for="object in objects">
        {{ object.word }}
      </template>
    </div>
  </post-list>
</div>

1 Ответ

1 голос
/ 06 мая 2020

То есть вы просите нас создать для вас копию "Grammarly" примерно за 10 минут?

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

Демо https://codepen.io/aQW5z9fe/pen/MWaQjdX

Кроме того, я бы переместите метод getFormattedData() на сервер, чтобы вы получали отформатированные данные со свойствами underlined вместе с val и corrections вместо их повторного вычисления на стороне клиента.

<v-menu 
  v-model="correctionsListIsVisible"
>
  <v-list dense>
    <v-list-item
      v-for="(correction, index) in correctionsListItems"
      :key="index"
      @click="applyCorrection(correction)"          
    >
      <v-list-item-content>
        <v-list-item-title>
          {{correction}}
        </v-list-item-title>
      </v-list-item-content>
    </v-list-item>
  </v-list>
</v-menu>

<div class="flex">
  <div v-for="(object, index) in getFormattedData" class="flex">
    <div
       @click="toggleCorrectionsList(object)"
       :class="{'underlined': object.underlined}"
       id="word"
    >{{ object.word }} 
    </div>
    <div v-if="addSpace(index)">&nbsp;</div>
  </div>
</div>
data () {
  return {
    correctionsListIsVisible: false,
    correctionsListItems: [],
    activeObject: {},
    objects: [
      {
         word: "This",
         val: 0.1,
         corrections: ["that", "Those"]
      },
      {
         word: "kat",
         val: 0.9,
         corrections: ["cat", "cats", "dogs", "animals"]
      },
      {
         word: "is",
         val: 0.1,
         corrections: []
      },
      {
         word: "cute",
         val: 0.2,
         corrections: []
      },
    ]
  }
},
computed: {
  getFormattedData() {
    let result = []
    for (const item of this.objects) {
      let object = {}
      if (item.val < 0.5) {
        object.word = item.word
        object.underlined = false
        object.corrections = []
      }
      else if (item.val >= 0.5) {
        object.word = item.word
        object.underlined = true
        object.corrections = item.corrections
      }

      result.push(object)
    }
    return result
  }
},
methods: {
  addSpace (index) {
    return index !== (this.getFormattedData.length - 1)
  },
  toggleCorrectionsList (object) {
    if (object.underlined) {
      this.correctionsListItems = object.corrections
      this.activeObject = object
      this.correctionsListIsVisible = true
    }
    else {
      this.activeObject = {}
    }
  },
  applyCorrection (correction) {
    this.activeObject.word = correction
    this.activeObject.underlined = false
  }
}
...