VuejsによるインタラクティブMatcher


フロントエンドの開発者として新しい仕事に応募するときは、インタビュープロセスのいくつかのレベルからのインタビューといくつかのタスクの任意のタイプを得ることができます.現在、我々は2種類のタスク「多くの人気テスト(インタビュー)タスク」と「人気のないテストタスク」をフロントエンド開発者に持っています.BTW多くの会社は、彼らの会社からのテストタスクがユニークであると思います、そして、彼らはあなたにそれを秘密にしておくよう頼みます、そして、あなたは公共のgithubレポを公表しません.しかし、タスクの検索キーワードは、多くの場合、同じAPIで同じタスクで完全なGitHubパブリックプロジェクトを見つけることができます.それで.この仕事を解決しましょうinteractive matcher Vuejsとのインタビュータスクから、この公共githubrepo .
2つのCVSファイル1で資産フォルダーを作成するこのプロジェクトの中で、私たちは新しいVujsプロジェクトを作成します.
州管理をするために、我々は店をつくります.プロジェクトsrcフォルダ内のJSと以下のコードを追加します.
import Vue from "vue";
import Vuex from "vuex";
import recordingsdata from "./assets/sound_recordings.csv";

import inputsdata from "./assets/sound_recordings_input_report.csv";
Vue.use(Vuex);

const appendId = (tempArray) => {
  return tempArray.map((item) => ({
    id: Math.random().toString().slice(2),
    ...item,
  }));
};

const postRecordingsData = appendId(recordingsdata);
const postInputs = appendId(inputsdata);

export const store = new Vuex.Store({
  state: {
    // origin
    recordings: postRecordingsData,

    // left aside list
    inputs: postInputs,

    // right aside list
    results: postRecordingsData,

    selectedInputsItem: {},
    selectedResultsItem: {},
  },
  mutations: {
    SET_STATE(state, payload) {
      Object.keys(payload).forEach((key) => {
        if (key in state) {
          state[key] = payload[key];
        }
      });
    },
    S_INPUT(state, payload) {
      state.selectedInputsItem = payload;
    },
    addInput(state) {
        console.log("state.selectedInputsItem:", state.selectedInputsItem);
    state.recordings.push(state.selectedInputsItem.item);
    state.results.push(state.selectedInputsItem.item)
    console.log("state:",state);    
    },
  },
});

と内部アプリ.Vue file以下のコードを追加します.
<template>
  <div id="app">
    <Header />
    <div class="container">
      <div class="row">
        <div class="col-md-5">
          <Inputs />
        </div>
        <div class="col-md-2">
          <Actions />
        </div>
        <div class="col-md-5">
          <Database />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Header from "./components/Header.vue";
import Inputs from "./components/inputs/Inputs.vue";
import Actions from "./components/actions/Actions.vue";
import Database from "./components/database/Database.vue";

export default {
  name: "App",
  components: {

    Header,
    Inputs,
    Actions,
    Database,
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #181c20;
  /* margin-top: 60px; */
}
</style>

コンポーネントフォルダで、入力、データベース、およびアクションコンポーネントを作成します.アクションは次のコードを追加します.
<template>
 <div>
  <button class="btn btn-outline-primary" @click="register"><i class="fa fa-arrow-right"></i> Register</button>
  </div>
</template>
<style scoped>
</style>
<script>

import { mapMutations } from "vuex";
export default {

  methods: {
    ...mapMutations(["SET_STATE"]),

    register() {
      console.log("selected:----",this.$store.state.selectedInputsItem);
      this.$store.commit('addInput')

    },
  },
};
</script>
次のようなデータベースコンポーネントコード
<template>
  <div>
    <input type="text" v-model="search" placeholder="Search title.." />

    <div>Records: {{ recordings.length }}</div>
    <ul class="list-group list-group-flush">
      <li class="mt-4" v-for="item in recordings" :key="item.id">
        <div class="card">
          <div class="card-body">
            <h5 style="">{{ item.title }}</h5>
            <p>{{ item.artist }}</p>
            <div style="display: flex; justify-content: space-between">
              <h6>{{ item.isrc }}</h6>
              <h6>{{ item.duration | formatTime }}</h6>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      search: "",
    };
  },
  computed: {
    recordings() {
      const searchrg=new RegExp(this.search,'i');
      return this.$store.state.results.filter((item) =>
        [item.isrc, item.artist, item.title].some((el) =>
          el && el.toLowerCase().match(searchrg)
        )
      );
    },
  },

  filters: {
    formatTime(time) {
      if (time > 0) {
        var mins = ~~((time % 3600) / 60);
        var secs = ~~time % 60;

        var ret = "";
        ret += "0" + mins + "m" + " " + (secs < 10 ? "0" : "");
        ret += "" + secs + "s";
        return ret;
      } else return "";
    },
  },
  methods: {

};
</script>
<style scoped>
ul {
  list-style-type: none;
  overflow: scroll;
  overflow-x: hidden;
  height: 80vh;
}
</style>
次のコードを追加します
<template>
  <ul class="list-group list-group-flush">
    <div>Inputs: {{ inputs.length }}</div>
    <li class="mt-4" v-for="item in inputs" :key="item.id">
      <div class="card " v-bind:class="{isActive:activeItem===item}" @click="findMatch(item)">
        <div class="card-body">
          <h5 style="">{{ item.title }}</h5>
          <p>{{ item.artist }}</p>
          <div style="display: flex; justify-content: space-between">
            <h6>{{ item.isrc }}</h6>
            <h6>{{ item.duration | formatTime }}</h6>
          </div>
        </div>
      </div>
    </li>
  </ul>
</template>
<style scoped>
ul {
  list-style-type: none;
  overflow: scroll;
  overflow-x: hidden;
  height: 80vh;
}
.isActive{
  border:18px solid #e19eae ;
}
</style>
<script>
import { mapMutations } from "vuex";
export default {
  data() {
    return {
      activeItem:null
    };
  },
  computed: {
    inputs() {
      return this.$store.state.inputs;
    },
  },
  methods: {
    ...mapMutations(["SET_STATE","S_INPUT"]),

    findMatch(item) {
      console.log(item);
      this.activeItem=item;
     this.S_INPUT({item});


      const targetFields =(item.title.toUpperCase()+' '+item.artist.toUpperCase() +(item.isrc?' ' + item.isrc?.toUpperCase():'')).split(' ');


      const t = this.$store.state.recordings.filter((elem) => {
         const ele=(elem.title.toUpperCase()+' '+elem.artist.toUpperCase() +' '+elem.isrc?.toUpperCase()).split(' ');

         return ele.filter(field=> targetFields.includes(field)).length>0;



      this.SET_STATE({
        results: t || [],
      });

    },
  },
  filters: {
    formatTime(time) {
      if (time > 0) {
        var mins = ~~((time % 3600) / 60);
        var secs = ~~time % 60;

        var ret = "";
        ret += "0" + mins + "m" + " " + (secs < 10 ? "0" : "");
        ret += "" + secs + "s";
        return ret;
      } else return "";
    },
  },
};
</script>
プロジェクトを実行すると、下のブラウザのタブイメージに表示できます.



私はこの記事は、インタビュープロセスを通過するのに役立ちます願っています.