来现在这公司一年了,一年时间里经手做的项目有六七个,不过呢大部分都是一些管理平台的功能,而管理平台做的最多的就是各种表格的展示了,所以在开发过程中,为了提高开发效率,封装一些通用的功能组件是十分有必要的,在这里我就把我在开发过程中所封装的表格组件分享一下,当然肯定是有很多不足的,因为到目前为止我还是有一些想法没有实现的,也希望可以互相交流一下,就当抛砖引玉了,砸到谁也别怨我啊0.0

开发环境

我这边使用的是vue全家桶+ElementUI,毕竟管理平台,没那么高的要求,版本的话随意,毕竟只是说明一种设计方法,通用的

需求分析

管理平台的表格页面一般包含这几部分功能:1.操作按钮(添加,批量删除等);2.表格数据筛选项(常用的有select过滤,时间过滤,搜索过滤等);3.表格主体;4.分页。

1.操作按钮设计

操作按钮的添加我这边想到的有两种方法,第一种:直接使用vue提供的插槽功能,直接在外部定义按钮、样式,以及按钮的操作事件,通过插槽插入组件内部;第二种:组件外部定义一个按钮的对象,通过父子组件通信传递到table组件内部,组件内部对按钮的对象进行解析、渲染,大概格式如下:

[{name: 'addBtn',text: '新增', // 按钮文案icon: 'el-icon-plus', // 按钮图标style: 'primary', // 按钮样式(这里取element的按钮样式)class: 'addBtn', // 自定义按钮classfunc: 'toAdd' // 按钮点击事件}, {name: 'multiDelBtn',text: '批量删除',icon: 'el-icon-delete',style: 'danger',class: 'multiDel',func: 'toMultiDel'}
]
复制代码

2.表格数据筛选项

筛选项的设计没想到有什么好的,就内设几个常用的就上面说的那些,然后通过参数判断是否展示,其他如果有定制需求可以外部定义,然后通过插槽插入

3.表格主体

表格主要包括两部分:表头和表格体,分开分析

表格头我这边设计是在组件外部定义配置项传递组件内部,组件内进行解析,格式如下:

[{prop: 'name', // 表格数据对应的字段label: '用户姓名', // 表格头展示的信息sortable: false,  // 这一列是否支持排序,true|false|'custom',可以不传(为true是前端排序,不过前端排序没什么意义,一半排序的话还是传‘custom’进行服务端排序)minWidth: '100', // 这一列的最小宽度(用minWidth是因为在表格宽度不够的时候有个限制不会变形,在宽度过大的时候又能够按照各列的比例进行伸展,perfect!)}, {prop: 'address',label: '住址',minWidth: '170'}, {prop: 'age',label: '年龄',sortable: 'custom',minWidth: '80'}
]
复制代码

表格体没什么,就参看element-ui的就行

4.分页

分页也没什么好说的,内置在组件内,少于一页不显示,在element组件库选一个自己需要的功能的分页

组件开发

根据需求对组件进行了封装

1.操作按钮设计

<div class="header-operate"><!-- 操作按钮插槽 --><slot name="operateBtn"></slot><el-buttonv-for="(btnItem, btnIndex) in propConfig.btnList":key="btnIndex":class="item.class":type="item.style":icon="item.icon"@click="toEmitFunc(item.func)">{{item.text}}</el-button>
</div>
复制代码

2.筛选项设计

<div class="header-filter"><!-- 筛选项插槽 --><slot name="filter"></slot><el-selectclass="filter-iterm"v-if="propConfig.showFilter"v-model="filter"size="small":placeholder="propConfig.filterPlaceholder":clearable="true"filterable@change="handleSelect"><el-optionv-for="(item, index) in propConfig.filterOptions":key="index":label="item.label":value="item.value"></el-option></el-select><el-date-pickerv-if="propConfig.showDatePick"v-model="dateRange"class="filter-iterm"align="right"size="small"format="timestamp"value-format="timestamp":type="propConfig.datePickType":clearable="true":start-placeholder="propConfig.startPlaceholder":end-placeholder="propConfig.endPlaceholder"@change="handleTimerange"></el-date-picker><el-inputclass="table-search filter-iterm"v-if="propConfig.showSearch"size="small":placeholder="propConfig.searchPlaceholder"v-model="search"@keyup.13.native="toSearch"><i slot="suffix" class="el-input__icon el-icon-search" @click="toSearch"></i></el-input>
</div>
复制代码

3.table主体设计

<el-table:data="tableData.tbody"style="width: 100%"@selection-change="handleSelection"@sort-change="handleSort"><el-table-column v-if="tableData.isMulti" type="selection" width="50"></el-table-column><template v-for="(item, index) in tableData.thead"><el-table-column:key="index":prop="item.prop":label="item.label":width="item.width":min-width="item.minWidth":sortable="item.sortable"><template slot-scope="scope"><span class="default-cell" :title="scope.row[item.prop]">{{scope.row[item.prop]}}</span></template></el-table-column></template>
</el-table>
复制代码

4.分页设计

<el-paginationclass="table-pagination"v-if="tableData.pageInfo.total > tableData.pageInfo.size"layout="total, prev, pager, next, jumper":current-page.sync="tableData.pageInfo.page":page-size="tableData.pageInfo.size":total="tableData.pageInfo.total"@current-change="pageChange"
></el-pagination>
复制代码

5.接受传参与methods

props: {tableConfig: {type: Object,default: () => {return {}}},tableData: {type: Object,default: () => {return {thead: [],tbody: [],isMulti: false, // 是否展示多选pageInfo: { page: 1, size: 10, total: 0 } // 默认一页十条数据}}}
},methods: {toEmitFunc (funName, params) {this.$emit(funName, params)},toSearch () {this.toEmitFunc('setFilter', { search: this.search, page: 1 })},pageChange (val) {this.toEmitFunc('setFilter', { page: val })},handleSelection (val) {let cluster = {id: [],status: [],grantee: [],rows: []}val.forEach(function (element) {cluster.id.push(element.id)cluster.status.push(element.status)cluster.rows.push(element)if (element.grantee) cluster.grantee.push(element.grantee)})this.toEmitFunc('selectionChange', cluster)},handleSort (value) {this.toEmitFunc('setFilter', {prop: value.prop,order: value.order})},handleTimerange () {if (this.dateRange) {this.eventBus('setFilter', {startTime: this.dateRange[0],endTime: this.dateRange[1]})} else {this.eventBus('setFilter', {startTime: '',endTime: ''})}},handleSelect () {this.toEmitFunc('setFilter', {filter: this.filter})}}
复制代码

看到这,你肯定说这不就是element的table的使用吗?嗯...你说的很有道理,我竟无法反驳0.0,下面我就加入一些自己的想法设计吧(づ ̄3 ̄)づ

先写demo,在写的过程中才能一步步完善不足

<!--外部引用文件-->
<template><div class="home"><TableComponent :loading="loading" :tableConfig="tableConfig" :tableData="tableData"/></div>
</template><script>
import TableComponent from '../components/TableComponent'
export default {name: 'home',components: { TableComponent },data () {return {tableConfig: {btnList: [{name: 'addBtn',text: '新增',icon: 'el-icon-plus',style: 'primary',class: 'addBtn',func: 'toAdd'}, {name: 'multiDelBtn',text: '批量删除',icon: 'el-icon-delete',style: 'danger',class: 'multiDel',func: 'toMultiDel'}],showFilter: true,filterOptions: [],showDatePick: true},tableData: {thead: [],tbody: [],isMulti: false,pageInfo: { page: 1, size: 10, total: 0 }},loading: false}},created () {this.toSetTdata()},methods: {toSetTdata () {let that = thisthat.loading = truethat.tableData.thead = [{prop: 'name',label: '用户姓名',minWidth: '100'}, {prop: 'age',label: '年龄',sortable: 'custom',minWidth: '92'}, {prop: 'address',label: '家庭住址',minWidth: '130'}, {prop: 'status',label: '账号状态',minWidth: '100'}, {prop: 'email',label: '邮箱地址',minWidth: '134'}, {prop: 'createdTime',label: '添加时间',minWidth: '128'}]setTimeout(() => {that.tableData.tbody = [{ "id": "810000199002137628", "name": "邓磊", "age": 23, "address": "勐海县", "status": "offline", "email": "y.rbuuy@ndtccqms.lv", "createdTime": 1560218008 },{ "id": "650000197210064188", "name": "蔡刚", "age": 26, "address": "四方台区", "status": "online", "email": "r.ifypqovuzl@rcvfhg.ir", "createdTime": 1500078008 },{ "id": "450000199109254165", "name": "蔡明", "age": 22, "address": "其它区", "status": "online", "email": "z.rbq@uqadfyx.ee", "createdTime": 1260078008 },{ "id": "440000198912192761", "name": "曹明", "age": 25, "address": "其它区", "status": "online", "email": "h.mkmqo@dcj.ee", "createdTime": 1260078008 },{ "id": "310000198807038763", "name": "侯静", "age": 21, "address": "莱城区", "status": "offline", "email": "u.xlkda@ckoicbhk.br", "createdTime": 1560078008 },{ "id": "310000198406163029", "name": "谭涛", "age": 29, "address": "闸北区", "status": "offline", "email": "r.wyr@hmqqlafes.no", "createdTime": 1500078008 },{ "id": "220000199605161598", "name": "罗秀兰", "age": 27, "address": "其它区", "status": "online", "email": "d.eggqvlbol@crqodjvdys.nu", "createdTime": 1560078008 },{ "id": "37000019810301051X", "name": "黎敏", "age": 27, "address": "其它区", "status": "online", "email": "s.unumfugq@qgeufl.om", "createdTime": 1560078008 },{ "id": "440000201411267619", "name": "黄强", "age": 24, "address": "合浦县", "status": "offline", "email": "q.ufollx@kdvgtb.al", "createdTime": 1560218008 },{ "id": "440000200504038626", "name": "叶艳", "age": 25, "address": "大渡口区", "status": "offline", "email": "h.trtiurcut@vnypp.sm", "createdTime": 1560078008 }]that.tableData.isMulti = truethat.tableData.pageInfo = { page: 1, size: 10, total: 135 }that.loading = false}, 500) // 模拟请求延时}}
}
</script>
复制代码

demo写完就发现,很多功能都么得啊,功能很是单一,发现问题:

  • 时间那一列,后端不一定传递过来就是可以直接展示的数据,如果传过来的是个时间戳呢?这时候就需要前端来做一下格式化处理
  • 状态那一列,单纯的文字并不显眼,很多时候需要一个状态标签或者其他样式来展示
  • 我还遇到很多次交互设计要求点击列表中姓名(不一定是姓名,就是某一项点击能进入详情页面)进入该用户的详情页
  • 如果列表内有操作项呢?操作项该如何配置传递到组件内部?

有问题了,一个一个来0.0

第一个:时间那一项需要格式化,在表格中这一列都需要按照同样的方法进行格式化处理,那么我们可以把配置信息放在表头中,然后再表格组件中解析处理,定义formatFn:

{prop: 'createdTime',label: '添加时间',minWidth: '128',formatFn: 'timeFormat'
}
复制代码

组件内添加formatFn判断

<template slot-scope="scope"><spanclass="default-cell"v-if="!item.formatFn || item.formatFn === ''":title="scope.row[item.prop]">{{scope.row[item.prop]}}</span><spanv-else:class="item.formatFn":title="formatFunc(item.formatFn, scope.row[item.prop], scope.row)">{{formatFunc(item.formatFn, scope.row[item.prop], scope.row)}}</span>
</template>
复制代码

添加utils类,编写格式化数据方法,并注册全局

// 格式化方法文件(format.js)(记得要在main.js注册啊)
export default {install (Vue, options) {Vue.prototype.formatFunc = (fnName = 'default', data = '', row = {}) => {const fnMap = {default: data => data,/*** 时间戳转换时间* 接受两个参数需要格式化的数据* 为防止某些格式化的规则需要表格当前行其他数据信息扩展传参row(可不传)*/timeFormat: (data, row) => {return unixToTime(data) // unixToTime是我书写的一个时间戳转时间的方法,如果你项目有引用其他类似方法插件,在这里返回格式化后的数据就可以}}return fnMap[fnName](data, row)}}
}
复制代码

这样如果有其他格式化规则的也可以通过自定义格式化方法,然后再表头中定义需要调用的方法就可以了,同时这个格式化方法不只是可以用在表格中,其他任何你想要进行格式化的地方都可以在这个文件中定义,然后直接使用就可以了,而不用再引入方法再使用,是不是很方便(づ ̄3 ̄)づ

看到这里应该就明白这个table组件的核心其实还是这个格式化方法的使用

继续第二个问题,状态那一列,需要的不只是数据的变化,更是需要将相应的状态数据转换成对应的标签,这就需要扩展一下table组件,添加新的判断逻辑

{prop: 'status',label: '账号状态',minWidth: '100',formatFn: 'formatAccountStatus',formatType: 'dom'
}
复制代码
<template slot-scope="scope"><!--不需要处理--><spanclass="default-cell"v-if="!item.formatFn || item.formatFn === ''":title="scope.row[item.prop]">{{scope.row[item.prop]}}</span><!--需要处理为标签--><spanv-else-if="item.formatType === 'dom'":class="item.formatFn"v-html="formatFunc(item.formatFn, scope.row[item.prop], scope.row)"></span><!--单纯的数据处理--><spanv-else:class="item.formatFn":title="formatFunc(item.formatFn, scope.row[item.prop], scope.row)">{{formatFunc(item.formatFn, scope.row[item.prop], scope.row)}}</span>
</template>
复制代码

我本意是想着format成element-ui的标签,如

但是在写format方法的时候发现直接返回el-tag标签,然后经过v-html解析为html标签但是后面发现并不能按照预期的那样解析成element的标签,思考一番没有发现什么好的方法,没办法只能自己返回原生标签,定义class然后自己书写样式修改为标签的样子

定义状态关系表,添加format方法

const accountStatusMaps = {status: {online: '在线',offline: '离线'},type: {online: 'success',offline: 'warning'}
}
// 用户账号状态转标签
formatAccountStatus: (data, row) => {return `<span class="status-tag ${accountStatusMaps.type[data]}">${accountStatusMaps.status[data]}</span>`
}
复制代码

这样一般的样式format是可以满足了,但是一些比较复杂的需求自己手写样式就比较不方便了,但是我自己一时也没想到好的解决办法,再加上这样比较难搞的需求比较少,所以就一直放着了(可能这就是我技术成长有限的原因吧0.0),各位看官如果有什么好的建议方法的话欢迎来提啊

继续第三项,这个需求在后台管理平台很容易遇到,点击名称进入详情,本来我还是想使用format,format出一个a标签,然后href是想要跳往的地址,但是功能虽然是实现了,但是使用a标签有个很大问题就是页面跳出感太强,只能放弃这个方法,后来没什么好的办法,就想着在表头上做文章,新定义一种formatType => 'link',可选参数linkUrl定义跳转链接,修改table组件的template

<spanv-if="item.formatType === 'link'":class="item.formatClass || 'to-detail-link'":title="scope.row[item.prop]"@click="toLink(item.linkUrl, scope.row)"
>{{scope.row[item.prop]}}</span>
复制代码
toLink (url, row) {if (url) {this.$router.push(`${url}/${row.id}`)} else {this.$router.push(this.$route.path + '/detail/' + row.id)}
}
复制代码
.to-detail-link {color: #1c92ff;cursor: pointer;&:hover {color: #66b1ff;}
}
复制代码

需求满足了,但是只是个妥协之计,该怎么在format返回的标签字符串上面绑定方法呢,如有想法,不胜感激,解决了这个问题能让这组件功能提高一大步,因为这个详情功能还算通用,可以在组件兼容,但是如果是其他点击方法呢?总不能一点点的都兼容,这样就失去了封装组件的意义,因为兼容是兼容不完的。

继续继续,操作项在后台管理平台是不可缺少的,主要的问题就在于怎么传递、抛出点击方法,我这边是这么实现的

先修改template

<span class="table-operation" v-if="item.prop === 'operation' && scope.row.hasOwnProperty('operation')"><spanclass="text-btn"v-for="(item, index) in scope.row.operation":class="item.type":key="index"@click="toEmitFunc(item.event, scope.row)">{{item.text}}</span>
</span>
复制代码

设置操作项数据信息

computed: {operateConfig () {return {optType: {toEdit: {event: 'toEdit', // 操作按钮调用的方法text: '编辑', // 操作按钮展示的文案type: 'primary' // 操作按钮展示的样式},toDel: {event: 'toDel',text: '删除',type: 'danger'}},optFunc: function (row) {// 在线状态用户不能删除if (row.status === 'offline') {return ['toEdit', 'toDel']} else {return ['toEdit']}}}}
}
复制代码

把一些通用的属性、方法抽离出来放在tableMixins里面,减少每次调用的书写

// tableMixins.js
// 表格方法的mixins
export default {data() {return {// 表格数据,具体参考接口数据tableData: {thead: [],tbody: [],isMulti: false,pageInfo: { page: 1, size: 10, total: 0 }},// 表格是否处于loading状态loading: true,// 多选,已选中数据selection: [],// 查询条件,包括排序、搜索以及筛选searchCondition: {}}},mounted: function () { },methods: {// 多选事件, 返回选中的行及每行的当前状态selectionChange(value) {this.selection = value},接口请求到数据后将数据传入这个方法进行thead、tbody、pageInfo等信息的赋值afterListSet(res) {let formData = this.setOperation(res)if (formData.thead) {this.tableData.thead = JSON.parse(JSON.stringify(formData.thead))}this.tableData.tbody = formData.tbodyif (formData.pageInfo) {this.tableData.pageInfo = JSON.parse(JSON.stringify(formData.pageInfo))}formData.isMulti && (this.tableData.isMulti = formData.isMulti)let query = JSON.parse(JSON.stringify(this.$route.query))this.$router.replace({query: Object.assign(query, { page: this.tableData.pageInfo.page })})this.loading = false},// 遍历原始数据,塞入前端定义好的操作项方法序列,设置操作项setOperation(res) {let that = thislet tdata = JSON.parse(JSON.stringify(res))if (that.operateConfig && that.operateConfig.optFunc) {for (let i in tdata.tbody) {let temp = that.operateConfig.optFunc(tdata.tbody[i])let operation = []for (let j in temp) {operation.push(that.operateConfig.optType[temp[j]])}that.$set(tdata.tbody[i], 'operation', operation)}}return tdata}}
}
复制代码

这样一套组合拳下来,管理平台常用的表格功能基本都实现了,贴一下成果图(样式没怎么写,这个就根据自己的项目风格进行调整吧)

我把这个组件的源码上传到了我的GitHub上了,同时写的有demo,有兴趣的朋友可以clone到本地琢磨琢磨,同时欢迎提出代码的不足或者bug,不胜感激0.0,贴上源码地址

思考

组件写完了,文章也水完了,反思一些不足,一个是怎么渲染出UI组件的标签,另一个是怎么在format出来的标签上面绑定方法,诚然组件开发过程中有很多妥协,这些妥协就是自身水平或者视野没能达到导致的恶果,把组件抛出来就是为了集思广益,这个文章对你有帮助,能帮助你提高那我会很高兴,如果你帮忙解决了我遇到的困难,帮助到我的提高那我会更加高兴,我为的不就是这个嘛,所以欢迎大家帮忙想解决方案

当然组件开发过程中我还是做了一些很人性化的设计,一个是提供了多冲筛选条件同时作用的方法,就是维护一个searchCondition,每次筛选起作用就添加到searchCondition中,然后把searchCondition传递给数据查询方法,这个方法可以在demo中尝试,控制台会有输出,另一个小功能就不得不吐槽一下很多开源组件的一个反人类设计,富文本编辑器很多人都用过吧,会有一个menu的配置项,如果这个配置项你什么也不穿他就默认展示全部的菜单项,但是如果你不想要其中一个菜单项,你在menu的配置中把这一项置为false.......然后所有的菜单全没了,我看过一些源码是直接使用传递进去的menu覆盖默认的menu配置项,那么我只是想取消其中一项,我就得把全部的菜单项全部配置一遍且全部置为true,这...不坑爹呢嘛,所以我在向组件内部传参的时候添加了一个方法,而是使用解构赋值,维护一个computed,代码如下:

computed: {propConfig () {// defaultConfig是默认配置项,tableConfig是父组件传递进来的配置项return { ...this.defaultConfig, ...this.tableConfig }}
}
复制代码

这样默认配置项只会在父组件某一项有修改的时候进行变更,其他不变

就这些吧,希望会对大家有所帮助

转载于:https://juejin.im/post/5ce1507551882525d05f7bed

书写一个管理平台开发常用的通用table组件相关推荐

  1. Vue实战(六)通用Table组件

    本文是Vue实战系列的第六篇文章,主要介绍Falcon项目中通用 Table 组件的开发和使用 .Falcon项目地址:https://github.com/thierryxing/Falcon 通用 ...

  2. 基于 OpenFire 的TVBox管理平台开发笔记

    目录 一.開發環境設置.... 3 1.1 JDK 安裝.... 3 1.2 MySql Server安裝.... 4 1.3 OpenFire安裝.... 6 1.4 Openfire Admin ...

  3. 基于 Vue 的学生社团线上管理平台开发与设计

    0 引言 近年来, 各高校为丰富学生的校园生活. 培养学生的个性, 社团与社团人数增加迅速, 需要处理的各类信息也层出不穷, 传统的管理方式已经不利于快捷地处理这些问题. 因此管理不便. 信息错综复杂 ...

  4. 厨卫电器行业B2B交易协同管理平台开发,优化企业库存结构

    后疫情时代,我国厨卫电器行业除集成灶.洗碗机等部分新兴产品外,市场整体呈现低迷状态.这样的状态一方面是由于疫情影响造成的市场扰动,但最根本的还是厨卫电器行业进入到了存量市场,市场竞争愈加激烈,企业稍有 ...

  5. 物联网开发智慧城镇管理平台开发

    智慧城镇综合管理平台面向政府机关部门. 过登录后台界面,可以宏观调控各种资源;合理安排各部门分工合作. 在各种紧急事件发生时,可以快速反应,精准定位并作出相应对策,大幅度降低人员伤亡和财产损失. 将互 ...

  6. 新闻舆情管理平台开发,监控舆情发展趋势

    打造企业良好声誉可能需要几年.十几年甚至更久,而毁掉它只需要短短几分钟.尤其是互联网时代下,人们接收信息的速度越来越快,在新闻发出去的几分钟内就能迅速占据热搜榜.而且网络上每天都会产生上亿条信息,单纯 ...

  7. php应用开发综合课程设计,学生综合测评管理平台开发(PHP)

    摘要:当前我国普通高校综合测评管理方式大多还停留在纸质的基础上, 已经不能适应信息时代的发展.文章结合当前高校的实际情况, 利用PHP语言和My SQL数据库构建一套符合综合测评要求的信息化系统. 关 ...

  8. Django轻量级任务追踪管理平台开发:二

    文章目录 今日内容 一.效果展示 二.代码展示 1.从主页进入后台 2.后台页面 2.1 后台界面路由 2.2 后台视图函数 2.3 前端模板 3.新建项目 3.1 表设计 3.2 新建按钮和模态框 ...

  9. JAVA三维可视化组件:Matplot 3D for JAVA(V3.0) 一个纯JAVA开发的科学数据可视化组件包 类似 Python 的matplotlib(含示例代码)

    目录 概述 组件下载及项目地址 效果展示和示例代码 概述 Matplot3D for JAVA(V3.0) 是一个基于JAVA SE 1.8环境开发的三维图形图表组件. 组件由纯JAVA SE 实现( ...

最新文章

  1. Strong Consistency, 强一致性技术概述
  2. Spring Boot 项目的这些文件都是干啥用的?
  3. 托管元数据(2)——托管元数据和搜索中的精简面板
  4. CTF---Web入门第八题 Guess Next Session
  5. Intel张旭:通信和计算的融合将是5G的关键
  6. 中国的脑部研究--脑网络组图谱
  7. 2013-09-16 构建C1000K的服务器(1) – 基础
  8. 产生式系统的基本概念
  9. 如何让电脑的开机速度变快?
  10. XCode11中The app delegate must implement the window property if it wants to use 如何解决
  11. linear-gradient实现纯CSS文字淡入效果
  12. 毕业论文设计:第二部分—激光雷达里程计研究
  13. 一、首页第一个首页栏制作【仿淘票票系统前后端完全制作(除支付外)】
  14. KK今年生日又给了103个建议,我最喜欢这33个
  15. idea Compound 一次启动多个应用
  16. 【JavaWeb学习笔记】TCP/IP 协议(三)
  17. 《六顶思考帽》读后感
  18. Flarum常用插件汇总
  19. Warcraft III 分辨率设置
  20. PPT设置动画:点击一次鼠标,显示一部分内容

热门文章

  1. python并发处理list数据_python之并发基础(进程)
  2. 简析TCP的三次握手与四次分手原理
  3. (网络速度)电信拉的100M光纤,测试峰值速度只有12M/s
  4. 硬件速攻-ST7735 0.96LCD屏幕
  5. [内网安全]四.内网信息收集--BloodHound工具与PowerShell工具的使用
  6. 异步升压LED驱动IC7209
  7. [UVa 1610] 聚会游戏(Party Games)
  8. hive中的 lateral view
  9. cpio.gz格式小系统
  10. 猿创征文|工具百宝箱-编辑器-笔记工具-日常小工具-原型设计工具