php动态网站建设/百度投放广告收费标准
下面的处理方式只针对自己遇到的问题,能否使用还是要看实际情况!切记!切记!希望有帮助
标题
- 缘起
- 吐槽
- 一、工作需要
- 二、实际官网实现
- 三、官网中的问题
- 四、改进后效果
- 五、分页添加原理(忘记为什么没用uni的分页了)
- 六、选择修改原理(自觉比较简单粗暴)
- 孽缘啊
- 一、分页pageHelper代码
- 二、选择的实现
- 缘落
缘起
吐槽
源码是真乱,好多变量都是null或者undefined,不知道写的时候怎样下去的,比如root、parent…其实好多都没取到。不过要我的话也写不出来
o(╥﹏╥)o
一、工作需要
uniapp项目数据列表需要分页。分页后还要实现选择和全选
二、实际官网实现
uni-table数据用于移动端,数据一般是向上滑,下方自动加载出现新数据。
unitable组件中的介绍包含分页处理,但是选择了之后,跳到其它页,直接将选择的数据清空了,而且函数selection-change携带的参数只有数据的index值,无实际数据。
三、官网中的问题
- uni-table数据无分页
- uni-table数据分页后,第一页选择完数据后,跳转其它页,数据丢失
- uni-table选择时,使用index值判断选择的数据。用户添加分页功能后,就会导致每页的index值都从0开始
四、改进后效果
- uni-table数据受分页控制,添加了分页功能
- uni-tr与uni-table源码修改,将 id_own(数据的主键,使用的话,这个主键要改成对应的) 作为数据的标志,不使用index判断选择与否。
- selection-change既返回了选择数据的主键数组,也返回了选择的数据集。(但我这边只需要主键数组,且在调用uni-table之前就已有了,所以没用这个方法。自觉使用的话,还是要根据实际情况修改)
五、分页添加原理(忘记为什么没用uni的分页了)
首先,要有分页三要素:total、pageSize、pageCurrent。
取出所有数据放在【baseList】中,自己写了【pageHelper】,根据【baseList】、【pageSize】、【pageCurrent】截取数据返回。【pageHelper】就用了最简单的数组的截取,代码在下面
六、选择修改原理(自觉比较简单粗暴)
修改时主要有两个问题:
- 怎样判断选择的数据有哪些
- 选择的数据前选择框的样式改变
解决方法:
- 将数据的id_own放在数组array中,根据id_own执行导出或者修改或者其他功能
- 该问题是修改的源码,uni-table源码中有个【check】方法,无论点击哪个选择框,都会触发,在方法中判断是单个选择还是批量选择。单个选择会直接往下走,批量选择会走批量选择的方法【selectionAll】,批量取消选择走【clearSelection】。
child:选择的数据
check;true为选择,false为取消选择。感觉没必要,直接数据的cheked值取反就可以了,但是怕源码开发人员想到的情况自己没想到的,所以没大改
keyValue:数据的Index值,修改后这里改为自己数据的主键id_own,点击表头的选择框,传空字符串
emit:布尔类型的值,没确定是什么,但不影响。check(child, check, keyValue, emit)
对外抛出的方法为【toggleRowSelection】,官网中显示微信小程序不支持,但看其他同门的反馈,是可以使用的。这个方法中修改的有参数和id_won相关。且在页码发生变化时,会调用一下,去渲染新页码中的选择框样式。
row:源码中为选择数据的index值
selected:表示是选择还是取消选择。感觉没必要,直接数据的cheked值取反就可以了,但是怕源码开发人员想到的情况自己没想到的,所以没大改toggleRowSelection(row, selected)
孽缘啊
一、分页pageHelper代码
// arrayList : 包含全部数据的数据源。无论是有搜索还是其他操作,只要将其他条件处理完后的数据源作arrayList即可
// pageSize : 每页数据条数
// pageCurrent : 当前页页码export function pageHelper(arrayList, pageSize, pageCurrent) {const leftInterval = pageSize * (pageCurrent - 1) + 1 // 左区间const rightInterval = pageSize * (pageCurrent - 1) + pageSize //右区间let returnList = [] // 要返回的数组// slice方法只会获取到右区间索引的前一位if (arrayList.length - 1 >= rightInterval) {returnList = arrayList.slice(leftInterval - 1, rightInterval)} else {returnList = arrayList.slice(leftInterval - 1, arrayList.length)}return returnList
}
// 为使用方便,将该方法放于vue的prototype中。
import {pageHelper
} from "@/common/pageHelper.js" // 文件位置
Vue.prototype.$pageHelper = pageHelper;
// 使用方法
this.$pageHelper(arrayList,pageSize,pageCurrent)
二、选择的实现
// 自己的table.vue文件<uni-table ref="uniTable" type="selection"> // 一定要给一个ref名,以便调用toggleRowSelection<uni-tr @row-click="rowClick(-1)">表头</uni-tr> // 这里-1作表头的id_own// 这有点坑,使用v-for,给其key时,直接用key,uni-tr组件得不到,将其设为key-value就可以了,源码中有。row-click也是后来加的<uni-tr v-for="(item,index) in dataList" :key-value="item.id_own" @row-click="rowClick(item.id_own)">数据</uni-tr>
</uni-table><script>
data() {return {selectedIdOwnArr:[]}
}
methods:{rowClick(selectedId) {if (selectedId != -1) {// 全选if (this.selectedIdOwnArr.indexOf(selectedId) != -1) {this.selectedIdOwnArr.splice(this.selectedIdOwnArr.indexOf(selectedId), 1)} else {this.selectedIdOwnArr.push(selectedId)}} else {// 单选if (this.dataList.length > 0) {let singleArray = this.dataList.map(item => item.id_own)this.selectedIdOwnArr = this.selectedIdOwnArr.concat(singleArray)}}if (this.selectedIdOwnArr.length > 0) {// 对选择的数据处理}},
}
</script>
// uni-tr文件:getRow方法是新增的,对应row-click方法;checkboxSelected方法是修改过的。标注“原版”的为初始代码<template><!-- #ifdef H5 --><tr class="uni-table-tr">// 这里对应表头的选择框<th v-if="selection === 'selection' && ishead" class="checkbox" :class="{ 'tr-table--border': border }"@click="getRow"><table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled"@checkboxSelected="checkboxSelected"></table-checkbox></th><slot></slot><!-- <uni-th class="th-fixed">123</uni-th> --></tr><!-- #endif --><!-- #ifndef H5 -->// 这里对应数据的选择框<view class="uni-table-tr" @click="getRow"><view v-if="selection === 'selection' " class="checkbox" :class="{ 'tr-table--border': border }"><table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled"@checkboxSelected="checkboxSelected"></table-checkbox></view><slot></slot></view><!-- #endif -->
</template><script>import tableCheckbox from './table-checkbox.vue'/*** Tr 表格行组件* @description 表格行组件 仅包含 th,td 组件* @tutorial https://ext.dcloud.net.cn/plugin?id=*/export default {name: 'uniTr',components: {tableCheckbox},props: {disabled: {type: Boolean,default: false},keyValue: {type: [String, Number],default: ''}},options: {virtualHost: true},data() {return {value: false,border: false,selection: false,widthThArr: [],ishead: true,checked: false,indeterminate: false}},created() {this.root = this.getTable()this.head = this.getTable('uniThead')if (this.head) {this.ishead = falsethis.head.init(this)}this.border = this.root.borderthis.selection = this.root.typethis.root.trChildren.push(this)const rowData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)if (rowData) {this.rowData = rowData}this.root.isNodata()},mounted() {if (this.widthThArr.length > 0) {const selectionWidth = this.selection === 'selection' ? 50 : 0this.root.minWidth = this.widthThArr.reduce((a, b) => Number(a) + Number(b)) + selectionWidth}},// #ifndef VUE3destroyed() {const index = this.root.trChildren.findIndex(i => i === this)this.root.trChildren.splice(index, 1)this.root.isNodata()},// #endif// #ifdef VUE3unmounted() {const index = this.root.trChildren.findIndex(i => i === this)this.root.trChildren.splice(index, 1)this.root.isNodata()},// #endifmethods: {minWidthUpdate(width) {this.widthThArr.push(width)},// 选中 -- 原版// checkboxSelected(e) {// let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)// this.checked = e.checked// this.root.check(rootData || this, e.checked, rootData ? this.keyValue : null)// },checkboxSelected(e) {// 这里这个this.root.data就是个undefined,根本就取不到let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)this.checked = e.checkedthis.root.check(rootData || this, e.checked, this.keyValue)},change(e) {this.root.trChildren.forEach(item => {if (item === this) {this.root.check(this, e.detail.value.length > 0 ? true : false)}})},/*** 获取父元素实例*/getTable(name = 'uniTable') {let parent = this.$parentlet parentName = parent.$options.namewhile (parentName !== name) {parent = parent.$parentif (!parent) return falseparentName = parent.$options.name}return parent},getRow() {this.$emit("row-click")}}}
</script><style lang="scss">$border-color: #ebeef5;.uni-table-tr {/* #ifndef APP-NVUE */display: table-row;transition: all 0.3s;box-sizing: border-box;/* #endif */}.checkbox {padding: 0 8px;width: 26px;padding-left: 12px;/* #ifndef APP-NVUE */display: table-cell;vertical-align: middle;/* #endif */color: #333;font-weight: 500;border-bottom: 1px $border-color solid;font-size: 14px;// text-align: center;}.tr-table--border {border-right: 1px $border-color solid;}/* #ifndef APP-NVUE */.uni-table-tr {::v-deep .uni-table-th {&.table--border:last-child {// border-right: none;}}::v-deep .uni-table-td {&.table--border:last-child {// border-right: none;}}}/* #endif */
</style>
// uni-table文件:标注“原版”为初始代码
<template><view class="uni-table-scroll" :class="{ 'table--border': border, 'border-none': !noData }"><!-- #ifdef H5 --><table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }":style="{ 'min-width': minWidth + 'px' }"><slot></slot><view v-if="noData" class="uni-table-loading"><view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view></view><view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view></table><!-- #endif --><!-- #ifndef H5 --><view class="uni-table" :style="{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }"><slot></slot><view v-if="noData" class="uni-table-loading"><view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view></view><view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view></view><!-- #endif --></view>
</template><script>/*** Table 表格* @description 用于展示多条结构类似的数据* @tutorial https://ext.dcloud.net.cn/plugin?id=3270* @property {Boolean} border 是否带有纵向边框* @property {Boolean} stripe 是否显示斑马线* @property {Boolean} type 是否开启多选* @property {String} emptyText 空数据时显示的文本内容* @property {Boolean} loading 显示加载中* @event {Function} selection-change 开启多选时,当选择项发生变化时会触发该事件*/export default {name: 'uniTable',options: {virtualHost: true},emits: ['selection-change'],props: {data: {type: Array,default () {return []}},// 是否有竖线border: {type: Boolean,default: false},// 是否显示斑马线stripe: {type: Boolean,default: false},// 多选type: {type: String,default: ''},// 没有更多数据emptyText: {type: String,default: '没有更多数据'},loading: {type: Boolean,default: false},rowKey: {type: String,default: ''}},data() {return {noData: true,minWidth: 0,multiTableHeads: []}},watch: {loading(val) {},/*** @param {Object} newVal --原版*/// data(newVal) {// let theadChildren = this.theadChildren// let rowspan = 1// if (this.theadChildren) {// rowspan = this.theadChildren.rowspan// }// // this.trChildren.length - rowspan// this.noData = false// // this.noData = newVal.length === 0 // }/*** 这个其实根本没有,所以监听不到,*/data: {handler(newVal) {let theadChildren = this.theadChildrenlet rowspan = 1if (this.theadChildren) {rowspan = this.theadChildren.rowspan}// this.trChildren.length - rowspanthis.noData = false// this.noData = newVal.length === 0 },deep: true}},created() {// 定义tr的实例数组this.trChildren = []this.thChildren = []this.theadChildren = nullthis.backData = []this.backIndexData = []},methods: {isNodata() {let theadChildren = this.theadChildrenlet rowspan = 1if (this.theadChildren) {rowspan = this.theadChildren.rowspan}this.noData = this.trChildren.length - rowspan <= 0},// /**// * 选中所有 --原版// */// selectionAll() {// let startIndex = 1// let theadChildren = this.theadChildren// if (!this.theadChildren) {// theadChildren = this.trChildren[0]// } else {// startIndex = theadChildren.rowspan - 1// }// let isHaveData = this.data && this.data.length.length > 0// theadChildren.checked = true// theadChildren.indeterminate = false// this.trChildren.forEach((item, index) => {// if (!item.disabled) {// item.checked = true// if (isHaveData && item.keyValue) {// const row = this.data.find(v => v[this.rowKey] === item.keyValue)// if (!this.backData.find(v => v[this.rowKey] === row[this.rowKey])) {// this.backData.push(row)// }// }// if (index > (startIndex - 1) && this.backIndexData.indexOf(index - startIndex) === -1) {// this.backIndexData.push(index - startIndex)// }// }// })// // this.backData = JSON.parse(JSON.stringify(this.data))// this.$emit('selection-change', {// detail: {// value: this.backData,// index: this.backIndexData// }// })// },/*** 选中所有*/selectionAll() {let startIndex = 1let theadChildren = this.theadChildrenif (!this.theadChildren) {theadChildren = this.trChildren[0]} else {startIndex = theadChildren.rowspan - 1}theadChildren.checked = truetheadChildren.indeterminate = falsethis.trChildren.forEach((item, index) => {if (!item.disabled) {item.checked = trueif (typeof item.keyValue == 'number') {this.backIndexData.push(item.keyValue)this.backData.push(item)}}})this.$emit('selection-change', {detail: {value: this.backData,index: this.backIndexData}})},/** -- 原版* 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)*/// toggleRowSelection(row, selected) {// // if (!this.theadChildren) return// row = [].concat(row)// this.trChildren.forEach((item, index) => {// // if (item.keyValue) {// const select = row.findIndex(v => {// //// if (typeof v === 'number') {// return v === index - 1// } else {// return v[this.rowKey] === item.keyValue// }// })// let ischeck = item.checked// if (select !== -1) {// if (typeof selected === 'boolean') {// item.checked = selected// } else {// item.checked = !item.checked// }// if (ischeck !== item.checked) {// this.check(item.rowData||item, item.checked, item.rowData?item.keyValue:null, true)// }// }// // }// })// this.$emit('selection-change', {// detail: {// value: this.backData,// index:this.backIndexData// }// })// },/*** 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)* @param {Array} row 选择的数据的id_own数组* @param {boolean} selected 选择还是取消选择*/toggleRowSelection(row, selected) {this.trChildren.forEach((item, index) => {const select = row.findIndex(v => {return v === item.keyValue})if (select !== -1) {if (typeof selected === 'boolean') {item.checked = selected} else {item.checked = !item.checked}this.check(item.rowData || item, item.checked, item.keyValue,true)} else {item.checked = false}})},/*** 用于多选表格,清空用户的选择*/clearSelection() {let theadChildren = this.theadChildrenif (!this.theadChildren) {theadChildren = this.trChildren[0]}// if (!this.theadChildren) returntheadChildren.checked = falsetheadChildren.indeterminate = falsethis.trChildren.forEach(item => {item.checked = false})this.backData = []this.backIndexData = []this.$emit('selection-change', {detail: {value: [],index: []}})},/*** 用于多选表格,切换所有行的选中状态 -- 原版,这个方法没用*/// toggleAllSelection() {// let list = []// let startIndex = 1// let theadChildren = this.theadChildren// if (!this.theadChildren) {// theadChildren = this.trChildren[0]// } else {// startIndex = theadChildren.rowspan - 1// }// this.trChildren.forEach((item, index) => {// if (!item.disabled) {// if (index > (startIndex - 1)) {// list.push(index - startIndex)// }// }// })// this.toggleRowSelection(list)// },/*** 选中\取消选中* @param {Object} child ,这是选中的某条数据* @param {Object} check ,选中为true,取消选中为false.* @param {Object} keyValue ,这里就是数据的id_own,表头是空字符串* @param {Object} emit * 通过emits将这两个对象给selection_change* @return {Object} backData , 选中的数据对象* @return {Object} backIndexData , 选中的数据id_own数组* * 根据keyValue判断这条数据有无被选中*/check(child, check, keyValue, emit) {let theadChildren = this.theadChildren // 这里应该是选择框的thead位置if (!this.theadChildren) { // 这里应该是表头的选择框,全选或者取消全选theadChildren = this.trChildren[0]}// 全选或者取消全选if (keyValue == "") {check ? this.selectionAll() : this.clearSelection()return}//单独选择或者取消选择时会走这儿,全选或者全部取消选择,不过来if (check) { // 选中if (keyValue && this.backData.indexOf(child) == -1) { // this.backData.push(child)}// 如果是选中,将数据的id_own放入this.backIndexDataif (this.backIndexData.indexOf(keyValue) == -1) {this.backIndexData.push(keyValue)}} else { //取消选中,将两个对象中已有的数据清除const index = this.backData.findIndex(v => v === child)const idx = this.backIndexData.findIndex(item => item === keyValue)if (index != -1) {this.backData.splice(index, 1)}if (idx != -1) {this.backIndexData.splice(idx, 1)}}const domCheckAll = this.trChildren.find((item, index) => item.keyValue == keyValue)if (!domCheckAll) {theadChildren.indeterminate = falsetheadChildren.checked = true} else {theadChildren.indeterminate = truetheadChildren.checked = false}if (this.backIndexData.length === 0) {theadChildren.indeterminate = false}// 这里要再确认一下emit是什么时候有,什么时候没有if (!emit) {this.$emit('selection-change', {detail: {value: this.backData,index: this.backIndexData}})}}/*** 选中\取消选中 -- 原版* @param {Object} child* @param {Object} check* @param {Object} rowValue*/// check(child, check, keyValue, emit) {// let theadChildren = this.theadChildren// if (!this.theadChildren) {// theadChildren = this.trChildren[0]// }// let childDomIndex = this.trChildren.findIndex((item, index) => child === item)// if(childDomIndex < 0){// childDomIndex = this.data.findIndex(v=>v[this.rowKey] === keyValue) + 1// }// const dataLen = this.trChildren.filter(v => !v.disabled && v.keyValue).length// if (childDomIndex === 0) {// check ? this.selectionAll() : this.clearSelection()// return// }// if (check) {// if (keyValue) {// this.backData.push(child)// }// this.backIndexData.push(childDomIndex - 1)// } else {// const index = this.backData.findIndex(v => v[this.rowKey] === keyValue)// const idx = this.backIndexData.findIndex(item => item === childDomIndex - 1)// if (keyValue) {// this.backData.splice(index, 1)// }// this.backIndexData.splice(idx, 1)// }// const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.checked && !item.disabled)// if (!domCheckAll) {// theadChildren.indeterminate = false// theadChildren.checked = true// } else {// theadChildren.indeterminate = true// theadChildren.checked = false// }// if (this.backIndexData.length === 0) {// theadChildren.indeterminate = false// }// if (!emit) {// this.$emit('selection-change', {// detail: {// value: this.backData,// index: this.backIndexData// }// })// }// }}}
</script><style lang="scss">$border-color: #ebeef5;.uni-table-scroll {width: 100%;/* #ifndef APP-NVUE */// overflow-x: auto;/* #endif */}.uni-table {position: relative;width: 100%;border-radius: 5px;// box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);background-color: #fff;/* #ifndef APP-NVUE */box-sizing: border-box;display: table;overflow-x: auto;::v-deep .uni-table-tr:nth-child(n + 2) {&:hover {background-color: #f5f7fa;}}::v-deep .uni-table-thead {.uni-table-tr {// background-color: red;&:hover {background-color: #fafafa;}}}/* #endif */}.table--border {border: 1px #d0d0d0 solid;border-right: none;}.border-none {/* #ifndef APP-NVUE */border-bottom: none;/* #endif */}.table--stripe {/* #ifndef APP-NVUE */::v-deep .uni-table-tr:nth-child(2n + 3) {background-color: #fafafa;}/* #endif */}/* 表格加载、无数据样式 */.uni-table-loading {position: relative;/* #ifndef APP-NVUE */display: table-row;/* #endif */height: 50px;line-height: 50px;overflow: hidden;box-sizing: border-box;}.empty-border {border-right: 1px $border-color solid;}.uni-table-text {position: absolute;right: 0;left: 0;text-align: center;font-size: 14px;color: #999;}.uni-table-mask {position: absolute;top: 0;bottom: 0;left: 0;right: 0;background-color: rgba(255, 255, 255, 0.8);z-index: 99;/* #ifndef APP-NVUE */display: flex;margin: auto;transition: all 0.5s;/* #endif */justify-content: center;align-items: center;}.uni-table--loader {width: 30px;height: 30px;border: 2px solid #aaa;// border-bottom-color: transparent;border-radius: 50%;/* #ifndef APP-NVUE */animation: 2s uni-table--loader linear infinite;/* #endif */position: relative;}@keyframes uni-table--loader {0% {transform: rotate(360deg);}10% {border-left-color: transparent;}20% {border-bottom-color: transparent;}30% {border-right-color: transparent;}40% {border-top-color: transparent;}50% {transform: rotate(0deg);}60% {border-top-color: transparent;}70% {border-left-color: transparent;}80% {border-bottom-color: transparent;}90% {border-right-color: transparent;}100% {transform: rotate(-360deg);}}
</style>
缘落
以上就是修改的内容,内心认为修改问题要从源头开始,像uni-table中的data、root…根本没传过来的,没有数据的,为null或者undefined的,还是要根据组件间的关系找下源头,为什么没传过来。纵使自己写不出来吧,但是不应该对自己的作品负责吗,官网上都有逻辑问题,也不及时修改。哼!
希望可以对其他同门有帮助。