vue组件的创建和使用

1.src文件夹下的components-》table -》index.js

import MTable from './table.vue';
import MyTable from './table1.vue';

export default (Vue)=>{
Vue.component("MTable", MTable);
Vue.component("myTable", MyTable)
}

2.src文件夹下的components-》table -》table1.vue

/**
* 自定义table组件
********** columns:表头信息 **********
* @type: index -- 序号
* checkbox -- 多选框
* date -- 日期组件
* imgUpdata -- 图片上传
* select -- 下拉框
* button -- 按钮
* @width: 宽
* @title: 表头
* @thClass: 表头class
* @tdClass: 表列class
* @key: 字段名
* @onBlur: 失焦事件
* @onChange: change事件
* @onClick: click事件
* @tdClass: 表列class
* @option:{
optionList:下拉框的列表
optionValueKey: 绑定的value值得字段名,
optionLabelKey: [],数组最多2个label字段名
* }
* @filterable: 下拉框可搜索
* @disabled: 下拉框禁用
* @clearable: 可清空下拉框内容
* @butTitle: button名
*CheckboxGroup 是一个多选框组件
* 注:optionList必须获取到list再赋值
***************** tableData:列表数据 **********
******* tableCheck:多选框绑定行的index ********
***********************************************
* 具体参考addAdvanceOrde.vue文件 *
***********************************************
*/
<template>
<div class="me-table">
< CheckboxGroup v-model="selections" @on-change="selectionsChange">
<div class="ivu-table-wrapper" :style="height ? {height: height + 'px'} : ''">
<div class="ivu-table ivu-table-small ivu-table-border ivu-table-with-fixed-top" style="overflow:auto;min-height:80px">
<table cellspacing="0" cellpadding="0" border="0" style="width: 100%;">
<thead class="ivu-table-header">
<tr>
<th style="white-space: normal" class="ivu-table-column-center" v-for="(item, index) in columns" :width="item.width" :class="item.thClass">
<span v-if="item.type === 'index'">#</span>
<span v-else-if="item.type === 'checkbox'">选择</span>
<span v-else>{{item.title}}</span>
<span v-if="item.copyIcon">
<Icon type="ios-copy-outline" size="17" class="copyIcon" @click="copyFun(item.key)"></Icon>
</span>
</th>
</tr>
</thead>
<tbody class="ivu-table-tbody">
<tr class="ivu-table-row" v-for="(trItem, trIndex) in tableData">
<td class="ivu-table-column-center" v-for="(tdItem, tdIndex) in columns" :class="tdItem.tdClass">
<span v-if="tdItem.type === 'index'">{{trIndex + 1}}</span>
<span v-else-if="tdItem.type === 'checkbox'">
<Checkbox :label="trIndex"><span> </span></Checkbox>
</span>
<!-- tdItem.type === 'input' && tdItem.onChange 是判断使用组件页面的:columns="columnsEdit"中对象中的type:是否为input 并且有onChange属性
调用组件的页面
<my-table v-if="btnType[0]" :columns="columnsEdit" :tableData="tableData" :tableCheck="selects" height="650"></my-table>
this.columnsEdit = [
{
title: '工厂报价',
type: 'input',
width: '130',
key: 'factoryQuote',
thClass: 'headerColor',
inputClass: this.message === 1 ? 'table_input normal_1 input_color1' : this.message === 2 ? 'table_input normal_1 input_color2' : 'table_input normal_1',
placeholder: this.message === 2 ? '未查询到核价单' : this.message === 1 ? '查询到多条结果请确认' : '',
onBlur: this.factoryQuoteChange,
onKeyUp: this.show,
copyIcon: true
}
]
 
