没组件版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网格组件</title> <link href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet"> <style> #div1 { margin-top: 100px; } </style> </head> <body> <div id="div1" class="container"> <label> serch: <input type="text" v-model="searchQuery"> </label> <table class="table"> <thead class="bg-primary"> <tr> <th>name</th> <th>power</th> </tr> </thead> <tbody> <tr v-for="item in filteredData"> <td>{{item.name}}</td> <td>{{item.power}}</td> </tr> </tbody> </table> </div> </body> <script src="//cdn.bootcss.com/vue/2.1.10/vue.js"></script> <script> var vm = new Vue({ el: '#div1', data: { searchQuery: '', gridData: [ {name: 'Chuck Norris', power: Infinity}, {name: 'Bruce Lee', power: 9000}, {name: 'Jackie Chan', power: 7000}, {name: 'Jet Li', power: 8000} ] }, computed: { filteredData: function () { var data = this.data; var filterKey= this.filterKey&&this.filterKey.toLowerCase(); if (filterKey) { data = data.filter((row) => { return Object.keys(row).some((key) => { return String(row[key]).toLowerCase().indexOf(filterKey) > -1 }) }); } return data; //注意 此处 data 改变,不会影响 gridData /* 简化版本为 var a =[]; var b= a; b=[]//此时a不会变,只是把b重新指向了一个新的内存地址而已 阔以参考 对象 深拷贝浅拷贝 */ /* //比较lou的写法,写两个return, 还要 if else if (this.searchQuery) { return data.filter((row) => { return Object.keys(row).some((key) => { return String(row[key]).indexOf(this.searchQuery) > -1 }) }); }else{ return data; } */ } }, }); var s=[{name:123}] var ss= s; ss.push({name:456}) console.log(ss) console.log(s) </script> </html>
有组件版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网格组件+组件版本</title> <!-- <link href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">--> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> #div1 { margin-top: 100px; } #div1 th[class='active']{ background-color: #a1defc; } #div1 th[class='active'] span[class='caret']{ transform:rotate(-180deg); transition: all 0.3s ease; color: white; } </style> </head> <body> <div id="div1" class="container"> <label> serch:<input type="text" v-model="filterKey"> </label> <demo-grid :data="gridData" :columns="gridColumns" :filter-Key="filterKey" > </demo-grid> </div> </body> <script src="//cdn.bootcss.com/vue/2.1.10/vue.js"></script> <script type="text/x-template" id="grid-template"> <table class="table"> <thead> <tr class="bg-info"> <th v-for="key in columns" @click="sortBy(key)" :class="{active : sortKey == key}"> {{key | capitalize}} <span class="caret"></span> </th> </tr> </thead> <tbody> <tr v-for="entry in filteredData"> <td v-for="key in columns"> {{entry[key]}} </td> </tr> </tbody> </table> </script> <script> Vue.component('demo-grid', { template: '#grid-template', props: { data: Array, columns: Array, filterKey: String }, data: function () { var sortOrders = {}; this.columns.forEach(function (key) { sortOrders[key] = 1 }); return { sortKey: '', sortOrders: sortOrders } }, filters: { capitalize: function (value) { if (!value) return ''; value = value.toString(); return value.charAt(0).toUpperCase() + value.slice(1); } }, methods: { sortBy: function (key) { this.sortKey = key; this.sortOrders[key] = this.sortOrders[key] * -1 } }, computed: { filteredData: function () { let data = this.data; let filterKey = this.filterKey && this.filterKey.toLowerCase(); if (filterKey) { data = data.filter((row) => { return Object.keys(row).some((key) => { return String(row[key]).toLowerCase().indexOf(filterKey) > -1 }) }); } let sortKey = this.sortKey; if (sortKey) { let order = this.sortOrders[sortKey]; data = data.slice().sort((a, b) => { a = a[sortKey]; b = b[sortKey]; return (a === b ? 0 : a > b ? 1 : -1) * order }) } return data; } } }); let vm = new Vue({ el: '#div1', data: { filterKey: '', 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> </html>
官方版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网格组件</title> <style> 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- 120px; padding: 10px 20px; } th.active { color: #fff; } th.active .arrow { opacity: 1; } .arrow { display: inline-block; vertical-align: middle; 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; } </style> </head> <body> <!-- 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 filteredData"> <td v-for="key in columns"> {{entry[key]}} </td> </tr> </tbody> </table> </script> <!-- demo root element --> <div id="demo"> <form id="search"> Search <input name="query" v-model="searchQuery"> </form> <demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery"> </demo-grid> </div> </body> <script src="//cdn.bootcss.com/vue/2.1.10/vue.js"></script> <script> // register the grid component Vue.component('demo-grid', { template: '#grid-template', props: { data: Array, columns: Array, filterKey: String }, data: function () { var sortOrders = {} this.columns.forEach(function (key) { sortOrders[key] = 1 }) return { sortKey: '', sortOrders: sortOrders } }, computed: { filteredData: function () { var sortKey = this.sortKey var filterKey = this.filterKey && this.filterKey.toLowerCase() var order = this.sortOrders[sortKey] || 1 var data = this.data if (filterKey) { data = data.filter(function (row) { return Object.keys(row).some(function (key) { return String(row[key]).toLowerCase().indexOf(filterKey) > -1 }) }) } if (sortKey) { data = data.slice().sort(function (a, b) { a = a[sortKey] b = b[sortKey] return (a === b ? 0 : a > b ? 1 : -1) * order }) } return data } }, 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> </html>