feat: 🎸 Table组件重构完成并给出相应示例
parent
429e42809c
commit
35879f8ecc
@ -0,0 +1,91 @@
|
||||
import Mock from 'mockjs'
|
||||
import { toAnyString } from '@/utils'
|
||||
|
||||
const List: any[] = []
|
||||
const count = 100
|
||||
|
||||
const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
|
||||
const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
List.push(Mock.mock({
|
||||
id: toAnyString(),
|
||||
timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
reviewer: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content_short: 'mock data',
|
||||
content: baseContent,
|
||||
forecast: '@float(0, 100, 2, 2)',
|
||||
importance: '@integer(1, 3)',
|
||||
'type|1': ['CN', 'US', 'JP', 'EU'],
|
||||
'status|1': ['published', 'draft', 'deleted'],
|
||||
display_time: '@datetime',
|
||||
comment_disabled: true,
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri,
|
||||
platforms: ['a-platform']
|
||||
}))
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
url: 'http://mockjs.test.cn/example/list',
|
||||
type: 'get',
|
||||
response: (config: any) => {
|
||||
const { title, pageIndex, pageSize } = config.query
|
||||
|
||||
const mockList = List.filter(item => {
|
||||
if (title && item.title.indexOf(title) < 0) return false
|
||||
return true
|
||||
})
|
||||
const pageList = mockList.filter((item, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1))
|
||||
|
||||
return {
|
||||
code: '0000',
|
||||
data: {
|
||||
total: mockList.length,
|
||||
list: pageList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
url: 'http://mockjs.test.cn/example/delete',
|
||||
type: 'post',
|
||||
response: (config: any) => {
|
||||
return {
|
||||
code: '0000',
|
||||
data: '删除成功'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
url: 'http://mockjs.test.cn/example/detail',
|
||||
type: 'get',
|
||||
response: (config: any) => {
|
||||
const { id } = config.query
|
||||
for (const example of List) {
|
||||
if (example.id === id) {
|
||||
return {
|
||||
code: '0000',
|
||||
data: example
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
url: 'http://mockjs.test.cn/example/save',
|
||||
type: 'post',
|
||||
response: (config: any) => {
|
||||
return {
|
||||
code: '0000',
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,63 @@
|
||||
import Mock from 'mockjs'
|
||||
import { param2Obj } from '@/utils'
|
||||
|
||||
import example from './example'
|
||||
|
||||
const mocks: any[] = [
|
||||
...example
|
||||
]
|
||||
|
||||
// for front mock
|
||||
// please use it cautiously, it will redefine XMLHttpRequest,
|
||||
// which will cause many of your third-party libraries to be invalidated(like progress event).
|
||||
export function mockXHR() {
|
||||
const send: any = (Mock as any).XHR.prototype.send;
|
||||
((Mock as any).XHR.prototype as any).proxy_send = send;
|
||||
(Mock as any).XHR.prototype.send = function() {
|
||||
if (this.custom.xhr) {
|
||||
this.custom.xhr.withCredentials = this.withCredentials || false
|
||||
|
||||
if (this.responseType) {
|
||||
this.custom.xhr.responseType = this.responseType
|
||||
}
|
||||
}
|
||||
this.proxy_send(...arguments)
|
||||
}
|
||||
|
||||
function XHR2ExpressReqWrap(respond: any) {
|
||||
return function(options: any) {
|
||||
let result = null
|
||||
if (respond instanceof Function) {
|
||||
const { body, type, url } = options
|
||||
// https://expressjs.com/en/4x/api.html#req
|
||||
result = respond({
|
||||
method: type,
|
||||
body: JSON.parse(body),
|
||||
query: param2Obj(url)
|
||||
})
|
||||
} else {
|
||||
result = respond
|
||||
}
|
||||
return Mock.mock(result)
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of mocks) {
|
||||
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
|
||||
}
|
||||
}
|
||||
|
||||
// for mock server
|
||||
const responseFake = (url: string, type: string, respond: any) => {
|
||||
return {
|
||||
url: new RegExp(`${url}`),
|
||||
type: type || 'get',
|
||||
response(req: any, res: any) {
|
||||
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default mocks.map(route => {
|
||||
return responseFake(route.url, route.type, route.response)
|
||||
})
|
||||
@ -0,0 +1,68 @@
|
||||
const chokidar = require('chokidar')
|
||||
const bodyParser = require('body-parser')
|
||||
const chalk = require('chalk')
|
||||
const path = require('path')
|
||||
|
||||
const mockDir = path.join(process.cwd(), 'mock')
|
||||
|
||||
function registerRoutes(app) {
|
||||
let mockLastIndex
|
||||
const { default: mocks } = require('./index.ts')
|
||||
for (const mock of mocks) {
|
||||
app[mock.type](mock.url, mock.response)
|
||||
mockLastIndex = app._router.stack.length
|
||||
}
|
||||
const mockRoutesLength = Object.keys(mocks).length
|
||||
return {
|
||||
mockRoutesLength: mockRoutesLength,
|
||||
mockStartIndex: mockLastIndex - mockRoutesLength
|
||||
}
|
||||
}
|
||||
|
||||
function unregisterRoutes() {
|
||||
Object.keys(require.cache).forEach(i => {
|
||||
if (i.includes(mockDir)) {
|
||||
delete require.cache[require.resolve(i)]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = app => {
|
||||
// es6 polyfill
|
||||
require('@babel/register')
|
||||
|
||||
// parse app.body
|
||||
// https://expressjs.com/en/4x/api.html#req.body
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}))
|
||||
|
||||
const mockRoutes = registerRoutes(app)
|
||||
var mockRoutesLength = mockRoutes.mockRoutesLength
|
||||
var mockStartIndex = mockRoutes.mockStartIndex
|
||||
|
||||
// watch files, hot reload mock server
|
||||
chokidar.watch(mockDir, {
|
||||
ignored: /mock-server/,
|
||||
ignoreInitial: true
|
||||
}).on('all', (event, path) => {
|
||||
if (event === 'change' || event === 'add') {
|
||||
try {
|
||||
// remove mock routes stack
|
||||
app._router.stack.splice(mockStartIndex, mockRoutesLength)
|
||||
|
||||
// clear routes cache
|
||||
unregisterRoutes()
|
||||
|
||||
const mockRoutes = registerRoutes(app)
|
||||
mockRoutesLength = mockRoutes.mockRoutesLength
|
||||
mockStartIndex = mockRoutes.mockStartIndex
|
||||
|
||||
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
||||
} catch (error) {
|
||||
console.log(chalk.redBright(error))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<Button v-bind="getBindValue" :class="[getColor, $attrs.class]">
|
||||
<template #default="data">
|
||||
<slot name="icon" />
|
||||
<slot v-bind="data" />
|
||||
</template>
|
||||
</Button>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { defineComponent, computed, VNodeChild } from 'vue'
|
||||
import { Button } from 'ant-design-vue'
|
||||
export default defineComponent({
|
||||
name: 'AButton',
|
||||
components: { Button },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
// 按钮类型
|
||||
type: {
|
||||
type: String as PropType<'primary' | 'default' | 'danger' | 'dashed' | 'link' | 'warning' | 'success' | 'info'>,
|
||||
default: 'default'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
htmlType: {
|
||||
type: String as PropType<'button' | 'submit' | 'reset' | 'menu'>,
|
||||
default: 'button'
|
||||
},
|
||||
icon: {
|
||||
type: Object as PropType<VNodeChild | JSX.Element>,
|
||||
default: () => null
|
||||
},
|
||||
size: {
|
||||
type: String as PropType<'small' | 'large' | 'default'>,
|
||||
default: 'default'
|
||||
},
|
||||
loading: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
ghost: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
block: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
setup(props, { attrs }) {
|
||||
const getColor = computed(() => {
|
||||
const res: string[] = []
|
||||
const { type, disabled } = props
|
||||
type && res.push(`ant-btn-${type}`)
|
||||
disabled && res.push('is-disabled')
|
||||
return res
|
||||
})
|
||||
|
||||
const getBindValue = computed((): any => {
|
||||
const otherTypes = ['warning', 'success', 'info']
|
||||
const bindValue = { ...attrs, ...props }
|
||||
if (otherTypes.indexOf(props.type) !== -1) {
|
||||
bindValue.type = 'default'
|
||||
}
|
||||
return bindValue
|
||||
})
|
||||
|
||||
return { getBindValue, getColor }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,23 @@
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
let messageInstance: any | null = null
|
||||
|
||||
const resetMessage = (options: any) => {
|
||||
if (messageInstance) {
|
||||
messageInstance.close()
|
||||
}
|
||||
messageInstance = ElMessage(options)
|
||||
}
|
||||
['error', 'success', 'info', 'warning'].forEach((type: string) => {
|
||||
resetMessage[type] = (options: any) => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
message: options
|
||||
}
|
||||
}
|
||||
options.type = type
|
||||
return resetMessage(options)
|
||||
}
|
||||
})
|
||||
|
||||
export const Message = resetMessage as any
|
||||
@ -1,6 +1,40 @@
|
||||
// 常用的增删改查 hook
|
||||
import { reactive } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
export function() {
|
||||
interface DefalutParams {
|
||||
pageIndex: number
|
||||
pageSize: number
|
||||
}
|
||||
|
||||
export function useExample() {
|
||||
const defalutParams = reactive<DefalutParams>({
|
||||
pageIndex: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
|
||||
const tableData = ref<any[]>([])
|
||||
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
const total = ref<number>(0)
|
||||
|
||||
function sizeChange(val: number) {
|
||||
loading.value = true
|
||||
defalutParams.pageIndex = 1
|
||||
defalutParams.pageSize = val
|
||||
}
|
||||
|
||||
function currentChange(val: number) {
|
||||
loading.value = true
|
||||
defalutParams.pageIndex = val
|
||||
}
|
||||
|
||||
return {
|
||||
defalutParams,
|
||||
tableData,
|
||||
loading,
|
||||
total,
|
||||
sizeChange,
|
||||
currentChange
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-alert
|
||||
effect="dark"
|
||||
:closable="false"
|
||||
title="二次封装 Element 的 Message 组件,每次只显示最新一条消息,避免出现太多消息提示导致不美观。"
|
||||
type="info"
|
||||
style="margin-bottom: 20px;"
|
||||
/>
|
||||
<el-button @click="show">显示</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { Message } from '_c/Message'
|
||||
export default defineComponent({
|
||||
name: 'MessageDemo',
|
||||
setup() {
|
||||
const count = ref<number>(0)
|
||||
function show() {
|
||||
count.value = count.value + 1
|
||||
Message.success('这是成功消息' + count.value)
|
||||
}
|
||||
return {
|
||||
count,
|
||||
show
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-alert
|
||||
effect="dark"
|
||||
:closable="false"
|
||||
title="基于 Element 的 Table 组件进行二次封装,实现数据驱动,支持所有 Table 参数 -- 自定义索引"
|
||||
type="info"
|
||||
style="margin-bottom: 20px;"
|
||||
/>
|
||||
<com-table
|
||||
v-loading="loading"
|
||||
:columns="columns"
|
||||
:data="tableData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import ComTable from '_c/Table/index.vue'
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1518 弄'
|
||||
}, {
|
||||
date: '2016-05-04',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1517 弄'
|
||||
}, {
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
}, {
|
||||
date: '2016-05-03',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1516 弄'
|
||||
}
|
||||
]
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'CustomIndex',
|
||||
components: {
|
||||
ComTable
|
||||
},
|
||||
setup() {
|
||||
const loading = ref<boolean>(true)
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
|
||||
const columns = ref<any[]>([
|
||||
{
|
||||
key: 'index',
|
||||
type: 'index',
|
||||
index: (index: number) => {
|
||||
return index * 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'date',
|
||||
label: '日期'
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
label: '姓名'
|
||||
},
|
||||
{
|
||||
key: 'address',
|
||||
label: '地址'
|
||||
}
|
||||
])
|
||||
|
||||
return {
|
||||
columns,
|
||||
tableData,
|
||||
loading
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-alert
|
||||
effect="dark"
|
||||
:closable="false"
|
||||
title="基于 Element 的 Table 组件进行二次封装,实现数据驱动,支持所有 Table 参数 -- 分页表格"
|
||||
type="info"
|
||||
style="margin-bottom: 20px;"
|
||||
/>
|
||||
<com-table
|
||||
v-loading="loading"
|
||||
:columns="columns"
|
||||
:data="tableData"
|
||||
:pagination="{
|
||||
currentPage: 1,
|
||||
total: 400,
|
||||
onSizeChange: handleSizeChange,
|
||||
onCurrentChange: handleCurrentChange
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import ComTable from '_c/Table/index.vue'
|
||||
|
||||
const columns = [
|
||||
{
|
||||
key: 'date',
|
||||
label: '日期'
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
label: '姓名'
|
||||
},
|
||||
{
|
||||
key: 'address',
|
||||
label: '地址'
|
||||
}
|
||||
]
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1518 弄'
|
||||
}, {
|
||||
date: '2016-05-04',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1517 弄'
|
||||
}, {
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
}, {
|
||||
date: '2016-05-03',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1516 弄'
|
||||
}
|
||||
]
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageTable',
|
||||
components: {
|
||||
ComTable
|
||||
},
|
||||
setup() {
|
||||
const loading = ref<boolean>(true)
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 1000)
|
||||
|
||||
function handleSizeChange(val: number) {
|
||||
console.log(val)
|
||||
}
|
||||
|
||||
function handleCurrentChange(val: number) {
|
||||
console.log(val)
|
||||
}
|
||||
|
||||
return {
|
||||
columns,
|
||||
tableData,
|
||||
loading,
|
||||
handleSizeChange, handleCurrentChange
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@ -1,126 +1,39 @@
|
||||
@import "~ant-design-vue/lib/style/themes/default";
|
||||
@import "~ant-design-vue/es/button/style/mixin";
|
||||
|
||||
// warning button style
|
||||
@btn-warning-color: #fff;
|
||||
@btn-warning-bg: @warning-color;
|
||||
@btn-warning-disabled-border-color: #f3d19e;
|
||||
@btn-warning-disabled-bg-color: #f3d19e;
|
||||
|
||||
// success button style
|
||||
@btn-success-color: #fff;
|
||||
@btn-success-bg: @success-color;
|
||||
@btn-success-disabled-border-color: #b3e19d;
|
||||
@btn-success-disabled-bg-color: #b3e19d;
|
||||
|
||||
// info button style
|
||||
@btn-info-color: #fff;
|
||||
@btn-info-bg: #909399;
|
||||
@btn-info-disabled-border-color: #c8c9cc;
|
||||
@btn-info-disabled-bg-color: #c8c9cc;
|
||||
|
||||
// primary button style
|
||||
@btn-primary-disabled-border-color: #a0cfff;
|
||||
@btn-primary-disabled-bg-color: #a0cfff;
|
||||
|
||||
// danger button style
|
||||
@btn-danger-disabled-border-color: #fab6b6;
|
||||
@btn-danger-disabled-bg-color: #fab6b6;
|
||||
|
||||
// set button margin
|
||||
.ant-btn+.ant-btn {
|
||||
margin-left: 10px;
|
||||
.el-button + .el-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.button-variant(@color; @background) {
|
||||
.button-color(@color; @background; @background);
|
||||
|
||||
text-shadow: @btn-text-shadow;
|
||||
box-shadow: @btn-primary-shadow;
|
||||
|
||||
&:hover,
|
||||
.el-button:not(.is-disabled) {
|
||||
position: relative;
|
||||
&:focus {
|
||||
.button-color(@color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) `);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.active {
|
||||
.button-color(@color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) `);
|
||||
}
|
||||
|
||||
.button-disabled();
|
||||
}
|
||||
|
||||
.ant-btn-warning,
|
||||
.ant-btn-success,
|
||||
.ant-btn-info {
|
||||
|
||||
.ant-btn-group {
|
||||
&:not(:first-child):not(:last-child) {
|
||||
border-right-color: @gold-5;
|
||||
border-left-color: @gold-5;
|
||||
|
||||
&:disabled {
|
||||
border-color: @btn-default-border;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
&:not(:last-child) {
|
||||
border-right-color: @gold-5;
|
||||
|
||||
&[disabled] {
|
||||
border-right-color: @btn-default-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-btn-group &:last-child:not(:first-child),
|
||||
.ant-btn-group & + & {
|
||||
border-left-color: @gold-5;
|
||||
|
||||
&[disabled] {
|
||||
border-left-color: @btn-default-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-btn-success {
|
||||
.button-variant(@btn-success-color; @btn-success-bg);
|
||||
&:not(.ant-btn-link)[disabled] {
|
||||
color: #fff;
|
||||
background-color: @btn-success-disabled-bg-color;
|
||||
border-color: @btn-success-disabled-border-color;
|
||||
}
|
||||
}
|
||||
.ant-btn-info {
|
||||
.button-variant(@btn-info-color; @btn-info-bg);
|
||||
&:not(.ant-btn-link)[disabled] {
|
||||
color: #fff;
|
||||
background-color: @btn-info-disabled-bg-color;
|
||||
border-color: @btn-info-disabled-border-color;
|
||||
}
|
||||
}
|
||||
.ant-btn-warning {
|
||||
.button-variant(@btn-warning-color; @btn-warning-bg);
|
||||
&:not(.ant-btn-link)[disabled] {
|
||||
color: #fff;
|
||||
background-color: @btn-warning-disabled-bg-color;
|
||||
border-color: @btn-warning-disabled-border-color;
|
||||
}
|
||||
}
|
||||
.ant-btn-primary {
|
||||
&:not(.ant-btn-link)[disabled] {
|
||||
color: #fff;
|
||||
background-color: @btn-primary-disabled-bg-color;
|
||||
border-color: @btn-primary-disabled-border-color;
|
||||
}
|
||||
}
|
||||
.ant-btn-danger {
|
||||
&:not(.ant-btn-link)[disabled] {
|
||||
color: #fff;
|
||||
background-color: @btn-danger-disabled-bg-color;
|
||||
border-color: @btn-danger-disabled-border-color;
|
||||
outline: none;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: -6px;
|
||||
right: -6px;
|
||||
bottom: -6px;
|
||||
pointer-events: none;
|
||||
background-color: inherit;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
transition: all .3s;
|
||||
border-radius: inherit;
|
||||
}
|
||||
&:active:after {
|
||||
opacity: .7;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
transition: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button--default {
|
||||
&:after {
|
||||
background-color: lightgrey !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
@import '~element-plus/lib/theme-chalk/index.css';
|
||||
// @import './sidebar.less';
|
||||
@import './transition.less';
|
||||
@import './sider.less';
|
||||
@import './glob.less';
|
||||
// @import './button.less';
|
||||
// @import './antdv.less';
|
||||
@import './button.less';
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
import ResizeObserver from 'resize-observer-polyfill'
|
||||
|
||||
const isServer = typeof window === 'undefined'
|
||||
|
||||
/* istanbul ignore next */
|
||||
const resizeHandler = function(entries: any[]) {
|
||||
for (const entry of entries) {
|
||||
const listeners = entry.target.__resizeListeners__ || []
|
||||
if (listeners.length) {
|
||||
listeners.forEach((fn: () => any) => {
|
||||
fn()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export const addResizeListener = function(element: any, fn: () => any) {
|
||||
if (isServer) return
|
||||
if (!element.__resizeListeners__) {
|
||||
element.__resizeListeners__ = []
|
||||
element.__ro__ = new ResizeObserver(resizeHandler)
|
||||
element.__ro__.observe(element)
|
||||
}
|
||||
element.__resizeListeners__.push(fn)
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export const removeResizeListener = function(element: any, fn: () => any) {
|
||||
if (!element || !element.__resizeListeners__) return
|
||||
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1)
|
||||
if (!element.__resizeListeners__.length) {
|
||||
element.__ro__.disconnect()
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
import { isWindow } from '@/utils/is'
|
||||
|
||||
let scrollBarWidth: number
|
||||
|
||||
export default function(): number {
|
||||
if (!isWindow) return 0
|
||||
if (scrollBarWidth !== undefined) return scrollBarWidth
|
||||
|
||||
const outer = document.createElement('div')
|
||||
outer.className = 'scrollbar__wrap'
|
||||
outer.style.visibility = 'hidden'
|
||||
outer.style.width = '100px'
|
||||
outer.style.position = 'absolute'
|
||||
outer.style.top = '-9999px'
|
||||
document.body.appendChild(outer)
|
||||
|
||||
const widthNoScroll = outer.offsetWidth
|
||||
outer.style.overflow = 'scroll'
|
||||
|
||||
const inner = document.createElement('div')
|
||||
inner.style.width = '100%'
|
||||
outer.appendChild(inner)
|
||||
|
||||
const widthWithScroll = inner.offsetWidth
|
||||
const parentNode = outer.parentNode
|
||||
parentNode && parentNode.removeChild(outer)
|
||||
scrollBarWidth = widthNoScroll - widthWithScroll
|
||||
|
||||
return scrollBarWidth
|
||||
}
|
||||
Loading…
Reference in New Issue