-->
<span v-else-if="tdItem.type === 'input' && tdItem.onChange">
<Input v-model="trItem[tdItem.key]" :placeholder="tdItem.placeholder" @on-change="tdItem.onChange(trItem, trIndex)" />
</span>
<span v-else-if="tdItem.type === 'input' && tdItem.onKeyUp">
<Input v-model="trItem[tdItem.key]" :placeholder="tdItem.placeholder" :class="tdItem.inputClass" @keyup.native="tdItem.onKeyUp($event, trItem, trIndex)" />
</span>
<span v-else-if="tdItem.type === 'input' && tdItem.onKeyUp && tdItem.onBlur">
<Input v-model="trItem[tdItem.key]" :placeholder="tdItem.placeholder" :class="tdItem.inputClass" @on-blur="tdItem.onBlur(trItem, trIndex)" @keyup.native="tdItem.onKeyUp($event, trItem, trIndex)" />
</span>
<span v-else-if="tdItem.type === 'input' && tdItem.onBlur">
<Input v-model="trItem[tdItem.key]" :placeholder="tdItem.placeholder" @on-blur="tdItem.onBlur(trItem, trIndex)" />
</span>
<span v-else-if="tdItem.type === 'input' && !tdItem.onChange && !tdItem.onBlur && !tdItem.onKeyUp">
<Input v-model="trItem[tdItem.key]" :placeholder="tdItem.placeholder" :maxlength="tdItem.maxlength" />
</span>
<span v-else-if="tdItem.type === 'select' && tdItem.onChange">
<Select ref="select" v-model="trItem[tdItem.key]" @on-change="tdItem.onChange(trItem, trIndex)" :filterable="tdItem.filterable" :disabled="tdItem.disabled"
:clearable="tdItem.clearable">
<Option v-for="item in tdItem.option.optionList" :value="item[tdItem.option.optionValueKey]" :key="item[tdItem.option.optionKey]?item[tdItem.option.optionKey]:item[tdItem.option.optionValueKey]"
:label="tdItem.option.optionLabelKey.length === 1 ? item[tdItem.option.optionLabelKey[0]] : tdItem.option.optionLabelKey.length === 2 ?item[tdItem.option.optionLabelKey[0]] + '-' + item[tdItem.option.optionLabelKey[1]]:item[tdItem.option.optionLabelKey[0]] + '-' + item[tdItem.option.optionLabelKey[1]]+'-'+item[tdItem.option.optionLabelKey[2]]"></Option>
</Select>
</span>
<span v-else-if="tdItem.type === 'select' && !tdItem.onChange">
<Select ref="select1" v-model="trItem[tdItem.key]" :filterable="tdItem.filterable" :disabled="tdItem.disabled" :clearable="tdItem.clearable">
<Option v-for="item in tdItem.option.optionList" :value="item[tdItem.option.optionValueKey]" :key="item[tdItem.option.optionKey]?item[tdItem.option.optionKey]:item[tdItem.option.optionValueKey]"
:label="tdItem.option.optionLabelKey.length === 1 ? item[tdItem.option.optionLabelKey[0]] : tdItem.option.optionLabelKey.length === 2 ?item[tdItem.option.optionLabelKey[0]] + '-' + item[tdItem.option.optionLabelKey[1]]:item[tdItem.option.optionLabelKey[0]] + '-' + item[tdItem.option.optionLabelKey[1]]+'-'+item[tdItem.option.optionLabelKey[2]]"></Option>
</Select>
</span>
<span v-else-if="tdItem.type === 'button'">
<Button type="info" @click="tdItem.onClick(trItem, trIndex)" size="small">{{tdItem.butTitle}}</Button>
</span>
<span v-else v-html="trItem[tdItem.key]"></span>
</td>
</tr>
</tbody>
</table>
<div v-if="!tableData.length" class="no-data">暂无数据</div>
</div>
</div>
</CheckboxGroup>
</div>
</template>

<script>
import {
getImgBlobSrc
} from '@/libs/util'

