Vue.js practice (2): multi-condition screening function table searching, sorting and pagination

And last week's first post hands-on tutorials , as in this article, I will continue from one common feature - starting form, showing some of the elegant properties in Vue.js. At the same time will also filter functions computed attributes were compared, indicating that their application scenarios, but also to prepare for the part of the filter function vue2.0 version to be deleted.

demand analysis

Or start demand start, think about what features to achieve such a note, how the general process, which application scenarios.

  1. The table itself is a very common component for performing well when to show some complex data.

  2. When comparing data for a long time, we need to provide some filtering conditions to allow the user to list their concerns data faster.

  3. In addition to the preset number of filter criteria, you may also need some personalized input search function.

  4. For obvious sequence data relationships, such as ranking, price, etc., also need to quickly and easily invert the data sorting function.

  5. If the amount of data is large, paged table display.

It should be noted that the above-mentioned requirements and in fact most of the functions provided by the database is very consistent, and because the database server has optimizations and better performance indexes, more suited to handle these needs. But now popular around the end of the separation, it is hoped to have the client within a reasonable range, more sharing of server-side pressures, so as to find a balance, the front-end processing needs the right amount of the right choice.

Then we try to complete these requirements vue bar.

Complete Table.vue

Because such a versatile form might be used in multiple projects, so far as possible on the table design ideas related to the content on Table.vue components, reducing coupling for easy reuse.

Obtaining test data

In order to better compare the pros and cons of front-end to achieve the above requirements, we need a larger and more complex test data. Luckily I had a project, the design of an API just to meet this demand, data for the World of Warcraft Arena ladder ranking API, this API is currently in an open state, the interface see Myarena introduction .

Similar to the previous tutorial, or create a new folder and a arena.js api for managing API interface. Arena.js App.vue reintroduction in the acquired data created stage. As a demo, we only get region is CN, laddar data 3v3, but as long as the two v-model parameters by binding to the corresponding form controls, you can easily switch between different regions to achieve the data.

Introduced table.vue components

As said before, the idea we want to reduce the table assembly is coupled with the external environment, we give a set Table.vue props attribute rows, for acquiring data retrieved App.vue.
In App.vue registration table when the formation is to be noted, can not use the default name table, it is registered vTable, able to use <v-table> tag introduced into the table assembly.

So far, our App.vue completed all of its functions, as follows:

<template>
  <div class="container">
    <v-table
    :rows="rows"></v-table>
  </div>
</template>

<script>
import arena from './api/arena'
import vTable from './components/Table'

export default {
  components: { vTable },
  data () {
    return {
      region: 'CN',
      laddar: '3v3',
      rows: []
    }
  },
  methods: {
    getLaddar (region, laddar) {
      arena.getLaddar(region, laddar, (err, val) => {
        if (!err) {
          this.rows = val.rows
        }
      })
    }
  },
  created () {
    this.getLaddar(this.region, this.laddar)
  }
}
</script>

There is also a practical App.vue get operation last update time of the API, as well as some css settings, consider the space has been omitted here, who are interested in the complete code can be the venue end of the article Github repository.

Basic layout

Table.vue the template in three main parts, namely, form controls for searching, filtering and pagination, headers for sorting table thead and tbody for displaying data.

First to complete tbody part, the basic idea is to traverse with v-for data, and then fill in the template, we need to pay attention to the following points:

  1. The returned data may not be entirely satisfactory. For example, I hope to achieve by winning the sort, but the data contains only a few winning games, you need to be calculated once. 2. Data for the performance of professional players classId this attribute data, but the actual project I want to show career with the icon of the occupation, so I implemented a classIdToIcon various utility functions in utils.js in for classId mapped to background-position sprite in FIG.

  2. The above two points that we better not traverse the rows props obtained the original data. Therefore, another built a computed property players, and in which the completion of the pre-treatment, I put all the pre-processing on the handleBefore in.

  3. Due to a variety of filters that will be used in more complex operations, it was console.log ( 'before handle') in handlebefore in to help us verify handlebefore at what stage is carried out.

