programing

VueJ에서 2개의 타사 구성 요소를 병합하는 방법

prostudy 2022. 3. 7. 22:13
반응형

VueJ에서 2개의 타사 구성 요소를 병합하는 방법s

나는 Form Tags 구성 요소 bootstrap-vue 프레임워크를 사용하고 있다.양식 태그가 있는 vue-simple-semple-sempt 구성 요소(npm)를 사용하여 사용자 쿼리와 관련된 단어를 제안하고 싶다.사용자는 제안에서 여러 단어를 선택할 수 있으며, 선택한 단어는 아래 그림과 같이 양식 태그에 알약으로 저장된다.

여기에 이미지 설명을 입력하십시오.

두 구성 요소를 단일 구성 요소(또는 더 나은 방법)로 병합하여 부팅스트랩의 UI 기능을 타사 모듈의 자동 제안 기능과 함께 사용할 수 있도록 하는 방법을 모르겠다.

나 지금 VueJs를 배우고 있는데, 이걸 하려면 뭘 배워야 할지 모르겠어.

내 암호는 다음과 같다.

<template>
  <div>
    <vue-simple-suggest
      v-model="chosen"
      mode="select"
      :list="simpleSuggestionsList"
      :filter-by-query="true"
      :destyled="false"
    >

      <b-form-tags 
        placeholder="Enter Keyword"
        size="lg"
        tag-variant="success"
        tag-pills
        remove-on-delete
        separator=","
        class="my-3"
        @input="updateValue"
      ></b-form-tags>

    </vue-simple-suggest>

  </div>
</template>

<script>
import VueSimpleSuggest from 'vue-simple-suggest'
import 'vue-simple-suggest/dist/styles.css'

export default {
  name: "SeedWordsSuggestions",

  data() {
    return {
      chosen: '',
      seedWords: []
    }
  },

  components: {
    VueSimpleSuggest
  },

  methods: {

    simpleSuggestionsList() {
      return [
        'Angular',
        'ReactJs',
        'VueJs'
      ]
    },

    addSelectedWord(e) {
      console.log(`addSelectedWord`, e)
    },

    updateValue(value) {
      const pos = value.length
      this.seedWords.push(value[pos - 1])
      console.log(this.seedWords)
    }
  }
}
</script>

<style scoped>

</style>

다음 솔루션은 두 구성 요소를 함께 해킹하여 태그 필이 있는 편집 가능한 콤보박스를 만든다.

의 주의사항에 따르면, 사용자 정의 입력 구성요소는 반드시inputfocus그리고blur사건들뿐만 아니라value에도 구성 하는 몇 clickkeydown그리고keyup.

b-form-tags가 있다value소품. 그러나 필요한 이벤트 중 몇 개가 누락되어 있음.그러나 내부에는 액세스할 수 있다.input전달되는 자체 이벤트 핸들러를 부착하는 요소$emit이벤트:

export default {
  async mounted() {
    // wait a couple ticks to ensure the inner contents
    // of b-form-tags are fully rendered
    await this.$nextTick()
    await this.$nextTick()

    // <b-form-tags ref="tags">
    const input = this.$refs.tags.getInput()
    const events = [
      'focus',
      'blur',
      'input',
      'click',
      'keydown',
      'keyup'
    ]
    events.forEach(event =>
      input.addEventListener(event, e => this.$refs.tags.$emit(event, e))
    )
  },
}

위의 변화만으로도 그 변화는vue-simple-suggest타이핑할 때 적절하게 표시/표시하다그러나 자동 제안과 상호 작용할 때는 태그를 추가/제거하지 않는다.그러한 행동은 다음과 같은 특징에 의해 구현될 수 있다.

  1. ENTER 또는 키프레스(keypress)는 보호되는 자동 검색을 태그로 추가하게 한다.아무 것도 맴돌지 않으면 키프레스는 태그로 첫 번째 자동 암시를 추가한다.
  2. 자동 제안을 클릭하면 자동 제안이 태그로 추가된다.
  3. BACKSPACE 자동 검색 태그에서 삭제하십시오.

기능 1 구현:

  1. 추가하다ref을 위해vue-simple-suggest그리고b-form-tags나중에 JavaScript의 구성요소에 액세스할 수 있도록:
<vue-simple-suggest ref="suggest">
  <b-form-tags ref="tags" />
</vue-simple-suggest>
  1. 추가 akeydown-내부 입력에 대한 영향b-form-tags:
export default {
  mounted() {
    //...

    // <b-form-tags ref="tags">
    const input = this.$refs.tags.getInput()
    input.addEventListener('keydown', e => this.onKeyDown(e))
  },
}
  1. 다음과 같이 처리기를 구현하십시오.