export default {
//导出的tableData columns tableCheck....都是需要父页面传的数据,(:绑定的数据)
name: 'myTable',
props: {
// 选择供应商之后增加明细的数据(更改供应商时可以获取到该数据)
tableData: {
type: Array,
default () {
return []
}
},
height: {
type: String
},
// 点击增加明细之后 弹框确定之后需要添加的table数据
columns: {
type: Array,
default () {
return []
}
},
tableCheck: {
type: Array,
default () {
return []
}
}
},
data() {
return {
modelData: [],
selections: this.tableCheck,
imgIndex: '',
imgKey: ''
}
},
mounted() {
let self = this
this.$(".ivu-table-row").hover(function () {
self.$(this).addClass('ivu-table-row-hover')
}, function () {
self.$(this).removeClass('ivu-table-row-hover')
})
},
methods: {
selectionsChange() {
this.tableCheck.splice(0, this.tableCheck.length)
this.selections.forEach(ele => {
this.tableCheck.push(ele)
})
},
copyFun(key) {
if(key === 'qualifiedQuantity'){
this.tableData.forEach(ele => {
this.$set(ele, key, ele.quantity)
ele.unqualifiedQuantity = ele.qualifiedQuantity && ele.quantity ? Number(ele.quantity) - Number(ele.qualifiedQuantity) : ''
})
return
}
if (!this.tableData[0][key] && this.tableData[0][key] != 0) {
this.$Message.warning('第一行值为空,不能复制!')
return
}
this.tableData.forEach(ele => {
this.$set(ele, key, this.tableData[0][key])
})
if (key === 'taxUnitPrice' || key === 'taxRate') {
this.tableData.forEach(ele => {
if ((ele.taxUnitPrice || ele.taxUnitPrice == 0) && (ele.taxRate || ele.taxRate == 0)) {
let unitPrice = ele.taxUnitPrice / (1 + ele.taxRate / 100)
this.$set(ele, 'unitPrice', unitPrice.toFixed(4))
}
})
}
},
uploadImg(file) {
let formData = new FormData()
formData.append('file', file)
this.$axios({
url: '/chenfan_api/file/upload',
method: 'post',
data: formData
}).then((data) => {
if (data.code === 200) {
this.$set(this.tableData[this.imgIndex], [this.imgKey], data.obj[0].id)
}
})
return false
},
getImgIndex(index, key) {
this.imgIndex = index
this.imgKey = key
},
removeImg(key, index) {
this.tableData[index][key] = ''
}
},
watch: {
tableCheck(newVal, oldVal) {
this.selections = newVal
}
}
}

</script>

<style lang="less">
.me-table {
.ivu-table-wrapper {
min-height: 80px;
}

.ivu-table-row {
td {
padding: 0 5px;
}
}

.no-data {
position: absolute;
top: 50%;
left: 50%;
font-size: 14px;
}

.demo-upload-list {
display: inline-block;
width: 70px;
height: 70px;
text-align: center;
line-height: 70px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
margin-right: 4px;
}

.demo-upload-list img {
width: 100%;
height: 100%;
}

.demo-upload-list-cover {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .6);
}

.demo-upload-list:hover .demo-upload-list-cover {
display: block;
}

.demo-upload-list-cover i {
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}

.span-img {
display: inline-block;
padding: 5px 0;
}

.ivu-checkbox-group-item {
width: 20px;
height: 20px;
overflow: hidden;
}
}

</style>
3.使用组件的页面
<Card style="margin-top: 20px;">
<!-- table1组件 -->
<my-table v-if="btnType[0]" :columns="columnsEdit" :tableData="tableData" :tableCheck="selects" height="650"></my-table>
</Card>
 
