首页 > 解决方案 > Vue JS 组件排序的最佳方式

问题描述

我有一个网站,我想使用 Vue 2 添加搜索功能,搜索将应用于通过 JSON 文件在页面加载时生成的组件。

我想为此使用的关键字包含在获取的 JSON 文件中。(名称和标签)(顺便说一下,这些组件被称为池)我正在考虑使用计算属性,但是我对如何去做这件事有点困惑

到目前为止,这是我的搜索栏组件所拥有的,但我对计算属性应该如何感到困惑。

<template>
    <div class="search">
        <input type="text" v-model="search" placeholder="Search for pools">
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Search Box Mounted')
        },
        data(){
            return{
                search:''
            }
        },
        computed: {
            filteredPools: function(){

            }
        }
    }
</script>

此代码负责显示池列表

<template>
    <div class="container pool" v-bind:id="'poolalgo-' + algo">
        <h2 class="type text-center">{{algo}}</h2>
        <hr class="poolruler" />
        <div class="row">
            <pool v-for="pool in pools" :pool="pool" :key="pool.tag">
            </pool>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('PoolList mounted.')
        },
        props:['pools','algo']
    }
</script>

然后只有显示实际池的组件

<template>

    <div class="col-xl-3 centered icon">
        <a v-bind:href="pool.url" target="_blank">
            <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
        </a>
        <h4>{{pool.name}}</h4>
        <p>Symbol/Tag: {{pool.tag}}</p>
        <p>Block Time: {{pool.blocktime}}</p>
        //ect
        <br>
    </div>
</template>

<script>
    export default {
        props: ['pool'],

        mounted() {
            console.log('Pool mounted.')
        },
    }
</script>

在我的主页中,这就是所谓的池列表

<pool-list v-for="(pools,algo) in poolConfig" :pools="pools" :algo="algo"></pool-list>

标签: javascriptvue.js

解决方案


运行此代码段(整页)并检查这是否是您想要的。它是单个组件,但您可以关注评论,以便您可以随意使用它(搜索输入组件 + 列表组件)

搜索组件

<template>
  <div class="search">
      <input type="text" @input="emitSearch" placeholder="Search for pools">
  </div>
</template>
<script>
export default {
    methods: {
    emitSearch (ev) {
      this.$root.$emit('app:search', ev.target.value)
    }
  }
}
</script>

列表组件

<template>
 <div class="col-xl-3 centered icon" v-for="pool in list" :key="pool.name">
    <a v-bind:href="pool.image" target="_blank">
        <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
    </a>
    <h4>{{pool.name}}</h4>
    <p>Symbol/Tag: {{pool.tag}}</p>
    <p>Block Time: {{pool.blocktime}}</p>
    //ect
    <br>
  </div>
</template>
<script>
export default {
  data () {
    return {
      search: '',
      orderBy: 'name', // sort by property
      pools: [ // raw list
        {name: 'Yellow pool', tag: 'yellow', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Blue pool', tag: 'blue', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Purple pool', tag: 'purple', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Black pool', tag: 'black', blocktime: 123, image: 'https://placehold.it/120'},
      ]
    }
  },
  computed: {
    list () {
      return this.pools.filter(p => { // first using this.search
        return p.name.toLowerCase()
          .indexOf(this.search.toLowerCase()) > -1
      })
        .sort((a, b) => { // sort using this.orderBy
          const first = a[this.orderBy].toLowerCase()
          const next = b[this.orderBy].toLowerCase()
          if (first > next) {
            return 1
          }
          if (first < next) {
            return -1
          }
          return 0
        })
    }
  },
  created () {
    this.$root.$on('app:search', search => {
      this.search = search
    })
  },
  beforeDestroy () {
    // dont forget to remove the listener
    this.$root.$off('app:search')

  }
}
</script>

工作小提琴

new Vue({
  el: '#app',
  data () {
    return {
      search: '',
      orderBy: 'name', // sort by property
      pools: [ // raw list
        {name: 'Yellow pool', tag: 'yellow', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Blue pool', tag: 'blue', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Purple pool', tag: 'purple', blocktime: 123, image: 'https://placehold.it/120'},
        {name: 'Black pool', tag: 'black', blocktime: 123, image: 'https://placehold.it/120'},
      ]
    }
  },
  computed: { // list component computed props
    list () {
      return this.pools.filter(p => { // first using this.search
        return p.name.toLowerCase()
          .indexOf(this.search.toLowerCase()) > -1
      })
        .sort((a, b) => { // sort using this.orderBy
          const first = a[this.orderBy].toLowerCase()
          const next = b[this.orderBy].toLowerCase()
          if (first > next) {
            return 1
          }
          if (first < next) {
            return -1
          }
          return 0
        })
    }
  },
  methods: { // search component method
    emitSearch (ev) {
      this.$root.$emit('app:search', ev.target.value)
    }
  },
  created () { // list component lifecycle hook
    this.$root.$on('app:search', search => {
      this.search = search
    })
  },
  beforeDestroy () { // list component lifecycle hook
    // dont forget to remove the listener
    this.$root.$off('app:search')

  }
})
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script>Vue.config.productionTip = false</script>

<div id="app">
  <!-- search component emits 'app:search' event -->
  <div class="search">
    <input type="text" @input="emitSearch" placeholder="Search for pools">
  </div>
  <hr>
  <!-- list component listens 'app:search' event -->
  <div class="col-xl-3 centered icon" v-for="pool in list" :key="pool.name">
    <a v-bind:href="pool.image" target="_blank">
        <img class="logo img rounded-circle" v-bind:src="pool.image" height="120px" width="120px">
    </a>
    <h4>{{pool.name}}</h4>
    <p>Symbol/Tag: {{pool.tag}}</p>
    <p>Block Time: {{pool.blocktime}}</p>
    //ect
    <br>
  </div>
</div>


推荐阅读