<el-table
:key="tableKey"
v-loading="listLoading" #决定列表是否处于加载状态的boolean值
:data="list" #数据绑定参数
border #是否有界限
fit
highlight-current-row
style="width: 100%;" # 宽度
@sort-change="sortChange" # 排序改变时触发的回调
>
在这个标签内的元素就可以使用row代表每一行, 但是想在表单中显示则必须使用这种格式,下例中的一级标签标识的就是每一竖排的数据 lable 表示表头数据名称,
<el-table-column label="" width="120" align="center">
<template slot-scope="{row,$index}"> # 在行中插槽绑定row为每一行,并注入$index表示索引,可以在任意地方使用
<el-button-group>
<el-button size="mini" type="primary" icon="el-icon-edit" round />
<el-button v-if="row.locked === 1" size="mini" type="info" icon="el-icon-lock" round @click="unLockUser(row.id,$index)" />
<el-button v-if="row.locked === 0" size="mini" type="primary" icon="el-icon-lock" round @click="lockUser(row.id,$index)" />
</el-button-group>
</template>
</el-table-column>
组件传值
创建了一个组件B, 要在父组件A引入他,同时用一个boolean控制B的展示;
方法: 在A中定义一个boolean控制组件的开关,并通过prop传值给组件,组件通过这个值决定是否渲染; 关闭时,父组件提供一个方法给子组件调用,父组件修改boolean值达到关闭的效果, 不要直接给改变子组件的值,会报错,。。没啥影响就是刷日志很烦
父组件调用开启
子组件调用关闭
子组件数据展示区的数值传递
由于这里是点击表单一行打开子组件展示 我不想在表单中为每一行都创建一个子组件,所以用了一个公用的组件,,,这里子组件就没法关联每一行的数据,只能在每一行点击事件触发 的时候传递本行数据 到一个方法 ,方法再改变boolean打开之前先将row 数据写入公共变量 ,同时将公共变量 传递给子组件 ,并且当关闭子组件的时候一定要清空临时区域 的数据 每一行的打开按钮 打开方法和关闭方法 调用子组件
子组件绑定数据 复制粘贴代码部分
子组件
<template>
<el-drawer
title="我是标题"
:visible.sync="show"
:with-header="false"
:before-close="handleClose"
>
{{ data }}
</el-drawer>
</template>
<script>
import { translation } from '@/utils/translation'
export default {
name: 'RightDrawer',
props: {
show: {
type: Boolean,
required: true
},
data: {
type: Object,
required: true
}
},
data() {
return {
dictionary: {
closeConfirm: 'Confirm to close?',
cancel: 'Cancel',
confirm: 'Confirm'
},
drawer: false
}
},
created() {
this.resetLanguage()
},
methods: {
handleClose(done) {
this.$confirm(this.closeConfirm)
.then(rse => {
this.$emit('closeRightDrawer')
})
.catch(res => {
console.log('取消退出')
})
},
resetLanguage() {
for (const dictionaryKey in this.dictionary) {
this.dictionary[dictionaryKey] = translation(dictionaryKey)
}
}
}
}
</script>
<style scoped>
</style>
父组件
<template>
<div class="app-container">
<div class="filter-container" style="margin-bottom: 5px">
<el-input
v-model="listQuery.email"
:placeholder="button.email"
style="width: 200px;"
class="filter-item"
@keyup.enter.native="handleFilter"
/>
<el-button
v-waves
style="margin-left: 12px"
class="filter-item"
type="primary"
icon="el-icon-search"
@click="handleFilter"
>
{{ button.search }}
</el-button>
<el-button
class="filter-item"
style="margin-left: 10px;"
type="primary"
icon="el-icon-edit"
@click="handleCreate"
>
{{ button.add }}
</el-button>
</div>
<el-table
:key="tableKey"
v-loading="listLoading"
:data="list"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="sortChange"
>
<el-table-column label="" width="120" align="center">
<template slot-scope="{row,$index}">
<el-button-group>
<el-button size="mini" type="primary" icon="el-icon-edit" round @click="openRightDrawer(row)" />
<el-button v-if="row.locked === 1" size="mini" type="info" icon="el-icon-lock" round @click="unLockUser(row.id,$index)" />
<el-button v-if="row.locked === 0" size="mini" type="primary" icon="el-icon-lock" round @click="lockUser(row.id,$index)" />
</el-button-group>
</template>
</el-table-column>
<el-table-column
label="id"
prop="id"
sortable="custom"
align="center"
width="180"
:class-name="getSortClass('id')"
>
<template slot-scope="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column label="email" width="200px" align="center">
<template slot-scope="{row}">
<span>{{ row.email }}</span>
</template>
</el-table-column>
<el-table-column label="fullName" width="140px" align="center">
<template slot-scope="{row}">
<span>{{ row.fullName }}</span>
</template>
</el-table-column>
<el-table-column label="avatarUrl" width="120px" align="center">
<template slot-scope="{row}">
<el-image
style="width: 70px; height: 70px"
:src="row.avatarUrl"
:preview-src-list="[row.avatarUrl]"
/>
</template>
</el-table-column>
<el-table-column label="score" width="100px" align="center">
<template slot-scope="{row}">
<span>{{ row.score }}</span>
</template>
</el-table-column>
<el-table-column label="frozenScore" width="110px" align="center">
<template slot-scope="{row}">
<span>{{ row.frozenScore }}</span>
</template>
</el-table-column>
<el-table-column label="gender" width="85px" align="center">
<template slot-scope="{row}">
<el-tag :type="row.gender === 1 ?'danger':''" effect="dark">
{{ row.gender === 1 ? 'woman' : 'man' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="locked" width="85px" align="center">
<template slot-scope="{row}">
<el-tag :type=" row.locked === 1 ?'info':'success'">{{ row.locked === 1 ? 'locked' : 'unLock' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="mobile" width="140px" align="center">
<template slot-scope="{row}">
<span>{{ row.mobile }}</span>
</template>
</el-table-column>
<el-table-column label="birthday" width="250px" align="center">
<template slot-scope="{row}">
<span>
<el-date-picker
v-model="row.birthday"
type="datetime"
placeholder="birthday"
disabled="disabled"
/>
</span>
</template>
</el-table-column>
<el-table-column label="created" width="250px" align="center">
<template slot-scope="{row}">
<span>
<el-date-picker
v-model="row.created"
type="datetime"
placeholder="created"
disabled="disabled"
/>
</span>
</template>
</el-table-column>
<el-table-column label="vipExpiration" width="250px" align="center">
<template slot-scope="{row}">
<span>
<el-date-picker
v-model="row.vipExpiration"
type="datetime"
placeholder="vipExpiration"
disabled="disabled"
/>
</span>
</template>
</el-table-column>
<el-table-column label="passWord" width="160px" align="center">
<template slot-scope="{row}">
<span>{{ tooLongString(row.passWord,12) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="listQuery.pageNumber"
:limit.sync="listQuery.limit"
@pagination="getList"
/>
<el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
<el-table :data="pvData" border fit highlight-current-row style="width: 100%">
<el-table-column prop="key" label="Channel" />
<el-table-column prop="pv" label="Pv" />
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
</span>
</el-dialog>
<div>
<RightDrawer ref="rightDrawer" :show="showDrawer" :data="drawerData" @closeRightDrawer="closeRightDrawer" />
</div>
</div>
</template>
<script>
import { fetchPv, createArticle, updateArticle } from '@/api/article'
import { getUserList, lockUserById, unLockUserById } from '@/api/user'
import { translation } from '@/utils/translation'
import { tooLongStr } from '@/utils/string-utils'
import waves from '@/directive/waves'
import { parseTime } from '@/utils'
import Pagination from '@/components/Pagination'
import { showMessage } from '@/utils/show-message'
import RightDrawer from '@/views/user/module/RightDrawer'
const calendarTypeOptions = [
{ key: 'CN', display_name: 'China' },
{ key: 'US', display_name: 'USA' },
{ key: 'JP', display_name: 'Japan' },
{ key: 'EU', display_name: 'Eurozone' }
]
const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
acc[cur.key] = cur.display_name
return acc
}, {})
export default {
name: 'ComplexTable',
components: { RightDrawer, Pagination },
directives: { waves },
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
},
typeFilter(type) {
return calendarTypeKeyValue[type]
}
},
data() {
return {
button: {
edit: 'Edit',
search: 'Search',
add: 'Add',
cancel: 'Cancel',
confirm: 'Confirm',
email: 'Email'
},
showDrawer: false,
drawerData: {},
tableKey: 0,
list: null,
total: 0,
listLoading: true,
listQuery: {
pageNumber: 1,
pageSize: 20,
email: ''
},
importanceOptions: [1, 2, 3],
calendarTypeOptions,
sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
statusOptions: ['published', 'draft', 'deleted'],
temp: {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
type: '',
status: 'published'
},
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
dialogPvVisible: false,
pvData: [],
rules: {
type: [{ required: true, message: 'type is required', trigger: 'change' }],
timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
title: [{ required: true, message: 'title is required', trigger: 'blur' }]
},
downloadLoading: false
}
},
created() {
this.getList()
this.resetLanguage()
},
methods: {
tooLongString(str, length) {
return tooLongStr(str, length)
},
lockUser(userId, index) {
lockUserById(userId).then(res => {
showMessage(this, res)
if (res.flag) {
this.list[index].locked = 1
}
})
},
unLockUser(userId, index) {
unLockUserById(userId).then(res => {
showMessage(this, res)
if (res.flag) {
this.list[index].locked = 0
}
})
},
getList() {
this.listLoading = true
getUserList(this.listQuery).then(response => {
console.log(response)
this.list = response.data.item
this.total = response.data.total
return true
}).catch(res => {
showMessage(this, res)
return false
})
this.listLoading = false
},
search() {
this.listLoading = true
getUserList(this.listQuery).then(response => {
console.log(response)
this.list = response.data.item
this.total = response.data.total
showMessage(this, response)
})
this.listLoading = false
},
resetLanguage() {
for (const buttonKey in this.button) {
this.button[buttonKey] = translation(buttonKey)
}
},
handleFilter() {
this.listQuery.pageNumber = 1
this.search()
},
openRightDrawer(row) {
console.log(row)
this.drawerData = row
this.showDrawer = true
},
closeRightDrawer() {
this.showDrawer = false
this.drawerData = { }
},
handleModifyStatus(row, status) {
this.$message({
message: '操作Success',
type: 'success'
})
row.status = status
},
sortChange(data) {
const { prop, order } = data
if (prop === 'id') {
this.sortByID(order)
}
},
sortByID(order) {
if (order === 'ascending') {
this.listQuery.sort = '+id'
} else {
this.listQuery.sort = '-id'
}
this.handleFilter()
},
resetTemp() {
this.temp = {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
status: 'published',
type: ''
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
createData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.temp.id = parseInt(Math.random() * 100) + 1024
this.temp.author = 'vue-element-admin'
createArticle(this.temp).then(() => {
this.list.unshift(this.temp)
this.dialogFormVisible = false
this.$notify({
title: 'Success',
message: 'Created Successfully',
type: 'success',
duration: 2000
})
})
}
})
},
handleUpdate(row) {
this.temp = Object.assign({}, row)
this.temp.timestamp = new Date(this.temp.timestamp)
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
updateData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
const tempData = Object.assign({}, this.temp)
tempData.timestamp = +new Date(tempData.timestamp)
updateArticle(tempData).then(() => {
const index = this.list.findIndex(v => v.id === this.temp.id)
this.list.splice(index, 1, this.temp)
this.dialogFormVisible = false
this.$notify({
title: 'Success',
message: 'Update Successfully',
type: 'success',
duration: 2000
})
})
}
})
},
handleDelete(row, index) {
this.$notify({
title: 'Success',
message: 'Delete Successfully',
type: 'success',
duration: 2000
})
this.list.splice(index, 1)
},
handleFetchPv(pv) {
fetchPv(pv).then(response => {
this.pvData = response.data.pvData
this.dialogPvVisible = true
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
const data = this.formatJson(filterVal)
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'table-list'
})
this.downloadLoading = false
})
},
formatJson(filterVal) {
return this.list.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
},
getSortClass: function(key) {
const sort = this.listQuery.sort
return sort === `+${key}` ? 'ascending' : 'descending'
}
}
}
</script>
|