this.columnsEdit = [
{
type: 'index',
width: '40'
}, {
type: 'checkbox',
width: '40'
}, {
title: '品牌',
width: '100',
key: 'brandName'
},
{
title: '货号',
width: '110',
key: 'productCode'
}, {
title: '存货编码',
width: '120',
key: 'inventoryCode',
thClass: 'headerColor'
}, {
title: '存货名称',
width: '160',
key: 'inventoryName'
}, {
title: '颜色',
width: '100',
key: 'color'
}, {
title: '尺码',
width: '100',
key: 'size'
}, {
title: '季节',
width: '100',
key: 'season'
}, {
title: '工厂报价',
type: 'input',
width: '130',
key: 'factoryQuote',
thClass: 'headerColor',
inputClass: this.message === 1 ? 'table_input normal_1 input_color1' : this.message === 2 ? 'table_input normal_1 input_color2' : 'table_input normal_1',
placeholder: this.message === 2 ? '未查询到核价单' : this.message === 1 ? '查询到多条结果请确认' : '',
onBlur: this.factoryQuoteChange,
onKeyUp: this.show,
copyIcon: true
}, {
title: '含税单价',
type: 'input',
width: '130',
key: 'taxUnitPrice',
thClass: 'headerColor',
onBlur: this.taxUnitPriceChange,
onKeyUp: this.show,
placeholder: this.message === 2 ? '未查询到核价单' : this.message === 1 ? '查询到多条结果请确认' : '',
inputClass: this.message === 1 ? 'table_input normal_2 input_color1' : this.message === 2 ? 'table_input normal_2 input_color2' : 'table_input normal_2',
copyIcon: true
}, {
title: '不含税单价',
width: '100',
key: 'unitPrice'
}, {
title: '税率',
type: 'select',
width: '110',
key: 'taxRate',
option: {optionList: taxRateList, optionValueKey: 'key', optionLabelKey: ['key']},
thClass: 'headerColor',
onChange: this.taxRateChange,
copyIcon: true
}, {
title: '调价原因',
type: 'input',
width: '160',
key: 'remark',
thClass: 'headerColor',
onKeyUp: this.show,
inputClass: 'table_input normal_3',
copyIcon: true
}
]
 
 
// 删除行
deleteTrFun () {
let _arr = []
if (!this.selects.length) this.$Message.warning('请先选择行!')

this.tableData.forEach((ele, index) => {
console.log(this.selects, 22)
if (this.selects.indexOf(index) < 0) _arr.push(ele)
})
this.productList.splice(this.selects, 1)
console.log(this.productList, 333)
this.selects = []
this.tableData = _arr
if(!this.tableData.length){
this.btnType[1] = true
}
},
 
 
// 键盘触发事件
show (item, row, index) {
let newIndex;
// 通过ev获取当前input名称,用于判断属于哪列
let className = item.target.offsetParent.className;
console.log(item, index);
// 每一列
if (className.indexOf('normal_1') !== -1) {
this.data = index;
this.didata = index*3;
newIndex = index*3;
} else if (className.indexOf('normal_2') !== -1) {
this.data = index;
this.didata = index*3 + 1;
newIndex = index*3 + 1;
} else if (className.indexOf('normal_3') !== -1) {
this.data = index;
this.didata = index*3 + 2;
newIndex = index*3 + 2;
}
// 获取所有input
let inputAll = document.querySelectorAll('.table_input input');
this.iddata = inputAll;
// 向上 =38
if (item.keyCode === 38) {
newIndex -= 3;
if (inputAll[newIndex]) {
inputAll[newIndex].focus();
}
}
// 向下 =40
if (item.keyCode === 40) {
newIndex += 3;
if (inputAll[newIndex]) {
inputAll[newIndex].focus();
}
}
// 向左
if (item.keyCode === 37) {
newIndex -= 1;
if (inputAll[newIndex]) {
inputAll[newIndex].focus();
}
}
// 向右
if (item.keyCode === 39) {
newIndex += 1;
if (inputAll[newIndex]) {
inputAll[newIndex].focus();
}
}
}

猜你喜欢

转载自www.cnblogs.com/wssdx/p/11114537.html