export default {
  methods: {
    async onKeyDown(e) {
      if (e.key === 'Enter' || e.key === 'Tab') {
        // prevent default so that the auto-suggestion isn't also
        // added as plaintext in b-form-tags
        e.preventDefault()

        // <vue-simple-suggest ref="suggest">
        if (this.$refs.suggest.hovered) {
          this.$refs.tags.addTag(this.$refs.suggest.hovered)

        } else {
          const suggestions = await this.$refs.suggest.getSuggestions(e.target.value)
          if (suggestions.length > 0) {
            this.$refs.tags.addTag(suggestions[0])

          } else {
            // no match, so clear chosen
            this.chosen = ''
          }
        }
      }
    }
  }
}
  1. 핸들러와의 충돌을 방지하려면 사용 안 함b-form-tag를 추가하여 의 자동 태그 지정no-add-on-enter받침대:
<b-form-tags no-add-on-enter />

기능 2 구현:

  1. 묶다suggestion-click-이벤트 핸들러:
<vue-simple-suggest @suggestion-click="onSuggestionClick">
  1. 다음과 같이 처리기를 구현하십시오.
export default {
  methods: {
    onSuggestionClick(suggestion) {
      this.$refs.tags.addTag(suggestion);
    },
  }
}

기능 3 구현:

  1. 추가remove-on-delete에 지지하다.b-form-tags:
<b-form-tags remove-on-delete />

풀 데모


그 외, 합치려고 하는 두 가지 요소의 조합을 지원하는 Vuetify's 는 더 나을지도 모르지만, 나는 그것을 당신에게 맡겨서 탐색해보겠다. :)

두 구성 요소를 병합하면 부트스트랩뷰의 내부 구성 요소를 수정할 필요가 있으며 시간이 걸린다.

https://bootstrap-vue.js.org/docs/components/form-tags 설명서를 참조하십시오.BootstrapVue는 이미 검색 태그를 지원하고 있다.에 저장된 사용 가능한 목록options:

data() {
  return {
    options: ['Apple', 'Orange', 'Banana', 'Lime', 'Peach', 'Chocolate', 'Strawberry'],
    search: '',
    value: []
  }
},

이 옵션 목록을 업데이트하도록 수정하면 제안을 얻을 수 있다.

추가하다@change사건in b-form-input촉발시키다updateOptionsList():

<!-- Add onChange event to update The List -->
<b-form-input
      v-model="search"
      id="tag-search-input"
      type="search"
      size="sm"
     @change="updateOptionsList()"
      autocomplete="off"
 ></b-form-input>

추가updateOptionsList()방법:

// Get Data From Server From URL
updateOptionsList() {
  console.log("update list");

  this.options = ["Jakarta", "London", "Birmingham", "Rome"];
  // Use  axios.get('...') then attach the result to this.options
  /**  axios.get("your-url-here").then(response => {
    // update options
    this.options = response.data;
  }); **/
}