After completing the layout, the focus of the current Table.vue code is as follows:

<template>
  <tbody>
    <tr
    v-for="player of players
    :class="player.factionId? 'horde':'alliance'">
      <th>{{ player.ranking }}</th>
      <th>{{ player.rating }}</th>
      <th>
        <span
        class="class"
        :style="{ backgroundImage: 'url(http://7xs8rx.com1.z0.glb.clouddn.com/class.png)',
                  backgroundPosition: player.classIcon }"></span>
        {{ player.name }}
      </th>
      <th>{{ player.realmName }}</th>
      <th>
        <bar
        :win="player.weeklyWins"
        :loss="player.weeklyLosses"></bar>
      </th>
      <th>
        <bar
        :win="player.seasonWins"
        :loss="player.seasonLosses"></bar>
      </th>
    </tr>
  </tbody>
</template>

<script>
import Bar from './Bar'
import { classIdToIcon } from '../assets/utils'

export default {
  components: { Bar },
  props: {
    rows: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  computed: {
    players () {
      this.rows = this.handleBefore(this.rows)
      return this.rows
    }
  },
  methods: {
    handleBefore (arr) {
      console.log('before handle')
      if (this.rows[0]) {
        arr.forEach((item) => {
          if (item.weeklyWins === 0 && item.weeklyLosses === 0) {
            item.weeklyRate = -1
          } else {
            item.weeklyRate = item.weeklyWins / (item.weeklyWins + item.weeklyLosses)
          }
          if (item.seasonWins === 0 && item.seasonLosses === 0) {
            item.seasonRate = -1
          } else {
            item.seasonRate = item.seasonWins / (item.seasonWins + item.seasonLosses)
          }
          item.classIcon = classIdToIcon(item.classId)
        })
      }
      return arr
    }
  }
}
</script>

You can see, I also introduced a Bar.vue component representative of winning, it is because I want the ultimate practical effect is this:

clipboard.png

I started directly in the <th> tag where odds of various operations, but imagine making some judgment boundary conditions, there will be all kinds containing player.weeklyWins, three player.weeklyLosses as long as named variables yuan expression.
It could have been considered a matter of convenience, but instead lead to code difficult to maintain. Thus a new bar of a component, the outcome of the incoming assembly, to achieve a more semantic manner inside bar assembly, Bar.vue template part of the code as follows:

<template>
  <div class="clear-fix">
    <span
    v-if="!hasGame || win / total > 0"
    :style="{ width: 100 * win / total + '%' }"
    :class="hasGame? '':'no-game'"
    class="win-bar">
      {{ hasGame? (100 * win / total).toFixed(1) + '%':'无场次' }}
    </span>
    <span
    v-if="loss / total > 0"
    :style="{ width: 100 * loss / total + '%' }"
    class="loss-bar">
      {{ win === 0? '0%':'' }}
    </span>
  </div>
</template>

Better understand and maintain, is not it?

Vue in use in the process, should be noted that in the framework of a number of methods actually inside the final is the same thing.

For example, we can perform some operation on the data directly in the element, such as @ click = "show =! Show", we can also bind the same method for the event, and then manipulate the data in a method, for example, @ click = "toggle" , toggle () {this.show =! this.show}. For example, we can also achieve a lot of the same functionality with computed properties and attributes watch, the next will be computed using filters to achieve the same functionality.

vue design flexibility so that we have more possibilities, but at the time of learning, should thoroughly understand the pros and cons of different ways in different scenes as the goal, choosing the best of what kind of practical application.

Implementation requirements with filters

In an example, a 5000 Players actually array data, when no treatment, directly render 5000 <tr>, so it was filtered quickly to!

For v-for loop, VUE filters provided in the filter array 3, respectively filterBy, orderBy, limitBy, the function corresponding to the search / filter, sorting and paging, are implemented using Array.filter, Array.sort () , Array.slice ().

These three filters in the use of very convenient, as long as the v-for later use | separated and then add filters corresponding to these three specific parameters in the filter can check out the official API, not much to do repeat them here.

Note that the actual process is the first iterated array (Players example) sequentially through the filter, and then a final filter array returned by the v-for operation.
Thus, the order of placement of filters is the need to adjust according to demand, but also because the internal efficiency of each filter to achieve different, it is not obvious when the demand priority, priority should be efficient.

Note : the actual test and found that no matter how filter array, handleBefore methods are not executed again, that is an array of players has not been altered.

For example, in my case, I hope you can filter out the name or the server that contains the players I've entered, and they will be sorted in some way, the final results per page show only 20.
Then obviously cut should be placed in an array is always the last step, but there is no obvious sorting and filtering priority requirements. But in most cases, be lower than the efficiency sort of filter, so let's carry on filter, reduce the length of the array, and then sort.

With this idea later, for the v-for <tr> becomes:

<tr
v-for="player of players
| filterBy query in 'name' 'realmName'
| orderBy sort.key sort.val
| limitBy 20 (page-1)*20"
:class="player.factionId? 'horde':'alliance'">

Here directly to each variable dynamic, re-v-model and header thead binding @click event to change the conditions screened by Table.vue the input binding, it has achieved most of the searching, filtering, paging function.

I change the sort ordering header is achieved by the following code, the way may not be good, hereby listed:

<thead>
  <tr>
    <th
    @click="sort = {key: 'ranking', val: -sort.val}">排名</th>
    <th
    @click="sort = {key: 'rating', val: -sort.val}">分数</th>
    <th>资料</th>
    <th>服务器</th>
    <th
    @click="sort = {key: 'weeklyRate', val: -sort.val}">本周战绩</th>
    <th
    @click="sort = {key: 'seasonRate', val: -sort.val}">赛季战绩</th>
  </tr>
</thead>

It can be seen through the filters vue function, you can easily have completed most of our functions, minimal amount of code. This is also vue2.0 Preview release, abandoned after the proposed section filters feature many people react more strongly reasons.
But as the author says in the description changes, filters for beginners are difficult to understand, and filters functions can be more flexible with computed attributes to achieve better control of. Complex and in some conditions, the filter stack may cause some additional complexity and inconvenience.

So what is the complex conditions? For example, I added two requirements, one is screened by professional players, but screening out more than a certain fraction of the players, then the latter is not very good with filterBy achieved.
We will need to score filtration segment were placed before the filters, but the players have to be careful not to damage the array itself. In practical completion, you will find this process quite tangled.

In addition, we also find a tab the most important information - we get less than the total number of pages. Because vue not a string of pipe in the filter output for the final array is exposed v-for, so we can not get the actual length of the circular array.

When these needs actual hack, it is easy to find a conflict with the execution order of filters, it was decided to re-use computed properties to achieve through all functions, without the aid of built-in filters.

Of course, in the first half of this period, we feel obvious from the convenience of filters. If you meet the needs of the filters, use filters in version 1.x is still very wise!

Complete with a computed property demand

In Github repository, I stored some code before using filters implemented with Table.vue.bak files facilitate comparison with the realization that we took inside.

First, sort out ideas using computed attributes to achieve:

  1. You must first realize filterBy, orderBy, limitBy three filter functions mentioned above have their internal implementation, so respectively Array.filter, Array.sort and Array.slice rewrite is not complicated.

  2. Said to be computed attributes to achieve, in fact, still only players this computed property, just execute all of the filtering action inside, we actually put a variety of filters placed in the logic of each method.

  3. Is not recommended to write each filter method is too abstract, because the built-in filters is highly abstract cause some special needs can not be achieved, so might as well in the most targeted way: a method corresponds to a filter.

  4. While performing various filtering method, still efficient problems caused by the initial order mentioned. Since vue indeed affect the whole body features a filter change any time, all the filtering method will be executed again, so soon as possible with an efficient filter to shorten the length of the array is more important.

  5. I tried to call the method minimized by watch property, but failed to achieve helpless skill is not enough. I also think the situation front-end processing large amounts of data are rare, and optimize data points in the fourth, the efficiency is not too low, so no need to do too much entangled in this regard. When really performance bottlenecks, seek solutions from the server will be easier.

Note: When implementing a variety of filtering method, to achieve the source vue recommended reading in filterBy, orderBy, limitBy three parts, which itself for the operation of the array will have some optimization, well worth learning. In some special cases, such as when a large amount equal to the value of the array, simplistic sort function will lead to the implementation of the surge in the number of steps, vue some processing are to be avoided.

According to the needs of the target, I set the following method (that is sequential execution order):

  1. classFilter: filter professional players, to judge by item.classId === this.class, this.class is bound to a select control.

  2. queryFilter: match the player's name in the field, by item.name.indexOf (this.query) judgment, this.query then bind a control input.

  3. ratingFilter: Screening player scores section, judged by item.rating> = this.rating, this.rating bound to a control input of the type of range, the range is calculated using a range computed property.

  4. sortTable: large number of steps because Array.sort performed, so that the array is placed after the three shorter processing method.

  5. paginate: After all the filtering operation is complete, you can collate up. Before using Array.slice (), the length of the first array pass this.total stored, for calculating the total number of pages in the tab.

  6. In addition to the above several filtration method, however there are also handleBefore array of pre-treatment method. However, since players recalculated every time, so in order to put a stop handleBefore is repeatedly executed with a certain determination condition should be, e.g. handleBefore added attribute already exists and so forth.
    Meanwhile, also some of the operation need not be performed prior to filtration from handleBefore out, for example, for example the conversion classId Icon, the data may ultimately be displayed after filtration to reduce the number of the number of steps. It is also provided a method handleAfter for subsequent operations after completion tab, of course, possible to repeat the execution handleAfter, the operation performed if a great strain is recommended to add the same determination, to avoid repeated.

In the example code, in every way I counted the number of steps are performed, the actual results show a reasonable set of filter order to avoid some performance issues with the following results:

clipboard.png

Initialization It can be seen, in any case of no filter, the higher the number of steps of the sort. And once some of the filters you've added, filter and sort of pick by the number of steps will be drastically reduced.

DEMO Institute Add

Because work is busy, there is no intention in the beginning of the show MyArena reconstruction project, but can imagine that would be a good example by making vue single page application, follow-up tutorial could be used to make an example.

Examples of this tutorial, focusing on the multi-function display table itself

DEMO point I address
Github repository

Writing Program

Last week was Vue.js development practices of the first article, the first time I published an article in a personal column SF community, hoping to put some of the problems usually encountered and resolved for everyone to share ideas, and he carried a comb.

Development practices this series will use some small examples, show some ideas to achieve something useful, common functions can be reused. Plan, there will be a series Vue.js combat and combat Sails.js series two series of articles.
The former project from a more complete analysis technology selection, vue-router and vuex use of multiport shared codes, post-maintenance and other aspects of a number of considerations. The latter is to try and build some experience with enterprise backend Node.js Sails.js this framework, including the advantages and disadvantages of the frame, and the horizontal contrast details groping like.
Ali is also currently concerned about the progress measured Weex open source projects, the state ideal is to achieve Weex project in the development of mobile App end, the real complete JS full stack, but Weex not yet officially open, be wait and see, so just imagine the late , temporarily absent in the plan.

Currently only made in the article on SF's column, so there are opinions and suggestions, please leave a message at the bottom of the article. At the same time due to the above mentioned all the work is done by one person in charge, the update of the article may or slower speed, and strive to achieve once per week.

Guess you like

Origin www.cnblogs.com/jlfw/p/12633741.html