mirror of https://github.com/ElemeFE/element
commit
5baa8774cb
|
@ -29,6 +29,7 @@
|
||||||
- [awesome-element](https://github.com/ElementUI/awesome-element)
|
- [awesome-element](https://github.com/ElementUI/awesome-element)
|
||||||
- [FAQ](./FAQ.md)
|
- [FAQ](./FAQ.md)
|
||||||
- [Customize Theme](http://element.eleme.io/#/en-US/component/custom-theme)
|
- [Customize Theme](http://element.eleme.io/#/en-US/component/custom-theme)
|
||||||
|
- [Preview and generate theme online](https://elementui.github.io/theme-preview)
|
||||||
- Starter Kit
|
- Starter Kit
|
||||||
- [element-starter](https://github.com/ElementUI/element-starter)
|
- [element-starter](https://github.com/ElementUI/element-starter)
|
||||||
- [element-cooking-starter](https://github.com/ElementUI/element-cooking-starter)
|
- [element-cooking-starter](https://github.com/ElementUI/element-cooking-starter)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var save = require('file-save');
|
||||||
|
var resolve = require('path').resolve;
|
||||||
|
var basename = require('path').basename;
|
||||||
|
var localePath = resolve(__dirname, '../../src/locale/lang');
|
||||||
|
var fileList = fs.readdirSync(localePath);
|
||||||
|
|
||||||
|
var transform = function(filename, name, cb) {
|
||||||
|
require('babel-core').transformFile(resolve(localePath, filename), {
|
||||||
|
plugins: [
|
||||||
|
'add-module-exports',
|
||||||
|
['transform-es2015-modules-umd', {loose: true}]
|
||||||
|
],
|
||||||
|
moduleId: name
|
||||||
|
}, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
fileList.forEach(function(file) {
|
||||||
|
var name = basename(file, '.js');
|
||||||
|
|
||||||
|
transform(file, name, function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
} else {
|
||||||
|
var code = result.code;
|
||||||
|
|
||||||
|
code = code
|
||||||
|
.replace('define(\'', 'define(\'element/locale/')
|
||||||
|
.replace('global.', 'global.ELEMENT.lang = global.ELEMENT.lang || {}; \n global.ELEMENT.lang.');
|
||||||
|
save(resolve(__dirname, '../../lib/umd/locale', file)).write(code);
|
||||||
|
|
||||||
|
console.log(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -58,5 +58,6 @@
|
||||||
"scrollbar": "./packages/scrollbar/index.js",
|
"scrollbar": "./packages/scrollbar/index.js",
|
||||||
"carousel-item": "./packages/carousel-item/index.js",
|
"carousel-item": "./packages/carousel-item/index.js",
|
||||||
"collapse": "./packages/collapse/index.js",
|
"collapse": "./packages/collapse/index.js",
|
||||||
"collapse-item": "./packages/collapse-item/index.js"
|
"collapse-item": "./packages/collapse-item/index.js",
|
||||||
|
"cascader": "./packages/cascader/index.js"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,487 @@
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
optionsWithDisabled: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
disabled: true,
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
selectedOptions: [],
|
||||||
|
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.demo-cascader {
|
||||||
|
.el-cascader {
|
||||||
|
width: 222px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.demo-cascader-size {
|
||||||
|
.el-cascader {
|
||||||
|
vertical-align: top;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
## Cascader
|
||||||
|
|
||||||
|
It's used to select from a set of associated data set. Such as province/city/district, company level, and categories.
|
||||||
|
|
||||||
|
### Basic usage
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
@change="handleChange"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Disabled option
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="optionsWithDisabled"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
optionsWithDisabled: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
disabled: true,
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Default Value
|
||||||
|
|
||||||
|
:::demo default value is assigned by an array type value.
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions2"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Size
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<div class="demo-cascader-size">
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
size="large"
|
||||||
|
></el-cascader>
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
></el-cascader>
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
size="small"
|
||||||
|
></el-cascader>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Hover to expand
|
||||||
|
|
||||||
|
Hover to expand the next level options, click to select option.
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
expand-trigger="hover"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Change on select
|
||||||
|
|
||||||
|
Allow only select parent options.
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
change-on-select
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Search
|
||||||
|
|
||||||
|
Search and select options directly.
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="Please select"
|
||||||
|
:options="options"
|
||||||
|
filterable
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
| Attribute | Description | Type | Options | Default|
|
||||||
|
|---------- |-------------------- |---------|------------- |-------- |
|
||||||
|
| options | data source of the options | array | — | — |
|
||||||
|
| value | selected value | array | — | — |
|
||||||
|
| popper-class | className of popup overlay | string | — | — |
|
||||||
|
| placeholder | input placeholder | string | — | — |
|
||||||
|
| disabled | 是否禁用 | boolean | — | false |
|
||||||
|
| clearable | whether allow clear | boolean | — | false |
|
||||||
|
| expand-trigger | trigger mode of expandind the current item | string | click / hover | 'click' |
|
||||||
|
| filterable | whether the options can be searched | boolean | — | — |
|
||||||
|
| size | size | string | large / small / mini | — |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
| Event Name | Description | Parameters |
|
||||||
|
|---------- |-------- |---------- |
|
||||||
|
| change | triggers when the binding value changes | value |
|
|
@ -1,5 +1,15 @@
|
||||||
## Custom theme
|
## Custom theme
|
||||||
Element uses BEM-styled CSS so that you can override styles easily. But if you need to replace styles at a large scale, e.g. change the theme color from blue to orange or green, maybe overriding them one by one is not a good idea, and this is where our theme customization tool kicks in.
|
Element uses BEM-styled CSS so that you can override styles easily. But if you need to replace styles at a large scale, e.g. change the theme color from blue to orange or green, maybe overriding them one by one is not a good idea, and this is where our theme customization tools kick in.
|
||||||
|
|
||||||
|
## Changing theme color
|
||||||
|
If you just want to change the theme color of Element, the [theme preview website](https://elementui.github.io/theme-preview/#/en-US) is recommended.
|
||||||
|
|
||||||
|
The main color of Element is bright and friendly blue. By changing it, you can make Element more visually connected to specific projects.
|
||||||
|
|
||||||
|
The above website enables you to preview theme of a new theme color in real-time, and it can generate a complete style package based on the new theme color for you to download directly (to import new style files in your project, please refer to the 'Import custom theme' or 'Import component theme on demand' part of this section).
|
||||||
|
|
||||||
|
## More customizations
|
||||||
|
If you need more customization than just changing the theme color, please follow these steps:
|
||||||
|
|
||||||
### Install related tool
|
### Install related tool
|
||||||
First install the theme generator globally or locally. Local install is recommended because in this way, when others clone your project, npm will automatically install it for them.
|
First install the theme generator globally or locally. Local install is recommended because in this way, when others clone your project, npm will automatically install it for them.
|
||||||
|
|
|
@ -164,6 +164,7 @@ The content of Dialog can be anything, even a table or a form. This example show
|
||||||
| size | size of Dialog | string | tiny/small/large/full | small |
|
| size | size of Dialog | string | tiny/small/large/full | small |
|
||||||
| top | value for `top` of Dialog CSS, works when `size` is not `full` | string | — | 15% |
|
| top | value for `top` of Dialog CSS, works when `size` is not `full` | string | — | 15% |
|
||||||
| modal | whether a mask is displayed | boolean | — | true |
|
| modal | whether a mask is displayed | boolean | — | true |
|
||||||
|
| modal-append-to-body | whether to append modal to body element. If false, the modal will be appended to Dialog's parent element | boolean | — | true |
|
||||||
| lock-scroll | whether scroll of body is disabled while Dialog is displayed | boolean | — | true |
|
| lock-scroll | whether scroll of body is disabled while Dialog is displayed | boolean | — | true |
|
||||||
| custom-class | custom class names for Dialog | string | — | — |
|
| custom-class | custom class names for Dialog | string | — | — |
|
||||||
| close-on-click-modal | whether the Dialog can be closed by clicking the mask | boolean | — | true |
|
| close-on-click-modal | whether the Dialog can be closed by clicking the mask | boolean | — | true |
|
||||||
|
|
|
@ -72,6 +72,33 @@ Vue.use(Element, {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Import via CDN
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="//unpkg.com/vue"></script>
|
||||||
|
<script src="//unpkg.com/element-ui"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/en.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
ELEMENT.locale(ELEMENT.lang.en)
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Compatible with `vue-i18n`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="//unpkg.com/vue"></script>
|
||||||
|
<script src="//unpkg.com/vue-i18n/dist/vue-i18n.js"></script>
|
||||||
|
<script src="//unpkg.com/element-ui"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/zh-CN.js"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/en.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Vue.locale('en', ELEMENT.lang.en)
|
||||||
|
Vue.locale('zh-cn', ELEMENT.lang.zhCN)
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
Currently Element ships with the following languages:
|
Currently Element ships with the following languages:
|
||||||
<ul class="language-list">
|
<ul class="language-list">
|
||||||
<li>Simplified Chinese (zh-CN)</li>
|
<li>Simplified Chinese (zh-CN)</li>
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-autocomplete__suggestions.my-autocomplete {
|
.el-autocomplete-suggestion.my-autocomplete {
|
||||||
li {
|
li {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
padding: 7px *;
|
padding: 7px *;
|
||||||
|
@ -133,7 +133,6 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #b4b4b4;
|
color: #b4b4b4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted .addr {
|
.highlighted .addr {
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ Radio with button styles.
|
||||||
|
|
||||||
Attribute | Description | Type | Accepted Values | Default
|
Attribute | Description | Type | Accepted Values | Default
|
||||||
---- | ---- | ---- | ---- | ----
|
---- | ---- | ---- | ---- | ----
|
||||||
label | the value of radio | string/number | — | —
|
label | the value of radio | string/number/boolean | — | —
|
||||||
disabled | whether radio is disabled | boolean | — | false
|
disabled | whether radio is disabled | boolean | — | false
|
||||||
name | native 'name' attribute | string | — | —
|
name | native 'name' attribute | string | — | —
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ Vertical step bars.
|
||||||
|
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------- |---------- |------------- |-------- |
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
| space | the spacing of each step, will be responsive if omitted | Number | — | — |
|
| space | the spacing of each step, will be responsive if omitted. Support percentage. | Number,String | — | — |
|
||||||
| direction | display direction | string | vertical/horizontal | horizontal |
|
| direction | display direction | string | vertical/horizontal | horizontal |
|
||||||
| active | current activation step | number | — | 0 |
|
| active | current activation step | number | — | 0 |
|
||||||
| process-status | status of current step | string | wait/process/finish/error/success | process |
|
| process-status | status of current step | string | wait/process/finish/error/success | process |
|
||||||
|
|
|
@ -2,9 +2,20 @@
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeName: 'first',
|
activeName: 'second',
|
||||||
activeName2: 'first',
|
activeName2: 'first',
|
||||||
tabs: [{
|
editableTabsValue: '2',
|
||||||
|
editableTabsValue2: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
editableTabs2: [{
|
||||||
title: 'Tab 1',
|
title: 'Tab 1',
|
||||||
name: '1',
|
name: '1',
|
||||||
content: 'Tab 1 content'
|
content: 'Tab 1 content'
|
||||||
|
@ -17,11 +28,62 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleRemove(tab) {
|
|
||||||
console.log(tab);
|
|
||||||
},
|
|
||||||
handleClick(tab, event) {
|
handleClick(tab, event) {
|
||||||
console.log(tab, event);
|
console.log(tab, event);
|
||||||
|
},
|
||||||
|
handleTabsEdit(targetName, action) {
|
||||||
|
if (action === 'add') {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
}
|
||||||
|
if (action === 'remove') {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addTab(targetName) {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs2.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue2 = newTabName;
|
||||||
|
},
|
||||||
|
removeTab(targetName) {
|
||||||
|
let tabs = this.editableTabs2;
|
||||||
|
let activeName = this.editableTabsValue2;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue2 = activeName;
|
||||||
|
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,37 +157,6 @@ Tabs styled as cards.
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Closable
|
|
||||||
|
|
||||||
Closable tabs.
|
|
||||||
|
|
||||||
:::demo You can set the closable attribute in el-tabs to make all tabs closable. Also, closable can be set in a tab panel to make that specific tab closable.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<template>
|
|
||||||
<el-tabs type="card" :closable="true" @tab-click="handleClick" @tab-remove="handleRemove">
|
|
||||||
<el-tab-pane label="User">User</el-tab-pane>
|
|
||||||
<el-tab-pane label="Config">Config</el-tab-pane>
|
|
||||||
<el-tab-pane label="Role">Role</el-tab-pane>
|
|
||||||
<el-tab-pane label="Task">Task</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
handleRemove(tab) {
|
|
||||||
console.log(tab);
|
|
||||||
},
|
|
||||||
handleClick(tab, event) {
|
|
||||||
console.log(tab, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Border card
|
### Border card
|
||||||
|
|
||||||
Border card tabs.
|
Border card tabs.
|
||||||
|
@ -161,11 +192,151 @@ You can use named slot to customize the tab label content.
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Add & close tab
|
||||||
|
|
||||||
|
Only card type Tabs support addable & closeable.
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-tabs v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="(item, index) in editableTabs"
|
||||||
|
:label="item.title"
|
||||||
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleTabsEdit(targetName, action) {
|
||||||
|
if (action === 'add') {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
}
|
||||||
|
if (action === 'remove') {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Customized trigger button of new tab
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<div style="margin-bottom: 20px;">
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
@click="addTab(editableTabsValue2)"
|
||||||
|
>
|
||||||
|
add tab
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-tabs v-model="editableTabsValue2" type="card" closable @tab-remove="removeTab">
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="(item, index) in editableTabs2"
|
||||||
|
:label="item.title"
|
||||||
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue2: '2',
|
||||||
|
editableTabs2: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addTab(targetName) {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs2.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue2 = newTabName;
|
||||||
|
},
|
||||||
|
removeTab(targetName) {
|
||||||
|
let tabs = this.editableTabs2;
|
||||||
|
let activeName = this.editableTabsValue2;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue2 = activeName;
|
||||||
|
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Tabs Attributes
|
### Tabs Attributes
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------- |---------- |------------- |-------- |
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
| type | type of Tab | string | card/border-card | — |
|
| type | type of Tab | string | card/border-card | — |
|
||||||
| closable | whether Tab is closable | boolean | — | false |
|
| closable | whether Tab is closable | boolean | — | false |
|
||||||
|
| addable | whether Tab is addable | boolean | — | false |
|
||||||
|
| editable | whether Tab is addable and closable | boolean | — | false |
|
||||||
| active-name(deprecated) | name of the selected tab | string | — | name of first tab |
|
| active-name(deprecated) | name of the selected tab | string | — | name of first tab |
|
||||||
| value | name of the selected tab | string | — | name of first tab |
|
| value | name of the selected tab | string | — | name of first tab |
|
||||||
|
|
||||||
|
@ -173,7 +344,9 @@ You can use named slot to customize the tab label content.
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|---------- |-------- |---------- |
|
|---------- |-------- |---------- |
|
||||||
| tab-click | triggers when a tab is clicked | clicked tab |
|
| tab-click | triggers when a tab is clicked | clicked tab |
|
||||||
| tab-remove | triggers when a tab is removed | removed tab |
|
| tab-remove | triggers when tab-remove button is clicked | name of the removed tab |
|
||||||
|
| tab-add | triggers when tab-add button is clicked | — |
|
||||||
|
| edit | triggers when tab-add button or tab-remove is clicked | (targetName, action) |
|
||||||
|
|
||||||
### Tab-pane Attributes
|
### Tab-pane Attributes
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
showInput() {
|
showInput() {
|
||||||
this.inputVisible = true;
|
this.inputVisible = true;
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.$refs.saveTagInput.$refs.input.focus();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInputConfirm() {
|
handleInputConfirm() {
|
||||||
|
@ -150,6 +153,9 @@ You can use the `close` event to add and remove tag dynamically.
|
||||||
|
|
||||||
showInput() {
|
showInput() {
|
||||||
this.inputVisible = true;
|
this.inputVisible = true;
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.$refs.saveTagInput.$refs.input.focus();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInputConfirm() {
|
handleInputConfirm() {
|
||||||
|
|
|
@ -0,0 +1,491 @@
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
optionsWithDisabled: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
disabled: true,
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: [],
|
||||||
|
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.demo-cascader {
|
||||||
|
.el-cascader {
|
||||||
|
width: 222px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.demo-cascader-size {
|
||||||
|
.el-cascader {
|
||||||
|
vertical-align: top;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
## 级联选择
|
||||||
|
|
||||||
|
需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等。
|
||||||
|
|
||||||
|
从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。
|
||||||
|
|
||||||
|
### 基本使用
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
@change="handleChange"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 禁用选项
|
||||||
|
|
||||||
|
通过在数据源中设置 `disabled` 字段来声明该选项时禁用的
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="optionsWithDisabled"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
optionsWithDisabled: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
disabled: true,
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 默认值
|
||||||
|
|
||||||
|
:::demo 默认值通过数组的方式指定。
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions2"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 尺寸
|
||||||
|
|
||||||
|
:::demo 提供三种尺寸的级联选择器
|
||||||
|
```html
|
||||||
|
<div class="demo-cascader-size">
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
size="large"
|
||||||
|
></el-cascader>
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
></el-cascader>
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
size="small"
|
||||||
|
></el-cascader>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 移入展开
|
||||||
|
|
||||||
|
在鼠标移入时就展开下级菜单,完成选择仍需要进行点击。
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
expand-trigger="hover"
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 选择即改变
|
||||||
|
|
||||||
|
该模式下允许只选中父级选项。
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
change-on-select
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 可搜索
|
||||||
|
|
||||||
|
可以直接搜索选项并选择。
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-cascader
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
filterable
|
||||||
|
></el-cascader>
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
|
| options | 可选项数据源 | array | — | — |
|
||||||
|
| value | 指定选中项 | array | — | — |
|
||||||
|
| popper-class | 自定义浮层类名 | string | — | — |
|
||||||
|
| placeholder | 输入框占位文本 | string | — | — |
|
||||||
|
| disabled | 是否禁用 | boolean | — | false |
|
||||||
|
| clearable | 是否支持清除 | boolean | — | false |
|
||||||
|
| expand-trigger | 次级菜单的展开方式 | string | click / hover | 'click' |
|
||||||
|
| filterable | 是否支持搜索选项 | boolean | — | — |
|
||||||
|
| size | 尺寸 | string | large / small / mini | — |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
|---------- |-------- |---------- |
|
||||||
|
| change | 当绑定值变化时触发的事件 | 当前值 |
|
|
@ -1,5 +1,17 @@
|
||||||
## 自定义主题
|
## 自定义主题
|
||||||
Element 默认提供一套主题,CSS 命名采用 BEM 的风格方便使用者覆盖样式。如果你想完全替换主题色或者部分样式,可以使用下面方法。
|
Element 默认提供一套主题,CSS 命名采用 BEM 的风格方便使用者覆盖样式。如果你想完全替换主题色或者部分样式,可以使用下面的方法。
|
||||||
|
|
||||||
|
## 仅替换主题色
|
||||||
|
如果仅希望更换 Element 的主题色,推荐使用[在线主题生成工具](https://elementui.github.io/theme-preview)。
|
||||||
|
|
||||||
|
Element 默认的主题色是鲜艳、友好的蓝色。通过替换主题色,能够让 Element 的视觉更加符合具体项目的定位。
|
||||||
|
|
||||||
|
使用上述工具,可以很方便地实时预览主题色改变之后的视觉,同时它还可以基于新的主题色生成完整的样式文件包,供直接下载使用(关于如何使用下载的主题包,请参考本节「引入自定义主题」和「搭配插件按需引入组件主题」部分)。
|
||||||
|
|
||||||
|
如果希望进行除主题色之外的样式定制,请继续阅读。
|
||||||
|
|
||||||
|
## 深层次的定制
|
||||||
|
如果仅仅改变主题色不能满足你的需求,请按以下步骤进行更深层次的主题定制:
|
||||||
|
|
||||||
### 安装工具
|
### 安装工具
|
||||||
首先安装「主题生成工具」,可以全局安装或者安装在当前项目下,推荐安装在项目里,方便别人 clone 项目时能直接安装依赖并启动,这里以全局安装做演示。
|
首先安装「主题生成工具」,可以全局安装或者安装在当前项目下,推荐安装在项目里,方便别人 clone 项目时能直接安装依赖并启动,这里以全局安装做演示。
|
||||||
|
|
|
@ -183,6 +183,7 @@ Dialog 组件的内容可以是任意的,甚至可以是表格或表单,下
|
||||||
| size | Dialog 的大小 | string | tiny/small/large/full | small |
|
| size | Dialog 的大小 | string | tiny/small/large/full | small |
|
||||||
| top | Dialog CSS 中的 top 值(仅在 size 不为 full 时有效) | string | — | 15% |
|
| top | Dialog CSS 中的 top 值(仅在 size 不为 full 时有效) | string | — | 15% |
|
||||||
| modal | 是否需要遮罩层 | boolean | — | true |
|
| modal | 是否需要遮罩层 | boolean | — | true |
|
||||||
|
| modal-append-to-body | 遮罩层是否插入至 body 元素上,若为 false,则遮罩层会插入至 Dialog 的父元素上 | boolean | — | true |
|
||||||
| lock-scroll | 是否在 Dialog 出现时将 body 滚动锁定 | boolean | — | true |
|
| lock-scroll | 是否在 Dialog 出现时将 body 滚动锁定 | boolean | — | true |
|
||||||
| custom-class | Dialog 的自定义类名 | string | — | — |
|
| custom-class | Dialog 的自定义类名 | string | — | — |
|
||||||
| close-on-click-modal | 是否可以通过点击 modal 关闭 Dialog | boolean | — | true |
|
| close-on-click-modal | 是否可以通过点击 modal 关闭 Dialog | boolean | — | true |
|
||||||
|
|
|
@ -84,6 +84,33 @@ Vue.use(Element, {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 通过 CDN 的方式加载语言文件
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="//unpkg.com/vue"></script>
|
||||||
|
<script src="//unpkg.com/element-ui"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/en.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
ELEMENT.locale(ELEMENT.lang.en)
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
搭配 `vue-i18n` 使用
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="//unpkg.com/vue"></script>
|
||||||
|
<script src="//unpkg.com/vue-i18n/dist/vue-i18n.js"></script>
|
||||||
|
<script src="//unpkg.com/element-ui"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/zh-CN.js"></script>
|
||||||
|
<script src="//unpkg.com/element-ui/lib/umd/locale/en.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Vue.locale('en', ELEMENT.lang.en)
|
||||||
|
Vue.locale('zh-cn', ELEMENT.lang.zhCN)
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
目前 Element 内置了以下语言:
|
目前 Element 内置了以下语言:
|
||||||
<ul class="language-list">
|
<ul class="language-list">
|
||||||
<li>简体中文(zh-CN)</li>
|
<li>简体中文(zh-CN)</li>
|
||||||
|
|
|
@ -161,7 +161,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-autocomplete__suggestions.my-autocomplete {
|
.el-autocomplete-suggestion.my-autocomplete {
|
||||||
li {
|
li {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
padding: 7px *;
|
padding: 7px *;
|
||||||
|
@ -174,7 +174,6 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #b4b4b4;
|
color: #b4b4b4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted .addr {
|
.highlighted .addr {
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
### Radio Attributes
|
### Radio Attributes
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|---------- |-------- |---------- |------------- |-------- |
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
| label | Radio 的 value | string,number | — | — |
|
| label | Radio 的 value | string,number,boolean | — | — |
|
||||||
| disabled | 是否禁用 | boolean | — | false |
|
| disabled | 是否禁用 | boolean | — | false |
|
||||||
| name | 原生 name 属性 | string | — | — |
|
| name | 原生 name 属性 | string | — | — |
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|---------- |-------- |---------- |------------- |-------- |
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
| space | 每个 step 的间距,不填写将自适应间距 | Number | — | — |
|
| space | 每个 step 的间距,不填写将自适应间距。支持百分比。 | Number,String | — | — |
|
||||||
| direction | 显示方向 | string | vertical/horizontal | horizontal |
|
| direction | 显示方向 | string | vertical/horizontal | horizontal |
|
||||||
| active | 设置当前激活步骤 | number | — | 0 |
|
| active | 设置当前激活步骤 | number | — | 0 |
|
||||||
| process-status | 设置当前步骤的状态 | string | wait/process/finish/error/success | process |
|
| process-status | 设置当前步骤的状态 | string | wait/process/finish/error/success | process |
|
||||||
|
|
|
@ -4,7 +4,18 @@
|
||||||
return {
|
return {
|
||||||
activeName: 'second',
|
activeName: 'second',
|
||||||
activeName2: 'first',
|
activeName2: 'first',
|
||||||
tabs: [{
|
editableTabsValue: '2',
|
||||||
|
editableTabsValue2: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
editableTabs2: [{
|
||||||
title: 'Tab 1',
|
title: 'Tab 1',
|
||||||
name: '1',
|
name: '1',
|
||||||
content: 'Tab 1 content'
|
content: 'Tab 1 content'
|
||||||
|
@ -17,11 +28,62 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleRemove(tab) {
|
|
||||||
console.log(tab);
|
|
||||||
},
|
|
||||||
handleClick(tab, event) {
|
handleClick(tab, event) {
|
||||||
console.log(tab, event);
|
console.log(tab, event);
|
||||||
|
},
|
||||||
|
handleTabsEdit(targetName, action) {
|
||||||
|
if (action === 'add') {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
}
|
||||||
|
if (action === 'remove') {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addTab(targetName) {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs2.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue2 = newTabName;
|
||||||
|
},
|
||||||
|
removeTab(targetName) {
|
||||||
|
let tabs = this.editableTabs2;
|
||||||
|
let activeName = this.editableTabsValue2;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue2 = activeName;
|
||||||
|
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,36 +157,6 @@
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### 可关闭
|
|
||||||
|
|
||||||
可以关闭标签页。
|
|
||||||
|
|
||||||
:::demo 通过设置 `closable` 属性来打开 `Tabs` 的可关闭标签效果, `closable` 也可以设置在 `Tab Panel` 中实现部分标签页的可关闭效果。
|
|
||||||
|
|
||||||
```html
|
|
||||||
<template>
|
|
||||||
<el-tabs type="card" closable @tab-click="handleClick" @tab-remove="handleRemove">
|
|
||||||
<el-tab-pane label="用户管理">用户管理</el-tab-pane>
|
|
||||||
<el-tab-pane label="配置管理">配置管理</el-tab-pane>
|
|
||||||
<el-tab-pane label="角色管理">角色管理</el-tab-pane>
|
|
||||||
<el-tab-pane label="定时任务补偿">定时任务补偿</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
handleRemove(tab) {
|
|
||||||
console.log(tab);
|
|
||||||
},
|
|
||||||
handleClick(tab, event) {
|
|
||||||
console.log(tab, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
### 卡片化
|
### 卡片化
|
||||||
|
|
||||||
卡片化的标签页。
|
卡片化的标签页。
|
||||||
|
@ -158,18 +190,141 @@
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### 动态增加标签页
|
### 动态增减标签页
|
||||||
|
|
||||||
展示如何通过触发器来动态增加标签页
|
增减标签页按钮只能在选项卡样式的标签页下使用
|
||||||
|
|
||||||
|
:::demo
|
||||||
|
```html
|
||||||
|
<el-tabs v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="(item, index) in editableTabs"
|
||||||
|
:label="item.title"
|
||||||
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleTabsEdit(targetName, action) {
|
||||||
|
if (action === 'add') {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
}
|
||||||
|
if (action === 'remove') {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 自定义增加标签页触发器
|
||||||
|
|
||||||
:::demo
|
:::demo
|
||||||
```html
|
```html
|
||||||
<div style="margin-bottom: 20px;">
|
<div style="margin-bottom: 20px;">
|
||||||
<el-button size="small" @click="tabs.push({ name: 'Tab ' + ++tabIndex, title: 'new Tab', content: 'new Tab content' })">add tab</el-button>
|
<el-button
|
||||||
|
size="small"
|
||||||
|
@click="addTab(editableTabsValue2)"
|
||||||
|
>
|
||||||
|
add tab
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-tabs type="card" closable>
|
<el-tabs v-model="editableTabsValue2" type="card" closable @tab-remove="removeTab">
|
||||||
<el-tab-pane v-for="(item, index) in tabs" :label="item.title" :name="item.name">{{item.content}}</el-tab-pane>
|
<el-tab-pane
|
||||||
|
v-for="(item, index) in editableTabs2"
|
||||||
|
:label="item.title"
|
||||||
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue2: '2',
|
||||||
|
editableTabs2: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addTab(targetName) {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs2.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue2 = newTabName;
|
||||||
|
},
|
||||||
|
removeTab(targetName) {
|
||||||
|
let tabs = this.editableTabs2;
|
||||||
|
let activeName = this.editableTabsValue2;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editableTabsValue2 = activeName;
|
||||||
|
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
@ -178,14 +333,18 @@
|
||||||
|---------- |-------- |---------- |------------- |-------- |
|
|---------- |-------- |---------- |------------- |-------- |
|
||||||
| type | 风格类型 | string | card/border-card | — |
|
| type | 风格类型 | string | card/border-card | — |
|
||||||
| closable | 标签是否可关闭 | boolean | — | false |
|
| closable | 标签是否可关闭 | boolean | — | false |
|
||||||
|
| addable | 标签是否可增加 | boolean | — | false |
|
||||||
|
| editable | 标签是否同时可增加和关闭 | boolean | — | false |
|
||||||
| active-name(deprecated) | 选中选项卡的 name | string | — | 第一个选项卡的 name |
|
| active-name(deprecated) | 选中选项卡的 name | string | — | 第一个选项卡的 name |
|
||||||
| value | 绑定值,选中选项卡的 name | string | — | 第一个选项卡的 name |
|
| value | 绑定值,选中选项卡的 name | string | — | 第一个选项卡的 name |
|
||||||
|
|
||||||
### Tabs Events
|
### Tabs Events
|
||||||
| 事件名称 | 说明 | 回调参数 |
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|---------- |-------- |---------- |
|
|---------- |-------- |---------- |
|
||||||
| tab-click | tab 被选中的钩子 | 被选中的标签 tab 实例 |
|
| tab-click | tab 被选中时触发 | 被选中的标签 tab 实例 |
|
||||||
| tab-remove | tab 被删除的钩子 | 被删除的标签 tab 实例 |
|
| tab-remove | 点击 tab 移除按钮后触发 | 被删除的标签的 name |
|
||||||
|
| tab-add | 点击 tabs 的新增按钮后触发 | — |
|
||||||
|
| edit | 点击 tabs 的新增按钮或 tab 被关闭后触发 | (targetName, action) |
|
||||||
|
|
||||||
### Tab-pane Attributes
|
### Tab-pane Attributes
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
showInput() {
|
showInput() {
|
||||||
this.inputVisible = true;
|
this.inputVisible = true;
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.$refs.saveTagInput.$refs.input.focus();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInputConfirm() {
|
handleInputConfirm() {
|
||||||
|
@ -150,6 +153,9 @@
|
||||||
|
|
||||||
showInput() {
|
showInput() {
|
||||||
this.inputVisible = true;
|
this.inputVisible = true;
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.$refs.saveTagInput.$refs.input.focus();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInputConfirm() {
|
handleInputConfirm() {
|
||||||
|
|
|
@ -76,6 +76,10 @@
|
||||||
"path": "/select",
|
"path": "/select",
|
||||||
"title": "Select 选择器"
|
"title": "Select 选择器"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/cascader",
|
||||||
|
"title": "Cascader 级联选择"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/switch",
|
"path": "/switch",
|
||||||
"title": "Switch 开关"
|
"title": "Switch 开关"
|
||||||
|
@ -298,6 +302,10 @@
|
||||||
"path": "/select",
|
"path": "/select",
|
||||||
"title": "Select"
|
"title": "Select"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/cascader",
|
||||||
|
"title": "Cascader"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/switch",
|
"path": "/switch",
|
||||||
"title": "Switch"
|
"title": "Switch"
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
"build:file": "node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js",
|
"build:file": "node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js",
|
||||||
"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-default/gulpfile.js && cp-cli packages/theme-default/lib lib/theme-default",
|
"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-default/gulpfile.js && cp-cli packages/theme-default/lib lib/theme-default",
|
||||||
"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
|
"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
|
||||||
|
"build:umd": "node build/bin/build-locale.js",
|
||||||
"clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage && lerna clean --yes",
|
"clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage && lerna clean --yes",
|
||||||
"deploy": "npm run deploy:build && gh-pages -d examples/element-ui --remote eleme && del examples/element-ui",
|
"deploy": "npm run deploy:build && gh-pages -d examples/element-ui --remote eleme && del examples/element-ui",
|
||||||
"deploy:build": "npm run build:file && cooking build -c build/cooking.demo.js -p && echo element.eleme.io>>examples/element-ui/CNAME",
|
"deploy:build": "npm run build:file && cooking build -c build/cooking.demo.js -p && echo element.eleme.io>>examples/element-ui/CNAME",
|
||||||
"dev": "npm run bootstrap && npm run build:file && cooking watch -c build/cooking.demo.js -p",
|
"dev": "npm run bootstrap && npm run build:file && cooking watch -c build/cooking.demo.js -p",
|
||||||
"dev:play": "npm run build:file && cross-env PLAY_ENV=true cooking watch -c build/cooking.demo.js -p",
|
"dev:play": "npm run build:file && cross-env PLAY_ENV=true cooking watch -c build/cooking.demo.js -p",
|
||||||
"dist": "npm run clean && npm run build:file && npm run lint && cooking build -c build/cooking.conf.js,build/cooking.common.js,build/cooking.component.js -p && npm run build:utils && npm run build:theme",
|
"dist": "npm run clean && npm run build:file && npm run lint && cooking build -c build/cooking.conf.js,build/cooking.common.js,build/cooking.component.js -p && npm run build:utils && npm run build:umd && npm run build:theme",
|
||||||
"dist:all": "node build/bin/build-all.js",
|
"dist:all": "node build/bin/build-all.js && npm run build:theme",
|
||||||
"i18n": "node build/bin/i18n.js",
|
"i18n": "node build/bin/i18n.js",
|
||||||
"lint": "eslint src/**/* test/**/* packages/**/*.{js,vue} build/**/* --quiet",
|
"lint": "eslint src/**/* test/**/* packages/**/*.{js,vue} build/**/* --quiet",
|
||||||
"pub": "npm run bootstrap && sh build/git-release.sh && sh build/release.sh",
|
"pub": "npm run bootstrap && sh build/git-release.sh && sh build/release.sh",
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
"babel-cli": "^6.14.0",
|
"babel-cli": "^6.14.0",
|
||||||
"babel-core": "^6.14.0",
|
"babel-core": "^6.14.0",
|
||||||
"babel-loader": "^6.2.5",
|
"babel-loader": "^6.2.5",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
"babel-plugin-module-resolver": "^2.2.0",
|
"babel-plugin-module-resolver": "^2.2.0",
|
||||||
"babel-plugin-syntax-jsx": "^6.8.0",
|
"babel-plugin-syntax-jsx": "^6.8.0",
|
||||||
"babel-plugin-transform-vue-jsx": "^3.3.0",
|
"babel-plugin-transform-vue-jsx": "^3.3.0",
|
||||||
|
@ -113,7 +115,7 @@
|
||||||
"uppercamelcase": "^1.1.0",
|
"uppercamelcase": "^1.1.0",
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^0.5.7",
|
||||||
"vue": "^2.1.8",
|
"vue": "^2.1.8",
|
||||||
"vue-loader": "^10.0.2",
|
"vue-loader": "^10.3.0",
|
||||||
"vue-markdown-loader": "^0.5.1",
|
"vue-markdown-loader": "^0.5.1",
|
||||||
"vue-router": "^2.0.0",
|
"vue-router": "^2.0.0",
|
||||||
"vue-template-compiler": "^2.1.8",
|
"vue-template-compiler": "^2.1.8",
|
||||||
|
|
|
@ -1,30 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
||||||
<ul
|
<div
|
||||||
v-show="showPopper"
|
v-show="showPopper"
|
||||||
class="el-autocomplete__suggestions"
|
class="el-autocomplete-suggestion"
|
||||||
:class="{ 'is-loading': parent.loading }"
|
:class="{ 'is-loading': parent.loading }"
|
||||||
:style="{ width: dropdownWidth }"
|
:style="{ width: dropdownWidth }"
|
||||||
>
|
>
|
||||||
<li v-if="parent.loading"><i class="el-icon-loading"></i></li>
|
<el-scrollbar
|
||||||
<template v-for="(item, index) in suggestions" v-else>
|
tag="ul"
|
||||||
<li
|
wrap-class="el-autocomplete-suggestion__wrap"
|
||||||
v-if="!parent.customItem"
|
view-class="el-autocomplete-suggestion__list"
|
||||||
:class="{'highlighted': parent.highlightedIndex === index}"
|
>
|
||||||
@click="select(item)"
|
<li v-if="parent.loading"><i class="el-icon-loading"></i></li>
|
||||||
>
|
<template v-for="(item, index) in suggestions" v-else>
|
||||||
{{item.value}}
|
<li
|
||||||
</li>
|
v-if="!parent.customItem"
|
||||||
<component
|
:class="{'highlighted': parent.highlightedIndex === index}"
|
||||||
v-else
|
@click="select(item)"
|
||||||
:class="{'highlighted': parent.highlightedIndex === index}"
|
>
|
||||||
@click="select(item)"
|
{{item.value}}
|
||||||
:is="parent.customItem"
|
</li>
|
||||||
:item="item"
|
<component
|
||||||
:index="index">
|
v-else
|
||||||
</component>
|
:class="{'highlighted': parent.highlightedIndex === index}"
|
||||||
</template>
|
@click="select(item)"
|
||||||
</ul>
|
:is="parent.customItem"
|
||||||
|
:item="item"
|
||||||
|
:index="index">
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -98,6 +98,10 @@
|
||||||
},
|
},
|
||||||
handleChange(value) {
|
handleChange(value) {
|
||||||
this.$emit('input', value);
|
this.$emit('input', value);
|
||||||
|
if (!this.triggerOnFocus && !value) {
|
||||||
|
this.suggestions = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.getData(value);
|
this.getData(value);
|
||||||
},
|
},
|
||||||
handleFocus() {
|
handleFocus() {
|
||||||
|
@ -129,22 +133,22 @@
|
||||||
},
|
},
|
||||||
highlight(index) {
|
highlight(index) {
|
||||||
if (!this.suggestionVisible || this.loading) { return; }
|
if (!this.suggestionVisible || this.loading) { return; }
|
||||||
if (index < 0) {
|
if (index < 0) index = 0;
|
||||||
index = 0;
|
if (index >= this.suggestions.length) {
|
||||||
} else if (index >= this.suggestions.length) {
|
|
||||||
index = this.suggestions.length - 1;
|
index = this.suggestions.length - 1;
|
||||||
}
|
}
|
||||||
var elSuggestions = this.$refs.suggestions.$el;
|
const suggestion = this.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
|
||||||
|
const suggestionList = suggestion.querySelectorAll('.el-autocomplete-suggestion__list li');
|
||||||
|
|
||||||
var elSelect = elSuggestions.children[index];
|
let highlightItem = suggestionList[index];
|
||||||
var scrollTop = elSuggestions.scrollTop;
|
let scrollTop = suggestion.scrollTop;
|
||||||
var offsetTop = elSelect.offsetTop;
|
let offsetTop = highlightItem.offsetTop;
|
||||||
|
|
||||||
if (offsetTop + elSelect.scrollHeight > (scrollTop + elSuggestions.clientHeight)) {
|
if (offsetTop + highlightItem.scrollHeight > (scrollTop + suggestion.clientHeight)) {
|
||||||
elSuggestions.scrollTop += elSelect.scrollHeight;
|
suggestion.scrollTop += highlightItem.scrollHeight;
|
||||||
}
|
}
|
||||||
if (offsetTop < scrollTop) {
|
if (offsetTop < scrollTop) {
|
||||||
elSuggestions.scrollTop -= elSelect.scrollHeight;
|
suggestion.scrollTop -= highlightItem.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.highlightedIndex = index;
|
this.highlightedIndex = index;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
var cooking = require('cooking');
|
||||||
|
var path = require('path');
|
||||||
|
var config = require('../../build/config');
|
||||||
|
|
||||||
|
cooking.set({
|
||||||
|
entry: {
|
||||||
|
index: path.join(__dirname, 'index.js')
|
||||||
|
},
|
||||||
|
dist: path.join(__dirname, 'lib'),
|
||||||
|
template: false,
|
||||||
|
format: 'umd',
|
||||||
|
moduleName: 'ElCascader',
|
||||||
|
extends: ['vue2'],
|
||||||
|
alias: config.alias,
|
||||||
|
externals: { vue: config.vue }
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = cooking.resolve();
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Cascader from './src/main';
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
Cascader.install = function(Vue) {
|
||||||
|
Vue.component(Cascader.name, Cascader);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Cascader;
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "element-cascader",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "A cascader component for Vue.js.",
|
||||||
|
"keywords": [
|
||||||
|
"element",
|
||||||
|
"vue",
|
||||||
|
"component"
|
||||||
|
],
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"repository": "https://github.com/ElemeFE/element/tree/master/packages/cascader",
|
||||||
|
"author": "elemefe",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
<template>
|
||||||
|
<span
|
||||||
|
class="el-cascader"
|
||||||
|
:class="[
|
||||||
|
{
|
||||||
|
'is-opened': menuVisible,
|
||||||
|
'is-disabled': disabled
|
||||||
|
},
|
||||||
|
size ? 'el-cascader--' + size : ''
|
||||||
|
]"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="inputHover = true"
|
||||||
|
@mouseleave="inputHover = false"
|
||||||
|
ref="reference"
|
||||||
|
v-clickoutside="handleClickoutside"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
ref="input"
|
||||||
|
:readonly="!filterable"
|
||||||
|
:placeholder="displayValue ? undefined : placeholder"
|
||||||
|
v-model="inputValue"
|
||||||
|
@change="handleInputChange"
|
||||||
|
:validate-event="false"
|
||||||
|
:size="size"
|
||||||
|
:disabled="disabled"
|
||||||
|
>
|
||||||
|
<template slot="icon">
|
||||||
|
<i
|
||||||
|
key="1"
|
||||||
|
v-if="inputHover && displayValue !== ''"
|
||||||
|
class="el-input__icon el-icon-circle-close el-cascader__clearIcon"
|
||||||
|
@click="clearValue"
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
key="2"
|
||||||
|
v-else
|
||||||
|
class="el-input__icon el-icon-caret-bottom"
|
||||||
|
:class="{ 'is-reverse': menuVisible }"
|
||||||
|
></i>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<span class="el-cascader__label" v-show="inputValue === ''">{{displayValue}}</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue';
|
||||||
|
import ElCascaderMenu from './menu';
|
||||||
|
import ElInput from 'element-ui/packages/input';
|
||||||
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
|
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||||
|
import emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
|
||||||
|
const popperMixin = {
|
||||||
|
props: {
|
||||||
|
placement: {
|
||||||
|
type: String,
|
||||||
|
default: 'bottom-start'
|
||||||
|
},
|
||||||
|
appendToBody: Popper.props.appendToBody,
|
||||||
|
offset: Popper.props.offset,
|
||||||
|
boundariesPadding: Popper.props.boundariesPadding,
|
||||||
|
popperOptions: Popper.props.popperOptions
|
||||||
|
},
|
||||||
|
methods: Popper.methods,
|
||||||
|
data: Popper.data,
|
||||||
|
beforeDestroy: Popper.beforeDestroy
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ElCascader',
|
||||||
|
|
||||||
|
directives: { Clickoutside },
|
||||||
|
|
||||||
|
mixins: [popperMixin, emitter, Locale],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
ElInput
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
placeholder: String,
|
||||||
|
disabled: Boolean,
|
||||||
|
clearable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
changeOnSelect: Boolean,
|
||||||
|
popperClass: String,
|
||||||
|
expandTrigger: {
|
||||||
|
type: String,
|
||||||
|
default: 'click'
|
||||||
|
},
|
||||||
|
filterable: Boolean,
|
||||||
|
size: String
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentValue: this.value,
|
||||||
|
displayValue: this.value.join('/'),
|
||||||
|
menuVisible: false,
|
||||||
|
inputHover: false,
|
||||||
|
inputValue: '',
|
||||||
|
flatOptions: this.filterable && this.flattenOptions(this.options)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
menuVisible(value) {
|
||||||
|
value ? this.showMenu() : this.hideMenu();
|
||||||
|
},
|
||||||
|
value(value) {
|
||||||
|
this.currentValue = value;
|
||||||
|
},
|
||||||
|
currentValue(value) {
|
||||||
|
this.displayValue = value.join('/');
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', [value]);
|
||||||
|
},
|
||||||
|
options(value) {
|
||||||
|
this.menu.options = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
showMenu() {
|
||||||
|
if (!this.menu) {
|
||||||
|
this.menu = new Vue(ElCascaderMenu).$mount();
|
||||||
|
this.menu.options = this.options;
|
||||||
|
this.menu.expandTrigger = this.expandTrigger;
|
||||||
|
this.menu.changeOnSelect = this.changeOnSelect;
|
||||||
|
this.menu.popperClass = this.popperClass;
|
||||||
|
this.popperElm = this.menu.$el;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.menu.value = this.currentValue.slice(0);
|
||||||
|
this.menu.visible = true;
|
||||||
|
this.menu.options = this.options;
|
||||||
|
this.menu.$on('pick', this.handlePick);
|
||||||
|
this.updatePopper();
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.menu.inputWidth = this.$refs.input.$el.offsetWidth - 2;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
hideMenu() {
|
||||||
|
this.inputValue = '';
|
||||||
|
this.menu.visible = false;
|
||||||
|
},
|
||||||
|
handlePick(value, close = true) {
|
||||||
|
this.currentValue = value;
|
||||||
|
this.$emit('input', value);
|
||||||
|
this.$emit('change', value);
|
||||||
|
|
||||||
|
if (close) {
|
||||||
|
this.menuVisible = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleInputChange(value) {
|
||||||
|
if (!this.menuVisible) return;
|
||||||
|
const flatOptions = this.flatOptions;
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
this.menu.options = this.options;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filteredFlatOptions = flatOptions.filter(optionsStack => {
|
||||||
|
return optionsStack.some(option => option.label.indexOf(value) > -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (filteredFlatOptions.length > 0) {
|
||||||
|
filteredFlatOptions = filteredFlatOptions.map(optionStack => {
|
||||||
|
return {
|
||||||
|
__IS__FLAT__OPTIONS: true,
|
||||||
|
value: optionStack.map(item => item.value),
|
||||||
|
label: this.renderFilteredOptionLabel(value, optionStack)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
filteredFlatOptions = [{
|
||||||
|
__IS__FLAT__OPTIONS: true,
|
||||||
|
label: this.t('el.cascader.noMatch'),
|
||||||
|
value: '',
|
||||||
|
disabled: true
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
this.menu.options = filteredFlatOptions;
|
||||||
|
},
|
||||||
|
renderFilteredOptionLabel(inputValue, optionsStack) {
|
||||||
|
return optionsStack.map(({ label }, index) => {
|
||||||
|
const node = label.indexOf(inputValue) > -1 ? this.highlightKeyword(label, inputValue) : label;
|
||||||
|
return index === 0 ? node : [' / ', node];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
highlightKeyword(label, keyword) {
|
||||||
|
const h = this._c;
|
||||||
|
return label.split(keyword)
|
||||||
|
.map((node, index) => index === 0 ? node : [
|
||||||
|
h('span', { class: { 'el-cascader-menu__item__keyword': true }}, [this._v(keyword)]),
|
||||||
|
node
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
flattenOptions(options, ancestor = []) {
|
||||||
|
let flatOptions = [];
|
||||||
|
options.forEach((option) => {
|
||||||
|
const optionsStack = ancestor.concat(option);
|
||||||
|
if (!option.children) {
|
||||||
|
flatOptions.push(optionsStack);
|
||||||
|
} else {
|
||||||
|
flatOptions = flatOptions.concat(this.flattenOptions(option.children, optionsStack));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return flatOptions;
|
||||||
|
},
|
||||||
|
clearValue(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.handlePick([], true);
|
||||||
|
},
|
||||||
|
handleClickoutside() {
|
||||||
|
this.menuVisible = false;
|
||||||
|
},
|
||||||
|
handleClick() {
|
||||||
|
if (this.disabled) return;
|
||||||
|
if (this.filterable) {
|
||||||
|
this.menuVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.menuVisible = !this.menuVisible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,148 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ElCascaderMenu',
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
inputWidth: 0,
|
||||||
|
options: [],
|
||||||
|
visible: false,
|
||||||
|
activeValue: [],
|
||||||
|
value: [],
|
||||||
|
expandTrigger: 'click',
|
||||||
|
changeOnSelect: false,
|
||||||
|
popperClass: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
visible(value) {
|
||||||
|
if (value) {
|
||||||
|
this.activeValue = this.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
immediate: true,
|
||||||
|
handler(value) {
|
||||||
|
this.activeValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
activeOptions: {
|
||||||
|
cache: false,
|
||||||
|
get() {
|
||||||
|
const activeValue = this.activeValue;
|
||||||
|
|
||||||
|
const loadActiveOptions = (options, activeOptions = []) => {
|
||||||
|
const level = activeOptions.length;
|
||||||
|
activeOptions[level] = options;
|
||||||
|
let active = activeValue[level];
|
||||||
|
if (active) {
|
||||||
|
options = options.filter(option => option.value === active)[0];
|
||||||
|
if (options && options.children) {
|
||||||
|
loadActiveOptions(options.children, activeOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activeOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
return loadActiveOptions(this.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
select(item, menuIndex) {
|
||||||
|
if (item.__IS__FLAT__OPTIONS) {
|
||||||
|
this.activeValue = item.value;
|
||||||
|
} else {
|
||||||
|
this.activeValue.splice(menuIndex, 1, item.value);
|
||||||
|
}
|
||||||
|
this.$emit('pick', this.activeValue);
|
||||||
|
},
|
||||||
|
activeItem(item, menuIndex) {
|
||||||
|
const len = this.activeOptions.length;
|
||||||
|
this.activeValue.splice(menuIndex, len, item.value);
|
||||||
|
this.activeOptions.splice(menuIndex + 1, len, item.children);
|
||||||
|
if (this.changeOnSelect) this.$emit('pick', this.activeValue, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
const {
|
||||||
|
activeValue,
|
||||||
|
activeOptions,
|
||||||
|
visible,
|
||||||
|
expandTrigger,
|
||||||
|
popperClass
|
||||||
|
} = this;
|
||||||
|
|
||||||
|
const menus = this._l(activeOptions, (menu, menuIndex) => {
|
||||||
|
let isFlat = false;
|
||||||
|
const items = this._l(menu, item => {
|
||||||
|
const events = {
|
||||||
|
on: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.__IS__FLAT__OPTIONS) isFlat = true;
|
||||||
|
|
||||||
|
if (!item.disabled) {
|
||||||
|
if (item.children) {
|
||||||
|
let triggerEvent = {
|
||||||
|
click: 'click',
|
||||||
|
hover: 'mouseenter'
|
||||||
|
}[expandTrigger];
|
||||||
|
events.on[triggerEvent] = () => { this.activeItem(item, menuIndex); };
|
||||||
|
} else {
|
||||||
|
events.on.click = () => { this.select(item, menuIndex); };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
class={{
|
||||||
|
'el-cascader-menu__item': true,
|
||||||
|
'el-cascader-menu__item--extensible': item.children,
|
||||||
|
'is-active': item.value === activeValue[menuIndex],
|
||||||
|
'is-disabled': item.disabled
|
||||||
|
}}
|
||||||
|
{...events}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let menuStyle = {};
|
||||||
|
if (isFlat) {
|
||||||
|
menuStyle.width = this.inputWidth + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul
|
||||||
|
class={{
|
||||||
|
'el-cascader-menu': true,
|
||||||
|
'el-cascader-menu--flexible': isFlat
|
||||||
|
}}
|
||||||
|
style={menuStyle}>
|
||||||
|
{items}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<transition name="el-zoom-in-top">
|
||||||
|
<div
|
||||||
|
v-show={visible}
|
||||||
|
class={[
|
||||||
|
'el-cascader-menus',
|
||||||
|
popperClass
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{menus}
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -329,7 +329,7 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
RANGE_SEPARATOR = this.rangeSeparator;
|
RANGE_SEPARATOR = this.rangeSeparator;
|
||||||
// vue-popper
|
// vue-popper
|
||||||
this.options = {
|
this.popperOptions = {
|
||||||
boundariesPadding: 0,
|
boundariesPadding: 0,
|
||||||
gpuAcceleration: false
|
gpuAcceleration: false
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,11 @@
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
modalAppendToBody: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
|
||||||
lockScroll: {
|
lockScroll: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
|
<template>
|
||||||
|
<li class="el-menu-item-group">
|
||||||
|
<div class="el-menu-item-group__title" :style="{paddingLeft: levelPadding + 'px'}">
|
||||||
|
<template v-if="!$slots.title">{{title}}</template>
|
||||||
|
<slot v-else name="title"></slot>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<slot></slot>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
<script>
|
<script>
|
||||||
module.exports = {
|
export default {
|
||||||
name: 'ElMenuItemGroup',
|
name: 'ElMenuItemGroup',
|
||||||
|
|
||||||
componentName: 'ElMenuItemGroup',
|
componentName: 'ElMenuItemGroup',
|
||||||
|
@ -31,14 +42,3 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
|
||||||
<li class="el-menu-item-group">
|
|
||||||
<div class="el-menu-item-group__title" :style="{paddingLeft: levelPadding + 'px'}">
|
|
||||||
<template v-if="!$slots.title">{{title}}</template>
|
|
||||||
<slot v-else name="title"></slot>
|
|
||||||
</div>
|
|
||||||
<ul>
|
|
||||||
<slot></slot>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
import Menu from './menu-mixin';
|
import Menu from './menu-mixin';
|
||||||
import Emitter from 'element-ui/src/mixins/emitter';
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
name: 'ElMenuItem',
|
name: 'ElMenuItem',
|
||||||
|
|
||||||
componentName: 'ElMenuItem',
|
componentName: 'ElMenuItem',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
indexPath() {
|
indexPath() {
|
||||||
var path = [this.index];
|
var path = [this.index];
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
import Emitter from 'element-ui/src/mixins/emitter';
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
|
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
name: 'ElSubmenu',
|
name: 'ElSubmenu',
|
||||||
|
|
||||||
componentName: 'ElSubmenu',
|
componentName: 'ElSubmenu',
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
mixins: [Emitter],
|
mixins: [Emitter],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
value: [String, Number],
|
value: {},
|
||||||
size: String,
|
size: String,
|
||||||
fill: String,
|
fill: String,
|
||||||
textColor: String,
|
textColor: String,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
options: {
|
popperOptions: {
|
||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
forceAbsolute: true,
|
forceAbsolute: true,
|
||||||
|
|
|
@ -69,7 +69,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
beforeCreate() {
|
||||||
this.$parent.steps.push(this);
|
this.$parent.steps.push(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -118,9 +118,11 @@ export default {
|
||||||
const isCenter = parent.center;
|
const isCenter = parent.center;
|
||||||
const len = parent.steps.length;
|
const len = parent.steps.length;
|
||||||
const isLast = this.isLast = parent.steps[parent.steps.length - 1] === this;
|
const isLast = this.isLast = parent.steps[parent.steps.length - 1] === this;
|
||||||
const space = parent.space
|
const space = typeof parent.space === 'number'
|
||||||
? parent.space + 'px'
|
? parent.space + 'px'
|
||||||
: 100 / (isCenter ? len - 1 : len) + '%';
|
: parent.space
|
||||||
|
? parent.space
|
||||||
|
: 100 / (isCenter ? len - 1 : len) + '%';
|
||||||
|
|
||||||
if (parent.direction === 'horizontal') {
|
if (parent.direction === 'horizontal') {
|
||||||
this.style = { width: space };
|
this.style = { width: space };
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default {
|
||||||
name: 'ElSteps',
|
name: 'ElSteps',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
space: Number,
|
space: [Number, String],
|
||||||
active: Number,
|
active: Number,
|
||||||
direction: {
|
direction: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -39,13 +39,13 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
active(newVal, oldVal) {
|
active(newVal, oldVal) {
|
||||||
this.$emit('change', newVal, oldVal);
|
this.$emit('change', newVal, oldVal);
|
||||||
}
|
},
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
steps(steps) {
|
||||||
this.steps.forEach((child, index) => {
|
steps.forEach((child, index) => {
|
||||||
child.index = index;
|
child.index = index;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -182,8 +182,7 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
this.customRender = this.$options.render;
|
this.customRender = this.$options.render;
|
||||||
this.$options.render = h => h('div', this.$slots.default);
|
this.$options.render = h => h('div', this.$slots.default);
|
||||||
|
this.columnId = (this.$parent.tableId || (this.$parent.columnId + '_')) + 'column_' + columnIdSeed++;
|
||||||
let columnId = this.columnId = this.columnKey || ((this.$parent.tableId || (this.$parent.columnId + '_')) + 'column_' + columnIdSeed++);
|
|
||||||
|
|
||||||
let parent = this.$parent;
|
let parent = this.$parent;
|
||||||
let owner = this.owner;
|
let owner = this.owner;
|
||||||
|
@ -210,7 +209,8 @@ export default {
|
||||||
let isColumnGroup = false;
|
let isColumnGroup = false;
|
||||||
|
|
||||||
let column = getDefaultColumn(type, {
|
let column = getDefaultColumn(type, {
|
||||||
id: columnId,
|
id: this.columnId,
|
||||||
|
columnKey: this.columnKey,
|
||||||
label: this.label,
|
label: this.label,
|
||||||
className: this.className,
|
className: this.className,
|
||||||
property: this.prop || this.property,
|
property: this.prop || this.property,
|
||||||
|
|
|
@ -87,14 +87,14 @@ TableStore.prototype.mutations = {
|
||||||
states._data = data;
|
states._data = data;
|
||||||
states.data = sortData((data || []), states);
|
states.data = sortData((data || []), states);
|
||||||
|
|
||||||
states.data.forEach((item) => {
|
// states.data.forEach((item) => {
|
||||||
if (!item.$extra) {
|
// if (!item.$extra) {
|
||||||
Object.defineProperty(item, '$extra', {
|
// Object.defineProperty(item, '$extra', {
|
||||||
value: {},
|
// value: {},
|
||||||
enumerable: false
|
// enumerable: false
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
this.updateCurrentRow();
|
this.updateCurrentRow();
|
||||||
|
|
||||||
|
@ -152,15 +152,17 @@ TableStore.prototype.mutations = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const prop = column.property;
|
const prop = column.property;
|
||||||
|
const filters = [];
|
||||||
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
states.filters[column.id] = values;
|
states.filters[column.id] = values;
|
||||||
|
filters[column.columnKey || column.id] = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = states._data;
|
let data = states._data;
|
||||||
const filters = states.filters;
|
|
||||||
|
|
||||||
Object.keys(filters).forEach((columnId) => {
|
Object.keys(states.filters).forEach((columnId) => {
|
||||||
const values = filters[columnId];
|
const values = states.filters[columnId];
|
||||||
if (!values || values.length === 0) return;
|
if (!values || values.length === 0) return;
|
||||||
const column = getColumnById(this.states, columnId);
|
const column = getColumnById(this.states, columnId);
|
||||||
if (column && column.filterMethod) {
|
if (column && column.filterMethod) {
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
name: 'TabBar',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
tabs: Array
|
tabs: Array
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
barStyle: {
|
barStyle: {
|
||||||
cache: false,
|
cache: false,
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
<script>
|
||||||
|
import TabBar from './tab-bar';
|
||||||
|
|
||||||
|
function noop() {}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TabNav',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
TabBar
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
panes: Array,
|
||||||
|
currentName: String,
|
||||||
|
editable: Boolean,
|
||||||
|
onTabClick: {
|
||||||
|
type: Function,
|
||||||
|
default: noop
|
||||||
|
},
|
||||||
|
onTabRemove: {
|
||||||
|
type: Function,
|
||||||
|
default: noop
|
||||||
|
},
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scrollable: false,
|
||||||
|
navStyle: {
|
||||||
|
transform: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
scrollPrev() {
|
||||||
|
const containerWidth = this.$refs.navScroll.offsetWidth;
|
||||||
|
const currentOffset = this.getCurrentScrollOffset();
|
||||||
|
|
||||||
|
if (!currentOffset) return;
|
||||||
|
|
||||||
|
let newOffset = currentOffset > containerWidth
|
||||||
|
? currentOffset - containerWidth
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
this.setOffset(newOffset);
|
||||||
|
},
|
||||||
|
scrollNext() {
|
||||||
|
const navWidth = this.$refs.nav.offsetWidth;
|
||||||
|
const containerWidth = this.$refs.navScroll.offsetWidth;
|
||||||
|
const currentOffset = this.getCurrentScrollOffset();
|
||||||
|
|
||||||
|
if (navWidth - currentOffset <= containerWidth) return;
|
||||||
|
|
||||||
|
let newOffset = navWidth - currentOffset > containerWidth * 2
|
||||||
|
? currentOffset + containerWidth
|
||||||
|
: (navWidth - containerWidth);
|
||||||
|
|
||||||
|
this.setOffset(newOffset);
|
||||||
|
},
|
||||||
|
scrollToActiveTab() {
|
||||||
|
if (!this.scrollable) return;
|
||||||
|
const nav = this.$refs.nav;
|
||||||
|
const activeTab = this.$el.querySelector('.is-active');
|
||||||
|
const navScroll = this.$refs.navScroll;
|
||||||
|
const activeTabBounding = activeTab.getBoundingClientRect();
|
||||||
|
const navScrollBounding = navScroll.getBoundingClientRect();
|
||||||
|
const navBounding = nav.getBoundingClientRect();
|
||||||
|
const currentOffset = this.getCurrentScrollOffset();
|
||||||
|
let newOffset = currentOffset;
|
||||||
|
|
||||||
|
if (activeTabBounding.left < navScrollBounding.left) {
|
||||||
|
newOffset = currentOffset - (navScrollBounding.left - activeTabBounding.left);
|
||||||
|
}
|
||||||
|
if (activeTabBounding.right > navScrollBounding.right) {
|
||||||
|
newOffset = currentOffset + activeTabBounding.right - navScrollBounding.right;
|
||||||
|
}
|
||||||
|
if (navBounding.right < navScrollBounding.right) {
|
||||||
|
newOffset = nav.offsetWidth - navScrollBounding.width;
|
||||||
|
}
|
||||||
|
this.setOffset(Math.max(newOffset, 0));
|
||||||
|
},
|
||||||
|
getCurrentScrollOffset() {
|
||||||
|
const { navStyle } = this;
|
||||||
|
return navStyle.transform
|
||||||
|
? Number(navStyle.transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1])
|
||||||
|
: 0;
|
||||||
|
},
|
||||||
|
setOffset(value) {
|
||||||
|
this.navStyle.transform = `translateX(-${value}px)`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updated() {
|
||||||
|
const navWidth = this.$refs.nav.offsetWidth;
|
||||||
|
const containerWidth = this.$refs.navScroll.offsetWidth;
|
||||||
|
const currentOffset = this.getCurrentScrollOffset();
|
||||||
|
|
||||||
|
if (containerWidth < navWidth) {
|
||||||
|
const currentOffset = this.getCurrentScrollOffset();
|
||||||
|
this.scrollable = this.scrollable || {};
|
||||||
|
this.scrollable.prev = currentOffset;
|
||||||
|
this.scrollable.next = currentOffset + containerWidth < navWidth;
|
||||||
|
if (navWidth - currentOffset < containerWidth) {
|
||||||
|
this.setOffset(navWidth - containerWidth);
|
||||||
|
}
|
||||||
|
} else if (currentOffset > 0) {
|
||||||
|
this.setOffset(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
panes,
|
||||||
|
editable,
|
||||||
|
onTabClick,
|
||||||
|
onTabRemove,
|
||||||
|
navStyle,
|
||||||
|
scrollable,
|
||||||
|
scrollNext,
|
||||||
|
scrollPrev
|
||||||
|
} = this;
|
||||||
|
|
||||||
|
const scrollBtn = scrollable
|
||||||
|
? [
|
||||||
|
<span class={['el-tabs__nav-prev', scrollable.prev ? '' : 'is-disabled']} on-click={scrollPrev}><i class="el-icon-arrow-left"></i></span>,
|
||||||
|
<span class={['el-tabs__nav-next', scrollable.next ? '' : 'is-disabled']} on-click={scrollNext}><i class="el-icon-arrow-right"></i></span>
|
||||||
|
] : null;
|
||||||
|
|
||||||
|
const tabs = this._l(panes, (pane, index) => {
|
||||||
|
let tabName = pane.name || pane.index || index;
|
||||||
|
const closable = pane.isClosable || editable;
|
||||||
|
|
||||||
|
pane.index = `${index}`;
|
||||||
|
|
||||||
|
const btnClose = closable
|
||||||
|
? <span class="el-icon-close" on-click={(ev) => { onTabRemove(pane, ev); }}></span>
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const tabLabelContent = pane.$slots.label || pane.label;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={{
|
||||||
|
'el-tabs__item': true,
|
||||||
|
'is-active': pane.active,
|
||||||
|
'is-disabled': pane.disabled,
|
||||||
|
'is-closable': closable
|
||||||
|
}}
|
||||||
|
ref="tabs"
|
||||||
|
refInFor
|
||||||
|
on-click={(ev) => { onTabClick(pane, tabName, ev); }}
|
||||||
|
>
|
||||||
|
{tabLabelContent}
|
||||||
|
{btnClose}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div class={['el-tabs__nav-wrap', scrollable ? 'is-scrollable' : '']}>
|
||||||
|
{scrollBtn}
|
||||||
|
<div class={['el-tabs__nav-scroll']} ref="navScroll">
|
||||||
|
<div class="el-tabs__nav" ref="nav" style={navStyle}>
|
||||||
|
{!type ? <tab-bar tabs={panes}></tab-bar> : null}
|
||||||
|
{tabs}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
module.exports = {
|
export default {
|
||||||
name: 'ElTabPane',
|
name: 'ElTabPane',
|
||||||
|
|
||||||
componentName: 'ElTabPane',
|
componentName: 'ElTabPane',
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
<script>
|
<script>
|
||||||
import TabBar from './tab-bar';
|
import TabNav from './tab-nav';
|
||||||
module.exports = {
|
|
||||||
|
export default {
|
||||||
name: 'ElTabs',
|
name: 'ElTabs',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
TabBar
|
TabNav
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
type: String,
|
type: String,
|
||||||
activeName: String,
|
activeName: String,
|
||||||
closable: {
|
closable: Boolean,
|
||||||
type: Boolean,
|
addable: Boolean,
|
||||||
default: false
|
value: {},
|
||||||
},
|
editable: Boolean
|
||||||
value: {}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
children: null,
|
|
||||||
currentName: this.value || this.activeName,
|
currentName: this.value || this.activeName,
|
||||||
panes: []
|
panes: []
|
||||||
};
|
};
|
||||||
|
@ -31,57 +30,31 @@
|
||||||
},
|
},
|
||||||
value(value) {
|
value(value) {
|
||||||
this.setCurrentName(value);
|
this.setCurrentName(value);
|
||||||
}
|
},
|
||||||
},
|
currentName(value) {
|
||||||
|
if (this.$refs.nav) {
|
||||||
computed: {
|
this.$nextTick(_ => {
|
||||||
currentTab() {
|
this.$refs.nav.scrollToActiveTab();
|
||||||
let result;
|
});
|
||||||
this.panes.forEach(tab => {
|
}
|
||||||
if (this.currentName === (tab.name || tab.index)) {
|
|
||||||
result = tab;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
handleTabRemove(pane, event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
const panes = this.panes;
|
|
||||||
const currentTab = this.currentTab;
|
|
||||||
|
|
||||||
let index = panes.indexOf(pane);
|
|
||||||
|
|
||||||
if (index === -1) return;
|
|
||||||
|
|
||||||
panes.splice(index, 1);
|
|
||||||
pane.$destroy();
|
|
||||||
|
|
||||||
this.$emit('tab-remove', pane);
|
|
||||||
|
|
||||||
this.$nextTick(_ => {
|
|
||||||
if (pane.active) {
|
|
||||||
const panes = this.panes;
|
|
||||||
let nextChild = panes[index];
|
|
||||||
let prevChild = panes[index - 1];
|
|
||||||
let nextActiveTab = nextChild || prevChild || null;
|
|
||||||
|
|
||||||
if (nextActiveTab) {
|
|
||||||
this.setCurrentName(nextActiveTab.name || nextActiveTab.index);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.setCurrentName(currentTab.name || currentTab.index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleTabClick(tab, tabName, event) {
|
handleTabClick(tab, tabName, event) {
|
||||||
if (tab.disabled) return;
|
if (tab.disabled) return;
|
||||||
this.setCurrentName(tabName);
|
this.setCurrentName(tabName);
|
||||||
this.$emit('tab-click', tab, event);
|
this.$emit('tab-click', tab, event);
|
||||||
},
|
},
|
||||||
|
handleTabRemove(pane, ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.$emit('edit', pane.name, 'remove');
|
||||||
|
this.$emit('tab-remove', pane.name);
|
||||||
|
},
|
||||||
|
handleTabAdd() {
|
||||||
|
this.$emit('edit', null, 'add');
|
||||||
|
this.$emit('tab-add');
|
||||||
|
},
|
||||||
setCurrentName(value) {
|
setCurrentName(value) {
|
||||||
this.currentName = value;
|
this.currentName = value;
|
||||||
this.$emit('input', value);
|
this.$emit('input', value);
|
||||||
|
@ -100,42 +73,37 @@
|
||||||
render(h) {
|
render(h) {
|
||||||
let {
|
let {
|
||||||
type,
|
type,
|
||||||
handleTabRemove,
|
|
||||||
handleTabClick,
|
handleTabClick,
|
||||||
|
handleTabRemove,
|
||||||
|
handleTabAdd,
|
||||||
currentName,
|
currentName,
|
||||||
panes
|
panes,
|
||||||
|
editable,
|
||||||
|
addable
|
||||||
} = this;
|
} = this;
|
||||||
|
|
||||||
const tabs = this._l(panes, (pane, index) => {
|
const newButton = editable || addable
|
||||||
let tabName = pane.name || pane.index || index;
|
? (
|
||||||
if (currentName === undefined && index === 0) {
|
<span
|
||||||
this.setCurrentName(tabName);
|
class="el-tabs__new-tab"
|
||||||
}
|
on-click={ handleTabAdd }
|
||||||
|
>
|
||||||
|
<i class="el-icon-plus"></i>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
pane.index = index;
|
const navData = {
|
||||||
|
props: {
|
||||||
const btnClose = pane.isClosable
|
currentName,
|
||||||
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(pane, ev); }}></span>
|
onTabClick: handleTabClick,
|
||||||
: null;
|
onTabRemove: handleTabRemove,
|
||||||
|
editable,
|
||||||
const tabLabelContent = pane.$slots.label || pane.label;
|
type,
|
||||||
return (
|
panes
|
||||||
<div
|
},
|
||||||
class={{
|
ref: 'nav'
|
||||||
'el-tabs__item': true,
|
};
|
||||||
'is-active': pane.active,
|
|
||||||
'is-disabled': pane.disabled,
|
|
||||||
'is-closable': pane.isClosable
|
|
||||||
}}
|
|
||||||
ref="tabs"
|
|
||||||
refInFor
|
|
||||||
on-click={(ev) => { handleTabClick(pane, tabName, ev); }}
|
|
||||||
>
|
|
||||||
{tabLabelContent}
|
|
||||||
{btnClose}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={{
|
<div class={{
|
||||||
|
@ -144,14 +112,19 @@
|
||||||
'el-tabs--border-card': type === 'border-card'
|
'el-tabs--border-card': type === 'border-card'
|
||||||
}}>
|
}}>
|
||||||
<div class="el-tabs__header">
|
<div class="el-tabs__header">
|
||||||
{!type ? <tab-bar tabs={panes}></tab-bar> : null}
|
{newButton}
|
||||||
{tabs}
|
<tab-nav { ...navData }></tab-nav>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-tabs__content">
|
<div class="el-tabs__content">
|
||||||
{this.$slots.default}
|
{this.$slots.default}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.currentName) {
|
||||||
|
this.setCurrentName('0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,71 +6,73 @@
|
||||||
@b autocomplete {
|
@b autocomplete {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
@b autocomplete-suggestion {
|
||||||
|
margin: 5px 0 0;
|
||||||
|
box-shadow: 0 0 6px 0 rgba(0,0,0,0.04), 0 2px 4px 0 rgba(0,0,0,0.12);
|
||||||
|
|
||||||
@e suggestions {
|
@e wrap {
|
||||||
position: absolute;
|
max-height: 280px;
|
||||||
left: 0;
|
overflow: auto;
|
||||||
top: 110%;
|
|
||||||
margin: 5px 0 0;
|
|
||||||
background-color: var(--color-white);
|
background-color: var(--color-white);
|
||||||
border: 1px solid var(--color-base-gray);
|
border: 1px solid var(--color-base-gray);
|
||||||
width: 100%;
|
|
||||||
padding: 6px 0;
|
padding: 6px 0;
|
||||||
z-index: 10;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
max-height: 280px;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: auto;
|
}
|
||||||
box-shadow: 0 0 6px 0 rgba(0,0,0,0.04), 0 2px 4px 0 rgba(0,0,0,0.12);
|
|
||||||
|
|
||||||
& li {
|
@e list {
|
||||||
list-style: none;
|
margin: 0;
|
||||||
line-height: 36px;
|
padding: 0;
|
||||||
padding: 0 10px;
|
}
|
||||||
margin: 0;
|
|
||||||
cursor: pointer;
|
& li {
|
||||||
color: var(--color-extra-light-black);
|
list-style: none;
|
||||||
font-size: 14px;
|
line-height: 36px;
|
||||||
white-space: nowrap;
|
padding: 0 10px;
|
||||||
overflow: hidden;
|
margin: 0;
|
||||||
text-overflow: ellipsis;
|
cursor: pointer;
|
||||||
|
color: var(--color-extra-light-black);
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--select-option-hover-background);
|
||||||
|
}
|
||||||
|
&.highlighted {
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background-color: darken(var(--color-primary), 0.2);
|
||||||
|
}
|
||||||
|
&.divider {
|
||||||
|
margin-top: 6px;
|
||||||
|
border-top: 1px solid var(--color-base-gray);
|
||||||
|
}
|
||||||
|
&.divider:last-child {
|
||||||
|
margin-bottom: -6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@when loading {
|
||||||
|
li {
|
||||||
|
text-align: center;
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #999;
|
||||||
|
@utils-vertical-center;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--select-option-hover-background);
|
background-color: var(--color-white);
|
||||||
}
|
|
||||||
&.highlighted {
|
|
||||||
background-color: var(--color-primary);
|
|
||||||
color: var(--color-white);
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: darken(var(--color-primary), 0.2);
|
|
||||||
}
|
|
||||||
&.divider {
|
|
||||||
margin-top: 6px;
|
|
||||||
border-top: 1px solid var(--color-base-gray);
|
|
||||||
}
|
|
||||||
&.divider:last-child {
|
|
||||||
margin-bottom: -6px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@when loading {
|
& .el-icon-loading {
|
||||||
li {
|
vertical-align: middle;
|
||||||
text-align: center;
|
|
||||||
height: 100px;
|
|
||||||
line-height: 100px;
|
|
||||||
font-size: 20px;
|
|
||||||
color: #999;
|
|
||||||
@utils-vertical-center;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--color-white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .el-icon-loading {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,163 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
@import "./input.css";
|
@import "./input.css";
|
||||||
@import "./common/var.css";
|
@import "./common/var.css";
|
||||||
/*@import "./core/dropdown.css";*/
|
|
||||||
|
|
||||||
@component-namespace element {
|
@component-namespace el {
|
||||||
|
|
||||||
@b cascader {
|
@b cascader {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
@e dropdown {
|
.el-input,
|
||||||
background-color: var(--cascader-menu-fill);
|
.el-input__inner {
|
||||||
border: var(--cascader-menu-border);
|
cursor: pointer;
|
||||||
border-radius: var(--cascader-menu-radius);
|
background-color: transparent;
|
||||||
box-shadow: var(--cascader-menu-submenu-shadow);
|
z-index: 1;
|
||||||
margin-top: 5px;
|
}
|
||||||
max-height: var(--cascader-height);
|
|
||||||
|
.el-input__icon {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-caret-bottom {
|
||||||
|
transition: transform .3s;
|
||||||
|
|
||||||
|
@when reverse {
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@e label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 34px;
|
||||||
|
padding: 0 15px 0 10px;
|
||||||
|
color: var(--input-color);
|
||||||
|
width: 100%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
z-index: 10;
|
text-overflow: ellipsis;
|
||||||
}
|
|
||||||
|
|
||||||
@e wrap {
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@e menu {
|
@m large {
|
||||||
border: 0;
|
font-size: var(--input-large-font-size);
|
||||||
box-shadow: none;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
&::before {
|
.el-cascader__label {
|
||||||
border-left: var(--cascader-menu-border);
|
line-height: calc(var(--input-large-height) - 2);
|
||||||
content: " ";
|
}
|
||||||
height: var(--cascader-height);
|
}
|
||||||
left: 0;
|
@m small {
|
||||||
position: absolute;
|
font-size: var(--input-small-font-size);
|
||||||
|
|
||||||
|
.el-cascader__label {
|
||||||
|
line-height: calc(var(--input-small-height) - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@b cascader-menus {
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #fff;
|
||||||
|
position: absolute;
|
||||||
|
margin: 5px 0;
|
||||||
|
z-index: 1001;
|
||||||
|
border: var(--select-dropdown-border);
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: var(--select-dropdown-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@b cascader-menu {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
height: 180px;
|
||||||
|
overflow: auto;
|
||||||
|
border-right: var(--select-dropdown-border);
|
||||||
|
background-color: var(--select-dropdown-background);
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-width: 110px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@e item {
|
||||||
|
font-size: var(--select-font-size);
|
||||||
|
padding: 8px 30px 8px 10px;
|
||||||
|
position: relative;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
color: var(--select-option-color);
|
||||||
|
height: var(--select-option-height);
|
||||||
|
line-height: 1.5;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@e keyword {
|
||||||
|
color: var(--color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
@m extensible {
|
||||||
|
&:after {
|
||||||
|
font-family: 'element-icons';
|
||||||
|
content: "\e602";
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.8);
|
||||||
|
color: rgb(191, 203, 217);
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@when disabled {
|
||||||
|
color: var(--select-option-disabled-color);
|
||||||
|
background-color: var(--select-option-disabled-background);
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@when active {
|
||||||
|
color: var(--color-white);
|
||||||
|
background-color: var(--select-option-selected);
|
||||||
|
|
||||||
|
&.hover {
|
||||||
|
background-color: var(--select-option-selected-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--select-option-hover-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
color: var(--color-white);
|
||||||
|
background-color: var(--select-option-selected);
|
||||||
|
|
||||||
|
&.hover {
|
||||||
|
background-color: var(--select-option-selected-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@m flexible {
|
||||||
|
height: auto;
|
||||||
|
max-height: 180px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.el-cascader-menu__item {
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@when active {
|
@when active {
|
||||||
.el-collapse-item__header__arrow {
|
> .el-collapse-item__header {
|
||||||
transform: rotate(90deg);
|
.el-collapse-item__header__arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@
|
||||||
|
|
||||||
--select-option-color: var(--link-color);
|
--select-option-color: var(--link-color);
|
||||||
--select-option-disabled-color: var(--color-extra-light-silver);
|
--select-option-disabled-color: var(--color-extra-light-silver);
|
||||||
|
--select-option-disabled-background: var(--color-white);
|
||||||
--select-option-height: 36px;
|
--select-option-height: 36px;
|
||||||
--select-option-hover-background: var(--color-light-gray);
|
--select-option-hover-background: var(--color-light-gray);
|
||||||
--select-option-selected: var(--color-primary);
|
--select-option-selected: var(--color-primary);
|
||||||
|
@ -458,8 +459,8 @@
|
||||||
--tag-gray-border: var(--color-light-gray);
|
--tag-gray-border: var(--color-light-gray);
|
||||||
--tag-gray-color: var(--link-color);
|
--tag-gray-color: var(--link-color);
|
||||||
|
|
||||||
--tag-primary-fill: rgba(32,159,255,0.10);
|
--tag-primary-fill: rgba(var(--color-primary),0.10);
|
||||||
--tag-primary-border: rgba(32,159,255,0.20);
|
--tag-primary-border: rgba(var(--color-primary),0.20);
|
||||||
--tag-primary-color: var(--color-primary);
|
--tag-primary-color: var(--color-primary);
|
||||||
|
|
||||||
--tag-success-fill: rgba(18,206,102,0.10);
|
--tag-success-fill: rgba(18,206,102,0.10);
|
||||||
|
|
|
@ -44,3 +44,4 @@
|
||||||
@import "./carousel.css";
|
@import "./carousel.css";
|
||||||
@import "./carousel-item.css";
|
@import "./carousel-item.css";
|
||||||
@import "./collapse.css";
|
@import "./collapse.css";
|
||||||
|
@import "./cascader.css";
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
width: 180px;
|
width: 180px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
& .el-input {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
& .el-input__inner {
|
& .el-input__inner {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
padding-right: calc(var(--input-height) * 2 + 10);
|
padding-right: calc(var(--input-height) * 2 + 10);
|
||||||
|
|
|
@ -127,7 +127,6 @@
|
||||||
}
|
}
|
||||||
@b radio-button {
|
@b radio-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
@e inner {
|
@e inner {
|
||||||
|
@ -138,6 +137,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--button-default-fill);
|
background: var(--button-default-fill);
|
||||||
border: var(--border-base);
|
border: var(--border-base);
|
||||||
|
border-left: 0;
|
||||||
color: var(--button-default-color);
|
color: var(--button-default-color);
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -176,6 +176,7 @@
|
||||||
color: var(--radio-button-checked-color);
|
color: var(--radio-button-checked-color);
|
||||||
background-color: var(--radio-button-checked-fill);
|
background-color: var(--radio-button-checked-fill);
|
||||||
border-color: var(--radio-button-checked-border-color);
|
border-color: var(--radio-button-checked-border-color);
|
||||||
|
box-shadow: -1px 0 0 0 var(--radio-button-checked-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,12 +191,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:last-child) {
|
|
||||||
margin-right: -1px;
|
|
||||||
}
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
|
border-left: var(--border-base);
|
||||||
border-radius: var(--border-radius-base) 0 0 var(--border-radius-base);
|
border-radius: var(--border-radius-base) 0 0 var(--border-radius-base);
|
||||||
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
|
|
@ -80,23 +80,11 @@
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
@utils-vertical-center;
|
||||||
|
|
||||||
.el-tooltip {
|
.el-tooltip {
|
||||||
line-height: 1;
|
vertical-align: middle;
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip::after {
|
|
||||||
content: '';
|
|
||||||
width: 0;
|
|
||||||
height: 100%;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip__rel {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
|
|
@ -38,16 +38,8 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tooltip {
|
.el-tooltip.cell {
|
||||||
display: block;
|
white-space: nowrap;
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip__rel {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.cell {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@e empty-block {
|
@e empty-block {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 0 15px;
|
margin: 0 0 15px;
|
||||||
@utils-clearfix;
|
|
||||||
}
|
}
|
||||||
@e active-bar {
|
@e active-bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -20,16 +19,68 @@
|
||||||
transition: transform .3s cubic-bezier(.645,.045,.355,1);
|
transition: transform .3s cubic-bezier(.645,.045,.355,1);
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
@e new-tab {
|
||||||
|
float: right;
|
||||||
|
border: 1px solid #d3dce6;
|
||||||
|
height: 18px;
|
||||||
|
width: @height;
|
||||||
|
line-height: @height;
|
||||||
|
margin: 12px 0 9px 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #d3dce6;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all .15s;
|
||||||
|
|
||||||
|
.el-icon-plus {
|
||||||
|
transform: scale(0.8, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@e nav-wrap {
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
@when scrollable {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@e nav-scroll {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
@e nav-next, nav-prev {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 44px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-base-silver);
|
||||||
|
}
|
||||||
|
@e nav-next {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
@e nav-prev {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
@e nav {
|
||||||
|
white-space: nowrap;
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
transition: transform .3s;
|
||||||
|
}
|
||||||
@e item {
|
@e item {
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
line-height: @height;
|
line-height: @height;
|
||||||
float: left;
|
display: inline-block;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-base-silver);
|
color: var(--color-base-silver);
|
||||||
margin-bottom: -1px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
& .el-icon-close {
|
& .el-icon-close {
|
||||||
|
@ -67,10 +118,10 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@m card {
|
@m card {
|
||||||
&>.el-tabs__header>.el-tabs__active-bar {
|
.el-tabs__nav .el-tabs__active-bar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
&>.el-tabs__header>.el-tabs__item .el-icon-close {
|
.el-tabs__nav .el-tabs__item .el-icon-close {
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
@ -82,7 +133,7 @@
|
||||||
right: -2px;
|
right: -2px;
|
||||||
transform-origin: 100% 50%;
|
transform-origin: 100% 50%;
|
||||||
}
|
}
|
||||||
&>.el-tabs__header>.el-tabs__item {
|
.el-tabs__nav .el-tabs__item {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
transition: all .3s cubic-bezier(.645,.045,.355,1);
|
transition: all .3s cubic-bezier(.645,.045,.355,1);
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
|
|
||||||
@component-namespace el {
|
@component-namespace el {
|
||||||
@b tooltip {
|
@b tooltip {
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
@e rel {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@e popper {
|
@e popper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
|
import debounce from 'throttle-debounce/debounce';
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ElTooltip',
|
||||||
|
|
||||||
|
mixins: [Popper],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
openDelay: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
disabled: Boolean,
|
||||||
|
manual: Boolean,
|
||||||
|
effect: {
|
||||||
|
type: String,
|
||||||
|
default: 'dark'
|
||||||
|
},
|
||||||
|
popperClass: String,
|
||||||
|
content: String,
|
||||||
|
visibleArrow: {
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
transition: {
|
||||||
|
type: String,
|
||||||
|
default: 'fade-in-linear'
|
||||||
|
},
|
||||||
|
popperOptions: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
boundariesPadding: 10,
|
||||||
|
gpuAcceleration: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeCreate() {
|
||||||
|
this.popperVM = new Vue({
|
||||||
|
data: { node: '' },
|
||||||
|
render(h) {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
}).$mount();
|
||||||
|
|
||||||
|
this.debounceClose = debounce(200, () => this.handleClosePopper());
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
this.popperVM.node = (
|
||||||
|
<transition
|
||||||
|
name={ this.transition }
|
||||||
|
onAfterLeave={ this.doDestroy }>
|
||||||
|
<div
|
||||||
|
onMouseleave={ () => { this.debounceClose(); this.togglePreventClose(); } }
|
||||||
|
onMouseenter= { this.togglePreventClose }
|
||||||
|
ref="popper"
|
||||||
|
v-show={!this.disabled && this.showPopper}
|
||||||
|
class={
|
||||||
|
['el-tooltip__popper', 'is-' + this.effect, this.popperClass]
|
||||||
|
}>
|
||||||
|
{ this.$slots.content || this.content }
|
||||||
|
</div>
|
||||||
|
</transition>);
|
||||||
|
|
||||||
|
if (!this.$slots.default) return this.$slots.default;
|
||||||
|
|
||||||
|
const vnode = this.$slots.default[0];
|
||||||
|
const data = vnode.data = vnode.data || {};
|
||||||
|
const on = vnode.data.on = vnode.data.on || {};
|
||||||
|
|
||||||
|
on.mouseenter = this.addEventHandle(on.mouseenter, this.handleShowPopper);
|
||||||
|
on.mouseleave = this.addEventHandle(on.mouseleave, this.debounceClose);
|
||||||
|
data.staticClass = this.concatClass(data.staticClass, 'el-tooltip');
|
||||||
|
|
||||||
|
return vnode;
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.referenceElm = this.$el;
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
addEventHandle(old, fn) {
|
||||||
|
return old ? Array.isArray(old) ? old.concat(fn) : [old, fn] : fn;
|
||||||
|
},
|
||||||
|
|
||||||
|
concatClass(a, b) {
|
||||||
|
if (a && a.indexOf(b) > -1) return a;
|
||||||
|
return a ? b ? (a + ' ' + b) : a : (b || '');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleShowPopper() {
|
||||||
|
if (this.manual) return;
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.showPopper = true;
|
||||||
|
}, this.openDelay);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClosePopper() {
|
||||||
|
if (this.preventClose || this.manual) return;
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.showPopper = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
togglePreventClose() {
|
||||||
|
this.preventClose = !this.preventClose;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,75 +0,0 @@
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
class="el-tooltip"
|
|
||||||
@mouseenter="handleShowPopper"
|
|
||||||
@mouseleave="handleClosePopper">
|
|
||||||
<div class="el-tooltip__rel" ref="reference">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<transition :name="transition" @after-leave="doDestroy">
|
|
||||||
<div
|
|
||||||
class="el-tooltip__popper"
|
|
||||||
:class="['is-' + effect, popperClass]"
|
|
||||||
ref="popper"
|
|
||||||
v-show="!disabled && showPopper">
|
|
||||||
<slot name="content"><div v-text="content"></div></slot>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Popper from 'element-ui/src/utils/vue-popper';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ElTooltip',
|
|
||||||
|
|
||||||
mixins: [Popper],
|
|
||||||
|
|
||||||
props: {
|
|
||||||
openDelay: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
disabled: Boolean,
|
|
||||||
manual: Boolean,
|
|
||||||
effect: {
|
|
||||||
type: String,
|
|
||||||
default: 'dark'
|
|
||||||
},
|
|
||||||
popperClass: String,
|
|
||||||
content: String,
|
|
||||||
visibleArrow: {
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
transition: {
|
|
||||||
type: String,
|
|
||||||
default: 'fade-in-linear'
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
default() {
|
|
||||||
return {
|
|
||||||
boundariesPadding: 10,
|
|
||||||
gpuAcceleration: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
handleShowPopper() {
|
|
||||||
if (this.manual) return;
|
|
||||||
this.timeout = setTimeout(() => {
|
|
||||||
this.showPopper = true;
|
|
||||||
}, this.openDelay);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleClosePopper() {
|
|
||||||
if (this.manual) return;
|
|
||||||
clearTimeout(this.timeout);
|
|
||||||
this.showPopper = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -60,6 +60,7 @@ import Scrollbar from '../packages/scrollbar';
|
||||||
import CarouselItem from '../packages/carousel-item';
|
import CarouselItem from '../packages/carousel-item';
|
||||||
import Collapse from '../packages/collapse';
|
import Collapse from '../packages/collapse';
|
||||||
import CollapseItem from '../packages/collapse-item';
|
import CollapseItem from '../packages/collapse-item';
|
||||||
|
import Cascader from '../packages/cascader';
|
||||||
import locale from 'element-ui/src/locale';
|
import locale from 'element-ui/src/locale';
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
|
@ -118,7 +119,8 @@ const components = [
|
||||||
Scrollbar,
|
Scrollbar,
|
||||||
CarouselItem,
|
CarouselItem,
|
||||||
Collapse,
|
Collapse,
|
||||||
CollapseItem
|
CollapseItem,
|
||||||
|
Cascader
|
||||||
];
|
];
|
||||||
|
|
||||||
const install = function(Vue, opts = {}) {
|
const install = function(Vue, opts = {}) {
|
||||||
|
@ -211,5 +213,6 @@ module.exports = {
|
||||||
Scrollbar,
|
Scrollbar,
|
||||||
CarouselItem,
|
CarouselItem,
|
||||||
Collapse,
|
Collapse,
|
||||||
CollapseItem
|
CollapseItem,
|
||||||
|
Cascader
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Няма данни',
|
noData: 'Няма данни',
|
||||||
placeholder: 'Избери'
|
placeholder: 'Избери'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Няма намерени',
|
||||||
|
placeholder: 'Избери'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Иди на',
|
goto: 'Иди на',
|
||||||
pagesize: '/страница',
|
pagesize: '/страница',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Ingen data',
|
noData: 'Ingen data',
|
||||||
placeholder: 'Vælg'
|
placeholder: 'Vælg'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Ingen matchende data',
|
||||||
|
placeholder: 'Vælg'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Gå til',
|
goto: 'Gå til',
|
||||||
pagesize: '/side',
|
pagesize: '/side',
|
||||||
|
|
|
@ -58,6 +58,10 @@ export default {
|
||||||
noData: 'Keine Datei',
|
noData: 'Keine Datei',
|
||||||
placeholder: 'Datei wählen'
|
placeholder: 'Datei wählen'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Nichts gefunden.',
|
||||||
|
placeholder: 'Datei wählen'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Gehe zu',
|
goto: 'Gehe zu',
|
||||||
pagesize: 'pro Seite',
|
pagesize: 'pro Seite',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'No data',
|
noData: 'No data',
|
||||||
placeholder: 'Select'
|
placeholder: 'Select'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'No matching data',
|
||||||
|
placeholder: 'Select'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Go to',
|
goto: 'Go to',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Sin datos',
|
noData: 'Sin datos',
|
||||||
placeholder: 'Seleccionar'
|
placeholder: 'Seleccionar'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'No hay datos que coincidan',
|
||||||
|
placeholder: 'Seleccionar'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Ir a',
|
goto: 'Ir a',
|
||||||
pagesize: '/pagina',
|
pagesize: '/pagina',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'اطلاعاتی وجود ندارد',
|
noData: 'اطلاعاتی وجود ندارد',
|
||||||
placeholder: 'انتخاب کنید'
|
placeholder: 'انتخاب کنید'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'هیچ دادهای پیدا نشد',
|
||||||
|
placeholder: 'انتخاب کنید'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'برو به',
|
goto: 'برو به',
|
||||||
pagesize: '/صفحه',
|
pagesize: '/صفحه',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Aucun résultat',
|
noData: 'Aucun résultat',
|
||||||
placeholder: 'Choisir'
|
placeholder: 'Choisir'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Aucune correspondance',
|
||||||
|
placeholder: 'Choisir'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Aller à',
|
goto: 'Aller à',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Tidak ada data',
|
noData: 'Tidak ada data',
|
||||||
placeholder: 'Pilih'
|
placeholder: 'Pilih'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Tidak ada data yang cocok',
|
||||||
|
placeholder: 'Pilih'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Pergi ke',
|
goto: 'Pergi ke',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Nessun risultato',
|
noData: 'Nessun risultato',
|
||||||
placeholder: 'Seleziona'
|
placeholder: 'Seleziona'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Nessuna corrispondenza',
|
||||||
|
placeholder: 'Seleziona'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Vai a',
|
goto: 'Vai a',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'データなし',
|
noData: 'データなし',
|
||||||
placeholder: '選択してください'
|
placeholder: '選択してください'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'データなし',
|
||||||
|
placeholder: '選択してください'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: '',
|
goto: '',
|
||||||
pagesize: '件/ページ',
|
pagesize: '件/ページ',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: '데이터 없음',
|
noData: '데이터 없음',
|
||||||
placeholder: '선택'
|
placeholder: '선택'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: '맞는 데이터가 없습니다',
|
||||||
|
placeholder: '선택'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: '이동',
|
goto: '이동',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Ingen data',
|
noData: 'Ingen data',
|
||||||
placeholder: 'Velg'
|
placeholder: 'Velg'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Ingen samsvarende data',
|
||||||
|
placeholder: 'Velg'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Gå til',
|
goto: 'Gå til',
|
||||||
pagesize: '/side',
|
pagesize: '/side',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Geen data',
|
noData: 'Geen data',
|
||||||
placeholder: 'Selecteer'
|
placeholder: 'Selecteer'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Geen overeenkomende resultaten',
|
||||||
|
placeholder: 'Selecteer'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Ga naar',
|
goto: 'Ga naar',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Brak danych',
|
noData: 'Brak danych',
|
||||||
placeholder: 'Wybierz'
|
placeholder: 'Wybierz'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Brak dopasowań',
|
||||||
|
placeholder: 'Wybierz'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Idź do',
|
goto: 'Idź do',
|
||||||
pagesize: '/strona',
|
pagesize: '/strona',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Sem dados',
|
noData: 'Sem dados',
|
||||||
placeholder: 'Selecione'
|
placeholder: 'Selecione'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Sem resultados',
|
||||||
|
placeholder: 'Selecione'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Ir para',
|
goto: 'Ir para',
|
||||||
pagesize: '/pagina',
|
pagesize: '/pagina',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Sem dados',
|
noData: 'Sem dados',
|
||||||
placeholder: 'Selecione'
|
placeholder: 'Selecione'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Sem correspondência',
|
||||||
|
placeholder: 'Selecione'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Ir para',
|
goto: 'Ir para',
|
||||||
pagesize: '/pagina',
|
pagesize: '/pagina',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Нет данных',
|
noData: 'Нет данных',
|
||||||
placeholder: 'Выбрать'
|
placeholder: 'Выбрать'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Совпадений не найдено',
|
||||||
|
placeholder: 'Выбрать'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Перейти',
|
goto: 'Перейти',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'ไม่พบข้อมูล',
|
noData: 'ไม่พบข้อมูล',
|
||||||
placeholder: 'เลือก'
|
placeholder: 'เลือก'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'ไม่พบข้อมูลที่ตรงกัน',
|
||||||
|
placeholder: 'เลือก'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'ไปที่',
|
goto: 'ไปที่',
|
||||||
pagesize: '/หน้า',
|
pagesize: '/หน้า',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Veri yok',
|
noData: 'Veri yok',
|
||||||
placeholder: 'Seç'
|
placeholder: 'Seç'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Eşleşen veri bulunamadı',
|
||||||
|
placeholder: 'Seç'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Git',
|
goto: 'Git',
|
||||||
pagesize: '/page',
|
pagesize: '/page',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: 'Không tìm thấy dữ liệu',
|
noData: 'Không tìm thấy dữ liệu',
|
||||||
placeholder: 'Chọn'
|
placeholder: 'Chọn'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: 'Dữ liệu không phù hợp',
|
||||||
|
placeholder: 'Chọn'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: 'Nhảy tới',
|
goto: 'Nhảy tới',
|
||||||
pagesize: '/trang',
|
pagesize: '/trang',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: '无数据',
|
noData: '无数据',
|
||||||
placeholder: '请选择'
|
placeholder: '请选择'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: '无匹配数据',
|
||||||
|
placeholder: '请选择'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: '前往',
|
goto: '前往',
|
||||||
pagesize: '条/页',
|
pagesize: '条/页',
|
||||||
|
|
|
@ -56,6 +56,10 @@ export default {
|
||||||
noData: '無資料',
|
noData: '無資料',
|
||||||
placeholder: '請選擇'
|
placeholder: '請選擇'
|
||||||
},
|
},
|
||||||
|
cascader: {
|
||||||
|
noMatch: '無匹配資料',
|
||||||
|
placeholder: '請選擇'
|
||||||
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
goto: '前往',
|
goto: '前往',
|
||||||
pagesize: '項/頁',
|
pagesize: '項/頁',
|
||||||
|
|
|
@ -70,6 +70,10 @@ export default {
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
modalClass: {},
|
modalClass: {},
|
||||||
|
modalAppendToBody: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
lockScroll: {
|
lockScroll: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
@ -185,7 +189,7 @@ export default {
|
||||||
PopupManager.closeModal(this._popupId);
|
PopupManager.closeModal(this._popupId);
|
||||||
this._closing = false;
|
this._closing = false;
|
||||||
}
|
}
|
||||||
PopupManager.openModal(this._popupId, PopupManager.nextZIndex(), dom, props.modalClass, props.modalFade);
|
PopupManager.openModal(this._popupId, PopupManager.nextZIndex(), this.modalAppendToBody ? undefined : dom, props.modalClass, props.modalFade);
|
||||||
if (props.lockScroll) {
|
if (props.lockScroll) {
|
||||||
if (!this.bodyOverflow) {
|
if (!this.bodyOverflow) {
|
||||||
this.bodyPaddingRight = document.body.style.paddingRight;
|
this.bodyPaddingRight = document.body.style.paddingRight;
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
options: {
|
popperOptions: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
|
@ -76,7 +76,7 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = this.options;
|
const options = this.popperOptions;
|
||||||
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper;
|
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper;
|
||||||
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference;
|
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference;
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ export default {
|
||||||
this.$slots.reference[0]) {
|
this.$slots.reference[0]) {
|
||||||
reference = this.referenceElm = this.$slots.reference[0].elm;
|
reference = this.referenceElm = this.$slots.reference[0].elm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!popper || !reference) return;
|
if (!popper || !reference) return;
|
||||||
if (this.visibleArrow) this.appendArrow(popper);
|
if (this.visibleArrow) this.appendArrow(popper);
|
||||||
if (this.appendToBody) document.body.appendChild(this.popperElm);
|
if (this.appendToBody) document.body.appendChild(this.popperElm);
|
||||||
|
|
|
@ -57,7 +57,7 @@ describe('Autocomplete', () => {
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const suggestions = vm.$refs.autocomplete.$refs.suggestions.$el;
|
const suggestions = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
expect(suggestions.style.display).to.not.equal('none');
|
expect(suggestions.style.display).to.not.equal('none');
|
||||||
expect(suggestions.children.length).to.be.equal(4);
|
expect(suggestions.querySelectorAll('.el-autocomplete-suggestion__list li').length).to.be.equal(4);
|
||||||
|
|
||||||
document.body.click();
|
document.body.click();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
|
@ -74,14 +74,12 @@ describe('Autocomplete', () => {
|
||||||
ref="autocomplete"
|
ref="autocomplete"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder="请输入内容autocomplete2"
|
placeholder="请输入内容autocomplete2"
|
||||||
@select="handleSelect"
|
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
restaurants: [],
|
restaurants: [],
|
||||||
state: '',
|
state: ''
|
||||||
onceSelected: false
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -102,27 +100,29 @@ describe('Autocomplete', () => {
|
||||||
{ 'value': '新旺角茶餐厅', 'address': '上海市普陀区真北路988号创邑金沙谷6号楼113' },
|
{ 'value': '新旺角茶餐厅', 'address': '上海市普陀区真北路988号创邑金沙谷6号楼113' },
|
||||||
{ 'value': '泷千家(天山西路店)', 'address': '天山西路438号' }
|
{ 'value': '泷千家(天山西路店)', 'address': '天山西路438号' }
|
||||||
];
|
];
|
||||||
},
|
|
||||||
handleSelect() {
|
|
||||||
this.onceSelected = true;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.restaurants = this.loadAll();
|
this.restaurants = this.loadAll();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
let elm = vm.$el;
|
const autocomplete = vm.$refs.autocomplete;
|
||||||
let inputElm = elm.querySelector('input');
|
const elm = vm.$el;
|
||||||
|
const inputElm = elm.querySelector('input');
|
||||||
|
const spy = sinon.spy();
|
||||||
|
|
||||||
|
autocomplete.$on('select', spy);
|
||||||
inputElm.focus();
|
inputElm.focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
const suggestions = autocomplete.$refs.suggestions.$el;
|
||||||
suggestionsList.children[1].click();
|
const suggestionList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
|
||||||
|
suggestionList[1].click();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
||||||
expect(vm.state).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
expect(vm.state).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
|
||||||
expect(vm.onceSelected).to.be.true;
|
expect(spy.withArgs().calledOnce).to.be.true;
|
||||||
expect(elm.querySelector('.el-autocomplete__suggestions')).to.not.exist;
|
expect(suggestions.style.display).to.be.equal('none');
|
||||||
done();
|
done();
|
||||||
}, 500);
|
}, 500);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -135,14 +135,12 @@ describe('Autocomplete', () => {
|
||||||
v-model="state"
|
v-model="state"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder="请输入内容autocomplete3"
|
placeholder="请输入内容autocomplete3"
|
||||||
@select="handleSelect"
|
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
restaurants: [],
|
restaurants: [],
|
||||||
state: '',
|
state: ''
|
||||||
onceSelected: false
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -181,28 +179,25 @@ describe('Autocomplete', () => {
|
||||||
{ 'value': '纵食', 'address': '元丰天山花园(东门) 双流路267号' },
|
{ 'value': '纵食', 'address': '元丰天山花园(东门) 双流路267号' },
|
||||||
{ 'value': '钱记', 'address': '上海市长宁区天山西路' }
|
{ 'value': '钱记', 'address': '上海市长宁区天山西路' }
|
||||||
];
|
];
|
||||||
},
|
|
||||||
handleSelect() {
|
|
||||||
this.onceSelected = true;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.restaurants = this.loadAll();
|
this.restaurants = this.loadAll();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
let elm = vm.$el;
|
const autocomplete = vm.$refs.autocomplete;
|
||||||
let inputElm = elm.querySelector('input');
|
const inputElm = autocomplete.$el.querySelector('input');
|
||||||
|
|
||||||
inputElm.focus();
|
inputElm.focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
vm.$refs.autocomplete.highlight(8);
|
autocomplete.highlight(8);
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
const suggestions = autocomplete.$refs.suggestions.$el.querySelector('.el-autocomplete-suggestion__wrap');
|
||||||
let highlightedItem = suggestionsList.children[8];
|
let suggestionsList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
|
||||||
expect(highlightedItem.className).to.be.equal('highlighted');
|
let highlightedItem = suggestionsList[8];
|
||||||
expect(suggestionsList.scrollTop === highlightedItem.scrollHeight).to.be.true;
|
expect(highlightedItem.classList.contains('highlighted')).to.be.true;
|
||||||
|
expect(suggestions.scrollTop === highlightedItem.scrollHeight).to.be.true;
|
||||||
vm.$refs.autocomplete.highlight(8);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -215,14 +210,12 @@ describe('Autocomplete', () => {
|
||||||
v-model="state"
|
v-model="state"
|
||||||
:fetch-suggestions="querySearch"
|
:fetch-suggestions="querySearch"
|
||||||
placeholder="请输入内容autocomplete3"
|
placeholder="请输入内容autocomplete3"
|
||||||
@select="handleSelect"
|
|
||||||
></el-autocomplete>
|
></el-autocomplete>
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
restaurants: [],
|
restaurants: [],
|
||||||
state: '',
|
state: ''
|
||||||
onceSelected: false
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -251,29 +244,27 @@ describe('Autocomplete', () => {
|
||||||
{ 'value': '阿姨奶茶/豪大大', 'address': '嘉定区曹安路1611号' },
|
{ 'value': '阿姨奶茶/豪大大', 'address': '嘉定区曹安路1611号' },
|
||||||
{ 'value': '新麦甜四季甜品炸鸡', 'address': '嘉定区曹安公路2383弄55号' }
|
{ 'value': '新麦甜四季甜品炸鸡', 'address': '嘉定区曹安公路2383弄55号' }
|
||||||
];
|
];
|
||||||
},
|
|
||||||
handleSelect() {
|
|
||||||
this.onceSelected = true;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.restaurants = this.loadAll();
|
this.restaurants = this.loadAll();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
let elm = vm.$el;
|
const autocomplete = vm.$refs.autocomplete;
|
||||||
let inputElm = elm.querySelector('input');
|
let inputElm = vm.$el.querySelector('input');
|
||||||
inputElm.focus();
|
inputElm.focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
vm.$refs.autocomplete.highlight(15);
|
autocomplete.highlight(15);
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
const suggestions = autocomplete.$refs.suggestions.$el;
|
||||||
let highlightedItem = suggestionsList.children[11];
|
const suggestionsList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
|
||||||
|
let highlightedItem = suggestionsList[11];
|
||||||
expect(highlightedItem.className).to.be.equal('highlighted');
|
expect(highlightedItem.className).to.be.equal('highlighted');
|
||||||
|
|
||||||
vm.$refs.autocomplete.highlight(-5);
|
autocomplete.highlight(-5);
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let highlightedItem = suggestionsList.children[0];
|
let highlightedItem = suggestionsList[0];
|
||||||
expect(highlightedItem.className).to.be.equal('highlighted');
|
expect(highlightedItem.className).to.be.equal('highlighted');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
|
@ -321,13 +312,12 @@ describe('Autocomplete', () => {
|
||||||
this.restaurants = this.loadAll();
|
this.restaurants = this.loadAll();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
let elm = vm.$el;
|
let inputElm = vm.$el.querySelector('input');
|
||||||
let inputElm = elm.querySelector('input');
|
|
||||||
inputElm.focus();
|
inputElm.focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
let suggestionsList = vm.$refs.autocomplete.$refs.suggestions.$el;
|
let suggestions = vm.$refs.autocomplete.$refs.suggestions.$el;
|
||||||
expect(suggestionsList.style.display).to.be.equal('none');
|
expect(suggestions.style.display).to.be.equal('none');
|
||||||
done();
|
done();
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,524 @@
|
||||||
|
import { createVue, destroyVM, triggerEvent } from '../util';
|
||||||
|
|
||||||
|
describe('Cascader', () => {
|
||||||
|
let vm;
|
||||||
|
afterEach(() => {
|
||||||
|
destroyVM(vm);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$el.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
item1.click();
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(2);
|
||||||
|
expect(item1.classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
const item2 = menuElm.children[1].querySelector('.el-cascader-menu__item');
|
||||||
|
item2.click();
|
||||||
|
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(3);
|
||||||
|
expect(item2.classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
const item3 = menuElm.children[2].querySelector('.el-cascader-menu__item');
|
||||||
|
item3.click();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
|
||||||
|
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
|
||||||
|
expect(vm.selectedOptions[1]).to.be.equal('hangzhou');
|
||||||
|
expect(vm.selectedOptions[2]).to.be.equal('xihu');
|
||||||
|
|
||||||
|
triggerEvent(vm.$refs.cascader.$el, 'mouseenter');
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
vm.$refs.cascader.$el.querySelector('.el-cascader__clearIcon').click();
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(vm.selectedOptions.length).to.be.equal(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
it('not allow clearable', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
:clearable="false"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
triggerEvent(vm.$refs.cascader.$el, 'mouseenter');
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(vm.$refs.cascader.$el.querySelector('.el-cascader__clearIcon')).to.not.exist;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('disabled options', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
disabled: true,
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$el.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
item1.click();
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(1);
|
||||||
|
expect(item1.classList.contains('is-active')).to.be.false;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
it('default value', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: ['zhejiang', 'hangzhou', 'xihu']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$el.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.children[0].querySelector('.el-cascader-menu__item');
|
||||||
|
const item2 = menuElm.children[1].querySelector('.el-cascader-menu__item');
|
||||||
|
const item3 = menuElm.children[2].querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
expect(menuElm.children.length).to.be.equal(3);
|
||||||
|
expect(item1.classList.contains('is-active')).to.be.true;
|
||||||
|
expect(item2.classList.contains('is-active')).to.be.true;
|
||||||
|
expect(item3.classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
document.body.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
|
||||||
|
done();
|
||||||
|
}, 500);
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
it('expand by hover', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
expand-trigger="hover"
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$el.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
triggerEvent(item1, 'mouseenter');
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(2);
|
||||||
|
expect(item1.classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
const item2 = menuElm.children[1].querySelector('.el-cascader-menu__item');
|
||||||
|
triggerEvent(item2, 'mouseenter');
|
||||||
|
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(3);
|
||||||
|
expect(item2.classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
const item3 = menuElm.children[2].querySelector('.el-cascader-menu__item');
|
||||||
|
item3.click();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
|
||||||
|
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
|
||||||
|
expect(vm.selectedOptions[1]).to.be.equal('hangzhou');
|
||||||
|
expect(vm.selectedOptions[2]).to.be.equal('xihu');
|
||||||
|
done();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
it('change on select', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
change-on-select
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$el.click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
item1.click();
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(2);
|
||||||
|
expect(item1.classList.contains('is-active')).to.be.true;
|
||||||
|
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
|
||||||
|
|
||||||
|
const item2 = menuElm.children[1].querySelector('.el-cascader-menu__item');
|
||||||
|
item2.click();
|
||||||
|
|
||||||
|
menu.$nextTick(_ => {
|
||||||
|
expect(menuElm.children.length).to.be.equal(3);
|
||||||
|
expect(item2.classList.contains('is-active')).to.be.true;
|
||||||
|
expect(vm.selectedOptions[1]).to.be.equal('hangzhou');
|
||||||
|
|
||||||
|
const item3 = menuElm.children[2].querySelector('.el-cascader-menu__item');
|
||||||
|
item3.click();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
|
||||||
|
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
|
||||||
|
expect(vm.selectedOptions[1]).to.be.equal('hangzhou');
|
||||||
|
expect(vm.selectedOptions[2]).to.be.equal('xihu');
|
||||||
|
done();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
it('filterable', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-cascader
|
||||||
|
ref="cascader"
|
||||||
|
placeholder="请选择"
|
||||||
|
:options="options"
|
||||||
|
filterable
|
||||||
|
v-model="selectedOptions"
|
||||||
|
></el-cascader>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [{
|
||||||
|
value: 'zhejiang',
|
||||||
|
label: 'Zhejiang',
|
||||||
|
children: [{
|
||||||
|
value: 'hangzhou',
|
||||||
|
label: 'Hangzhou',
|
||||||
|
children: [{
|
||||||
|
value: 'xihu',
|
||||||
|
label: 'West Lake'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'ningbo',
|
||||||
|
label: 'NingBo',
|
||||||
|
children: [{
|
||||||
|
value: 'jiangbei',
|
||||||
|
label: 'Jiang Bei'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
value: 'jiangsu',
|
||||||
|
label: 'Jiangsu',
|
||||||
|
children: [{
|
||||||
|
value: 'nanjing',
|
||||||
|
label: 'Nanjing',
|
||||||
|
children: [{
|
||||||
|
value: 'zhonghuamen',
|
||||||
|
label: 'Zhong Hua Men'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
selectedOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
expect(vm.$el).to.be.exist;
|
||||||
|
vm.$refs.cascader.inputValue = 'z';
|
||||||
|
vm.$el.click();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
|
||||||
|
|
||||||
|
const menu = vm.$refs.cascader.menu;
|
||||||
|
const menuElm = menu.$el;
|
||||||
|
const item1 = menuElm.querySelector('.el-cascader-menu__item');
|
||||||
|
|
||||||
|
expect(menuElm.children.length).to.be.equal(1);
|
||||||
|
expect(menuElm.children[0].children.length).to.be.equal(1);
|
||||||
|
done();
|
||||||
|
|
||||||
|
item1.click();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(document.body.querySelector('.el-cascader-menus').style.display).to.be.equal('none');
|
||||||
|
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
|
||||||
|
expect(vm.selectedOptions[1]).to.be.equal('hangzhou');
|
||||||
|
expect(vm.selectedOptions[2]).to.be.equal('xihu');
|
||||||
|
done();
|
||||||
|
}, 500);
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
});
|
|
@ -24,7 +24,7 @@ describe('Tabs', () => {
|
||||||
vm.$refs.tabs.$on('tab-click', spy);
|
vm.$refs.tabs.$on('tab-click', spy);
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const tabList = vm.$refs.tabs.$refs.tabs;
|
const tabList = vm.$refs.tabs.$refs.nav.$refs.tabs;
|
||||||
expect(tabList[0].classList.contains('is-active')).to.be.true;
|
expect(tabList[0].classList.contains('is-active')).to.be.true;
|
||||||
expect(paneList[0].style.display).to.not.ok;
|
expect(paneList[0].style.display).to.not.ok;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ describe('Tabs', () => {
|
||||||
}, true);
|
}, true);
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
||||||
const tabList = vm.$refs.tabs.$refs.tabs;
|
const tabList = vm.$refs.tabs.$refs.nav.$refs.tabs;
|
||||||
|
|
||||||
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
||||||
expect(paneList[1].style.display).to.not.ok;
|
expect(paneList[1].style.display).to.not.ok;
|
||||||
|
@ -140,33 +140,172 @@ describe('Tabs', () => {
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
it('closable', done => {
|
it('editable', done => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-tabs type="card" :closable="true" ref="tabs">
|
<el-tabs ref="tabs" v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
|
||||||
<el-tab-pane label="用户管理">A</el-tab-pane>
|
<el-tab-pane
|
||||||
<el-tab-pane label="配置管理">B</el-tab-pane>
|
v-for="(item, index) in editableTabs"
|
||||||
<el-tab-pane label="角色管理">C</el-tab-pane>
|
:label="item.title"
|
||||||
<el-tab-pane label="定时任务补偿">D</el-tab-pane>
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
`
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 3',
|
||||||
|
name: '3',
|
||||||
|
content: 'Tab 3 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 3
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleTabsEdit(targetName, action) {
|
||||||
|
if (action === 'add') {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
}
|
||||||
|
if (action === 'remove') {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
let spy = sinon.spy();
|
|
||||||
vm.$refs.tabs.$on('tab-remove', spy);
|
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const tabList = vm.$refs.tabs.$refs.tabs;
|
const tabList = vm.$refs.tabs.$refs.nav.$refs.tabs;
|
||||||
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
||||||
|
|
||||||
tabList[1].querySelector('.el-icon-close').click();
|
tabList[1].querySelector('.el-icon-close').click();
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(tabList.length).to.be.equal(2);
|
||||||
|
expect(paneList.length).to.be.equal(2);
|
||||||
|
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
||||||
|
|
||||||
|
vm.$refs.tabs.$el.querySelector('.el-tabs__new-tab').click();
|
||||||
|
vm.$nextTick(_ => {
|
||||||
|
expect(tabList.length).to.be.equal(3);
|
||||||
|
expect(paneList.length).to.be.equal(3);
|
||||||
|
expect(tabList[2].classList.contains('is-active')).to.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
it('addable & closable', done => {
|
||||||
|
vm = createVue({
|
||||||
|
template: `
|
||||||
|
<el-tabs
|
||||||
|
ref="tabs"
|
||||||
|
v-model="editableTabsValue"
|
||||||
|
type="card"
|
||||||
|
addable
|
||||||
|
closable
|
||||||
|
@tab-add="addTab"
|
||||||
|
@tab-remove="removeTab"
|
||||||
|
>
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="(item, index) in editableTabs"
|
||||||
|
:label="item.title"
|
||||||
|
:name="item.name"
|
||||||
|
>
|
||||||
|
{{item.content}}
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editableTabsValue: '2',
|
||||||
|
editableTabs: [{
|
||||||
|
title: 'Tab 1',
|
||||||
|
name: '1',
|
||||||
|
content: 'Tab 1 content'
|
||||||
|
}, {
|
||||||
|
title: 'Tab 2',
|
||||||
|
name: '2',
|
||||||
|
content: 'Tab 2 content'
|
||||||
|
}],
|
||||||
|
tabIndex: 2
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addTab(targetName) {
|
||||||
|
let newTabName = ++this.tabIndex + '';
|
||||||
|
this.editableTabs.push({
|
||||||
|
title: 'New Tab',
|
||||||
|
name: newTabName,
|
||||||
|
content: 'New Tab content'
|
||||||
|
});
|
||||||
|
this.editableTabsValue = newTabName;
|
||||||
|
},
|
||||||
|
removeTab(targetName) {
|
||||||
|
let tabs = this.editableTabs;
|
||||||
|
let activeName = this.editableTabsValue;
|
||||||
|
if (activeName === targetName) {
|
||||||
|
tabs.forEach((tab, index) => {
|
||||||
|
if (tab.name === targetName) {
|
||||||
|
let nextTab = tabs[index + 1] || tabs[index - 1];
|
||||||
|
if (nextTab) {
|
||||||
|
activeName = nextTab.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.editableTabsValue = activeName;
|
||||||
|
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
const tabList = vm.$refs.tabs.$refs.nav.$refs.tabs;
|
||||||
|
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
||||||
|
|
||||||
|
vm.$refs.tabs.$el.querySelector('.el-tabs__new-tab').click();
|
||||||
|
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
expect(tabList.length).to.be.equal(3);
|
expect(tabList.length).to.be.equal(3);
|
||||||
expect(paneList.length).to.be.equal(3);
|
expect(paneList.length).to.be.equal(3);
|
||||||
expect(spy.calledOnce).to.true;
|
expect(tabList[2].classList.contains('is-active')).to.be.true;
|
||||||
expect(tabList[1].innerText.trim()).to.be.equal('角色管理');
|
|
||||||
expect(paneList[0].innerText.trim()).to.be.equal('A');
|
tabList[2].querySelector('.el-icon-close').click();
|
||||||
done();
|
vm.$nextTick(_ => {
|
||||||
|
expect(tabList.length).to.be.equal(2);
|
||||||
|
expect(paneList.length).to.be.equal(2);
|
||||||
|
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
@ -187,42 +326,6 @@ describe('Tabs', () => {
|
||||||
done();
|
done();
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
it('closable edge', done => {
|
|
||||||
vm = createVue({
|
|
||||||
template: `
|
|
||||||
<el-tabs type="card" :closable="true" ref="tabs">
|
|
||||||
<el-tab-pane label="用户管理">A</el-tab-pane>
|
|
||||||
<el-tab-pane label="配置管理">B</el-tab-pane>
|
|
||||||
<el-tab-pane label="角色管理">C</el-tab-pane>
|
|
||||||
<el-tab-pane label="定时任务补偿">D</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
`
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
vm.$nextTick(_ => {
|
|
||||||
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
|
||||||
const tabList = vm.$refs.tabs.$refs.tabs;
|
|
||||||
|
|
||||||
tabList[0].querySelector('.el-icon-close').click();
|
|
||||||
vm.$nextTick(_ => {
|
|
||||||
expect(tabList.length).to.be.equal(3);
|
|
||||||
expect(paneList.length).to.be.equal(3);
|
|
||||||
expect(tabList[0].innerText.trim()).to.be.equal('配置管理');
|
|
||||||
expect(paneList[0].innerText.trim()).to.be.equal('B');
|
|
||||||
|
|
||||||
tabList[2].click();
|
|
||||||
tabList[2].querySelector('.el-icon-close').click();
|
|
||||||
setTimeout(_ => {
|
|
||||||
expect(tabList.length).to.be.equal(2);
|
|
||||||
expect(paneList.length).to.be.equal(2);
|
|
||||||
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
|
||||||
expect(tabList[1].innerText.trim()).to.be.equal('角色管理');
|
|
||||||
expect(paneList[1].innerText.trim()).to.be.equal('C');
|
|
||||||
done();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('disabled', done => {
|
it('disabled', done => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
|
@ -236,7 +339,7 @@ describe('Tabs', () => {
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
const tabList = vm.$refs.tabs.$refs.tabs;
|
const tabList = vm.$refs.tabs.$refs.nav.$refs.tabs;
|
||||||
|
|
||||||
tabList[1].click();
|
tabList[1].click();
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
|
|
|
@ -6,22 +6,27 @@ describe('Tooltip', () => {
|
||||||
destroyVM(vm);
|
destroyVM(vm);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create', () => {
|
it('create', done => {
|
||||||
vm = createVue(`
|
vm = createVue(`
|
||||||
<el-tooltip content="提示文字">
|
<el-tooltip ref="tooltip" content="提示文字">
|
||||||
<button>click</button>
|
<button>click</button>
|
||||||
</el-tooltip>`);
|
</el-tooltip>`);
|
||||||
|
|
||||||
expect(vm.$el.querySelector('.el-tooltip__popper')).to.have.property('textContent', '提示文字');
|
vm.$nextTick(_ => {
|
||||||
|
expect(vm.$refs.tooltip.popperVM.$el).to.have.property('textContent', '提示文字');
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('custom popper class', () => {
|
it('custom popper class', done => {
|
||||||
vm = createVue(`
|
vm = createVue(`
|
||||||
<el-tooltip content="提示文字" popper-class="custom-popper">
|
<el-tooltip ref="tooltip" content="提示文字" popper-class="custom-popper">
|
||||||
<button>click</button>
|
<button>click</button>
|
||||||
</el-tooltip>`);
|
</el-tooltip>`);
|
||||||
|
vm.$nextTick(_ => {
|
||||||
expect(vm.$el.querySelector('.el-tooltip__popper').classList.contains('custom-popper')).to.true;
|
expect(vm.$refs.tooltip.popperVM.$el.classList.contains('custom-popper')).to.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('manual', () => {
|
describe('manual', () => {
|
||||||
|
@ -73,18 +78,24 @@ describe('Tooltip', () => {
|
||||||
triggerEvent(tooltip.$el, 'mouseenter');
|
triggerEvent(tooltip.$el, 'mouseenter');
|
||||||
it('popperElm is exist', () => expect(tooltip.popperElm).to.exist);
|
it('popperElm is exist', () => expect(tooltip.popperElm).to.exist);
|
||||||
it('showPopper is true', () => expect(tooltip.showPopper).to.true);
|
it('showPopper is true', () => expect(tooltip.showPopper).to.true);
|
||||||
it('close popper', () => {
|
it('close popper', done => {
|
||||||
triggerEvent(tooltip.$el, 'mouseleave');
|
triggerEvent(tooltip.$el, 'mouseleave');
|
||||||
expect(tooltip.showPopper).to.false;
|
setTimeout(() => {
|
||||||
|
expect(tooltip.showPopper).to.false;
|
||||||
|
done();
|
||||||
|
}, 300);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('light mode', () => {
|
it('light mode', done => {
|
||||||
vm = createVue(`
|
vm = createVue(`
|
||||||
<el-tooltip content="abc" effect="light">
|
<el-tooltip ref="tooltip" content="abc" effect="light">
|
||||||
<button>abc</button>
|
<button>abc</button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
`);
|
`);
|
||||||
expect(vm.$el.querySelector('.is-light')).to.exist;
|
vm.$nextTick(_ => {
|
||||||
|
expect(vm.$refs.tooltip.popperVM.$el.classList.contains('is-light')).to.exist;
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -437,6 +437,10 @@ babel-messages@^6.8.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-runtime "^6.0.0"
|
babel-runtime "^6.0.0"
|
||||||
|
|
||||||
|
babel-plugin-add-module-exports@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
|
||||||
|
|
||||||
babel-plugin-check-es2015-constants@^6.3.13:
|
babel-plugin-check-es2015-constants@^6.3.13:
|
||||||
version "6.8.0"
|
version "6.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7"
|
resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7"
|
||||||
|
@ -6905,20 +6909,19 @@ vue-hot-reload-api@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.0.6.tgz#817d4bfb30f55428aa1012d029499e07f3147d21"
|
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.0.6.tgz#817d4bfb30f55428aa1012d029499e07f3147d21"
|
||||||
|
|
||||||
vue-loader@>=9.4.2, vue-loader@^10.0.2:
|
vue-loader@>=9.4.2, vue-loader@^10.0.2:
|
||||||
version "10.0.2"
|
version "10.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-10.0.2.tgz#6fe7bcefb32c5439bd0338464aa22673ad62299c"
|
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-10.3.0.tgz#436421736e9ad0f1c481330327c376963db86a19"
|
||||||
dependencies:
|
dependencies:
|
||||||
consolidate "^0.14.0"
|
consolidate "^0.14.0"
|
||||||
hash-sum "^1.0.2"
|
hash-sum "^1.0.2"
|
||||||
js-beautify "^1.6.3"
|
js-beautify "^1.6.3"
|
||||||
loader-utils "^0.2.10"
|
loader-utils "^0.2.10"
|
||||||
lru-cache "^4.0.1"
|
lru-cache "^4.0.1"
|
||||||
object-assign "^4.0.0"
|
|
||||||
postcss "^5.0.10"
|
postcss "^5.0.10"
|
||||||
postcss-selector-parser "^2.0.0"
|
postcss-selector-parser "^2.0.0"
|
||||||
source-map "^0.5.6"
|
source-map "^0.5.6"
|
||||||
vue-hot-reload-api "^2.0.1"
|
vue-hot-reload-api "^2.0.1"
|
||||||
vue-style-loader "^1.0.0"
|
vue-style-loader "^2.0.0"
|
||||||
vue-template-es2015-compiler "^1.2.2"
|
vue-template-es2015-compiler "^1.2.2"
|
||||||
|
|
||||||
vue-markdown-loader@^0.5.1:
|
vue-markdown-loader@^0.5.1:
|
||||||
|
@ -6941,6 +6944,13 @@ vue-style-loader@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^0.2.7"
|
loader-utils "^0.2.7"
|
||||||
|
|
||||||
|
vue-style-loader@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-2.0.0.tgz#1a3bb55239ac541ee3af0301d66f16fc86786543"
|
||||||
|
dependencies:
|
||||||
|
hash-sum "^1.0.2"
|
||||||
|
loader-utils "^0.2.7"
|
||||||
|
|
||||||
vue-template-compiler@*, vue-template-compiler@^2.1.8:
|
vue-template-compiler@*, vue-template-compiler@^2.1.8:
|
||||||
version "2.1.8"
|
version "2.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.1.8.tgz#12dd1cc63793f59be580c694a61610cb9369d629"
|
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.1.8.tgz#12dd1cc63793f59be580c694a61610cb9369d629"
|
||||||
|
|
Loading…
Reference in New Issue