참고: acios(https://vuejs.org/v2/cookbook/using-axios-to-consume-apis.html)를 사용하여 서버에서 실제 데이터를 가져올 수 있으며 옵션 목록을 업데이트하십시오.

전체 샘플 코드:

<template>
  <div>
    <b-form-group label="Tagged input using dropdown">
      <b-form-tags v-model="value" no-outer-focus class="mb-2">
        <template v-slot="{ tags, disabled, addTag, removeTag }">
          <ul v-if="tags.length > 0" class="list-inline d-inline-block mb-2">
            <li v-for="tag in tags" :key="tag" class="list-inline-item">
              <b-form-tag
                @remove="removeTag(tag)"
                :title="tag"
                :disabled="disabled"
                variant="info"
              >{{ tag }}</b-form-tag>
            </li>
          </ul>

          <b-dropdown size="sm" variant="outline-secondary" block menu-class="w-100">
            <template v-slot:button-content>
              <b-icon icon="tag-fill"></b-icon>Choose tags
            </template>
            <b-dropdown-form @submit.stop.prevent="() => {}">
              <b-form-group
                label-for="tag-search-input"
                label="Search tags"
                label-cols-md="auto"
                class="mb-0"
                label-size="sm"
                :description="searchDesc"
                :disabled="disabled"
              >
                <!-- Add onChange event to update The List -->
                <b-form-input
                  v-model="search"
                  id="tag-search-input"
                  type="search"
                  size="sm"
                  @change="updateOptionsList()"
                  autocomplete="off"
                ></b-form-input>
              </b-form-group>
            </b-dropdown-form>
            <b-dropdown-divider></b-dropdown-divider>
            <b-dropdown-item-button
              v-for="option in availableOptions"
              :key="option"
              @click="onOptionClick({ option, addTag })"
            >{{ option }}</b-dropdown-item-button>
            <b-dropdown-text
              v-if="availableOptions.length === 0"
            >There are no tags available to select</b-dropdown-text>
          </b-dropdown>
        </template>
      </b-form-tags>
    </b-form-group>
  </div>
</template>

<script>
import axios from "axios";

export default {
  data() {
    return {
      options: [
        "Apple",
        "Orange",
        "Banana",
        "Lime",
        "Peach",
        "Chocolate",
        "Strawberry"
      ],
      search: "",
      value: []
    };
  },
  computed: {
    criteria() {
      // Compute the search criteria
      return this.search.trim().toLowerCase();
    },
    availableOptions() {
      const criteria = this.criteria;
      // Filter out already selected options
      const options = this.options.filter(
        opt => this.value.indexOf(opt) === -1
      );
      if (criteria) {
        // Show only options that match criteria
        return options.filter(opt => opt.toLowerCase().indexOf(criteria) > -1);
      }
      // Show all options available
      return options;
    },
    searchDesc() {
      if (this.criteria && this.availableOptions.length === 0) {
        return "There are no tags matching your search criteria";
      }
      return "";
    }
  },
  methods: {
    onOptionClick({ option, addTag }) {
      addTag(option);
      this.search = "";
    },
    // Get Data From Server From URL
    updateOptionsList() {
      console.log("update list");

      this.options = ["Jakarta", "London", "Birmingham", "Rome"];
      // Use  axios.get('...') then attach the result to this.options
      /**  axios.get("your-url-here").then(response => {
        // update options
        this.options = response.data;
      }); **/
    }
  }
};
</script>

여기 https://codesandbox.io/s/vue-bootstrap-tags-search-ldsqx에서 먹어봤는데 상품처럼 생겼어.

분명히, b-폼 태그는 태그가 입력될 때까지 입력 이벤트를 내보내지 않는다.사용자가 키를 누를 때마다 입력을 변경해야 하기 때문에 이는 vue-simple-sump-sump 제안으로 작업하기에 이상적인 경우는 아니다.따라서, 당신이 할 수 있는 것은 다른 방식으로 하는 것이 아니라, b-form-tags 안에 있는 슬롯 vue-simple-sump-sump-sump-sump-sump-sempt를 제안하는 것이다.이런게 필요할거야:

<template>
  <div>
    <b-form-tags
      size="lg"
      tag-variant="success"
      tag-pills
      remove-on-delete
      separator=","
      class="my-3"
      v-model="chosenTags"
    >

      <template v-slot="{tags, tagVariant, addTag, removeTag}">
        <b-form-tag
          v-for="tag in tags"
          :key="tag"
          :variant="tagVariant"
          @remove="removeTag(tag)"
          class="mr-1 mb-1"
        >{{ tag }}</b-form-tag>

        <b-form @submit.prevent="addSelectedWord(chosen)">
          <vue-simple-suggest
            placeholder="Enter Keyword"
            @input="textInput"
            :value="chosen"
            mode="select"
            @select="addSelectedWord"
            :list="simpleSuggestionsList"
            :filter-by-query="true"
            :destyled="false"
          ></vue-simple-suggest>

          <b-btn v-if="!!chosen" type="submit" class="my-1" outline>Add</b-btn>

        </b-form>

      </template>
    </b-form-tags>
  </div>
</template>

<script>
import VueSimpleSuggest from "vue-simple-suggest";
import "vue-simple-suggest/dist/styles.css";

export default {
  name: "SeedWordsSuggestions",

  data() {
    return {
      chosen: "",
      chosenTags: [],
      seedWords: []
    };
  },

  components: {
    VueSimpleSuggest
  },

  methods: {
    simpleSuggestionsList() {
      return ["Angular", "ReactJs", "VueJs"];
    },

    textInput(text) {
      this.chosen = text;
    },

    addSelectedWord(word) {
      console.log(word);
      this.chosenTags.push(word);
      this.chosen = "";
    }
  }
};
</script>

<style scoped>
</style>

맞춤 스타일링을 추가하여 슬롯 또는 구성요소를 추가로 사용자 정의할 수 있다.두 개의 입력 필드가 표시되지 않는 경우, CSS에서 경계 속성을 없음으로 설정하여 한 개의 경계선을 제거해 보십시오.

나는 이 두 리를 사용한 적이 없다. 단지 약간의 충고만 할 뿐이다.

내 생각에 주요 요점은 UI가 제공하는 것을 사용하지 않는 것 같아.vue-simple-suggest너도 알다시피, UI 프레임워크는 BootstrapVue이고 그것은 다른 사람들이 그 환경에 들어가는 것을 좋아하지 않을 것이다.

대신 API를 사용하여 제안사항을 가져오십시오.

단계는 다음과 같이 보일 수 있다.

1. Show dropdown menu with {fetchSuggestions(something)} when typeing {something}
2. Add a pill labeled with the {suggestion} when {suggestion} being clicked

그게 도움이 되길 바래.

참조URL: https://stackoverflow.com/questions/60450873/how-to-merge-2-third-party-components-in-vuejs

반응형