Chcemy tworzyć pole wejściowe , które oferuje sugestie dotyczące zakończeń , jak jaka Vscode "Intellisense" (myślę) lub jak DMenu robi.

Używam VUE JS i kodu jak:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label>Lookup German word:
<input type="text" v-model.trim="word" v-on:keyup="signalChange" v-on:change="signalChange" list="words" autofocus>
</label>
<datalist id="words">
<option v-for="w in words">${w}</option>
</datalist>
Query: ${query} Results: ${words.length} Time taken: ${fetchtime} ms
</div>
<script>
    const app = new Vue({
        el:'#app',
        delimiters: ['${', '}'],
        data() {
            return {
                word:'',
                query:'',
                words:[],
                fetchtime: 0
            }
        },
        methods: {
            async signalChange(){
                console.log(this.word)
                if (this.word.length > 2 && this.word.slice(0,3).toLowerCase() != this.query) {
                    this.query = this.word.slice(0,3).toLowerCase()
                    let time1 = performance.now()
                    let response = await fetch('https://dfts.dabase.com/?q=' + this.query)
                    this.words = await response.json()
                    let time2 = performance.now()
                    this.fetchtime = time2 - time1
                }
            }
        }
    })
</script>

Gdzie signalChange pobierałby kilka wyników zakończenia.

Jednak doświadczenie użytkownika (UX) jest intuicyjne. Musisz wstać, aby zobaczyć zakończenia po wpisaniu trzech znaków takich jak "dla". Mam Próbowałem kilku przeglądarek, a doświadczenie Vuejs jest ładne ubogi przez planszę. Jednak to działa OK bez Vuejs.

Czy brakuje ci czegoś? DEMO: https://dfts.dabase.com/

Być może muszę stworzyć własny dropdown HTML w Vuejs, co dzieje się w HTTPS: //dl.dabase. COM /? Poliple = true?

2
hendry 14 marzec 2021, 09:04

1 odpowiedź

Najlepsza odpowiedź

Wydajność problemu na Chrome

Istnieje problem dotyczący Chrome zgłoszony tutaj: -Input-datalist">Czy to błąd wydajności UI Chrome związany z wejściem + Datalist?

Stosowanie rozwiązania do kodu VUE działa dobrze dla Chrome:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label>Lookup German word:
<input type="text" v-model.trim="word" v-on:keyup="signalChange" v-on:change="signalChange" list="words" autofocus>
</label>
<datalist v-bind:id="listId">
<option v-for="w in words">${w}</option>
</datalist>
Query: ${query} Results: ${words.length} Time taken: ${fetchtime} ms
</div>
<script>
    const app = new Vue({
        el:'#app',
        delimiters: ['${', '}'],
        data() {
            return {
                listId:'words',
                word:'',
                query:'',
                words:[],
                fetchtime: 0
            }
        },
        methods: {
            async signalChange(){
                console.log(this.word)
                if (this.word.length > 2 && this.word.slice(0,3).toLowerCase() != this.query) {
                    this.query = this.word.slice(0,3).toLowerCase()
                    let time1 = performance.now()
                    let response = await fetch('https://dfts.dabase.com/?q=' + this.query)
                    const words = await response.json()
                    let time2 = performance.now()                    
                    this.fetchtime = time2 - time1
                    this.listId="";
                    this.words = words
                    setTimeout(()=>this.listId="words");
                }
            }
        }
    })
</script>

Firefox nadal nie działa poprawnie, więc odnosząc się do mojej oryginalnej odpowiedzi poniżej:

Oryginalna odpowiedź:

Zauważyłem duży opóźnienie podczas prowadzenia swojego kodu, więc zacząłem bawić się trochę i wydaje się, że problem generuje opcje listy danych dla dużej ilości elementów.

Ponieważ tak można wyświetlić tylko kilka wyników, co można zrobić, jest ograniczenie ilości opcji renderowanych, a następnie użyć filtra, aby pokazać dalsze wyniki, gdy dodano więcej znaków.

Działa to dobrze na chromie, ale wciąż nie zawodzi w Firefoksie (choć jest znany problem w Firefoksie: HTTPS : //bugzilla.mozilla.org/show_bug.cgi? Id = 1474137)

Sprawdź to:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <label>Lookup German word:
<input type="text" v-model="word" v-on:keyup="signalChange"  list="words" autofocus>
</label>
  <datalist id="words">
<option v-for="w in words">${w}</option>
</datalist> Query: ${query} Results: ${fetchedWords.length} Time taken: ${fetchtime} ms
</div>
<script>
  new Vue({
    el: '#app',
    delimiters: ['${', '}'],
    data() {
      return {
        word: '',
        query: '',
        words: [],
        fetchedWords: [],
        fetchtime: 0
      }
    },
    methods: {
      async signalChange() {
        if (this.word.length > 2 && this.word.slice(0, 3).toLowerCase() != this.query) {
          this.query = this.word.slice(0, 3).toLowerCase();
          let response = await fetch('https://dfts.dabase.com/?q=' + this.query);
          this.fetchedWords = (await response.json());
          this.words = this.fetchedWords.slice(0, 10);
        } else if (this.word.includes(this.query)) {
          this.words = this.fetchedWords.filter(w => w.startsWith(this.word)).slice(0, 10);
        } else {
          this.words = [];
        }
      }
    }


  })
</script>

Edytuj: Czy to tylko problem związany z Vue? Nie.

Stworzyłem równoważną implementację w Pure JS + HTML. Wykorzystał wydajny sposób, aby zminimalizować czas tworzenia Domu (stworzony fragment i tylko dołączyć go raz do domu zgodnie z Jak wypełnić dużą datalistę (~ 2000 pozycji) z słownika), ale nadal trwa długo trwa długo. Kiedy już to działa dobrze, ale na mojej maszynie zajęło prawie minutę po wejściu "było", aby stać się reagującą.

Oto wdrożenie w Pure JS + HTML:

let word = '';
let query = '';
const input = document.querySelector('input');
const combo = document.getElementById('words');
input.onkeyup = function signalChange(e) {
  word = e.target.value;
  console.log(word)
  if (word.length > 2 && word.slice(0, 3).toLowerCase() != query) {
    query = word.slice(0, 3).toLowerCase();
    fetch('https://dfts.dabase.com/?q=' + query)
      .then(response => response.json())
      .then(words => {
        const frag = document.createDocumentFragment();
        words.forEach(w => {
          var option = document.createElement("OPTION");
          option.textContent = w;
          option.value = w;
          frag.appendChild(option);
        })
        combo.appendChild(frag);
      });
  }
}
<div id="app">
  <label>Lookup German word:
    <input type="text" list="words" autofocus>
  </label>
  <datalist id="words"></datalist>
</div>

Tak więc, biorąc to pod uwagę i ograniczone doświadczenie w Firefoksie z powodu błędów, należy zaimplementować niestandardowy autouzupełnianie bez danych.

Aby uzyskać dobrą wydajność, jeśli lista jest bardzo duża, może chcesz zachować całą listę z Domu i zaktualizować go jako użytkownik zmienia wejście lub przewijania na liście.

Oto przykład istniejącego niestandardowego autouzupełniania pracującego z API z Przykładu OP: https://jsfiddle.net/ YWRVHLA8 / 4 /

1
Tiago Coelho 18 marzec 2021, 12:32