3. 网格组件 Example

99 阅读1分钟

创建了一个可复用组件,可结合外部数据来使用它

1.gif

<!DOCTYPE html>
<html>
  <head>
    <title>Grid Component</title>
    <script src="https://unpkg.com/vue@2"></script>
    <link rel="stylesheet" type="text/css" href="./style.css" />

    <!-- component template -->
    <script type="text/x-template" id="grid-template">
      <table>
        <thead>
          <tr>
            <th v-for="key in columns"
              @click="sortBy(key)"
              :class="{ active: sortKey == key }">
              {{ key | capitalize }}
              <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
              </span>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="entry in filteredHeroes">
            <td v-for="key in columns">
              {{entry[key]}}
            </td>
          </tr>
        </tbody>
      </table>
    </script>
  </head>
  <body>
    <!-- demo root element -->
    <div id="demo">
      <form id="search">
        Search <input name="query" v-model="searchQuery" />
      </form>
      <demo-grid
        :heroes="gridData"
        :columns="gridColumns"
        :filter-key="searchQuery"
      >
      </demo-grid>
    </div>

    <script>
      // register the grid component
      Vue.component("demo-grid", {
        template: "#grid-template",
        props: {
          heroes: Array,
          columns: Array,
          filterKey: String
        },
        data: function() {
          var sortOrders = {};
          this.columns.forEach(function(key) {
            sortOrders[key] = 1;
          });
          return {
            sortKey: "",
            sortOrders: sortOrders
          };
        },
        computed: {
          filteredHeroes: function() {
            var sortKey = this.sortKey;
            var filterKey = this.filterKey && this.filterKey.toLowerCase();
            var order = this.sortOrders[sortKey] || 1;
            var heroes = this.heroes;
            if (filterKey) {
              heroes = heroes.filter(function(row) {
                return Object.keys(row).some(function(key) {
                  return (
                    String(row[key])
                      .toLowerCase()
                      .indexOf(filterKey) > -1
                  );
                });
              });
            }
            if (sortKey) {
              heroes = heroes.slice().sort(function(a, b) {
                a = a[sortKey];
                b = b[sortKey];
                return (a === b ? 0 : a > b ? 1 : -1) * order;
              });
            }
            return heroes;
          }
        },
        filters: {
          capitalize: function(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
          }
        },
        methods: {
          sortBy: function(key) {
            this.sortKey = key;
            this.sortOrders[key] = this.sortOrders[key] * -1;
          }
        }
      });

      // bootstrap the demo
      var demo = new Vue({
        el: "#demo",
        data: {
          searchQuery: "",
          gridColumns: ["name", "power"],
          gridData: [
            { name: "Chuck Norris", power: Infinity },
            { name: "Bruce Lee", power: 9000 },
            { name: "Jackie Chan", power: 7000 },
            { name: "Jet Li", power: 8000 }
          ]
        }
      });
    </script>
  </body>
</html>

/* ./style.css */
body {
  font-family: Helvetica Neue, Arial, sans-serif;
  font-size: 14px;
  color: #444;
}

table {
  border: 2px solid #42b983;
  border-radius: 3px;
  background-color: #fff;
}

th {
  background-color: #42b983;
  color: rgba(255, 255, 255, 0.66);
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

td {
  background-color: #f9f9f9;
}

th,
td {
  min-width: 120px;
  padding: 10px 20px;
}

th.active {
  color: #fff;
}

th.active .arrow {
  opacity: 1;
}

.arrow {
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 0;
  margin-left: 5px;
  opacity: 0.66;
}

.arrow.asc {
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 4px solid #fff;
}

.arrow.dsc {
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid #fff;
}