mirror of https://github.com/ElemeFE/element
Merge branch '1.1' into feat/scrollbar
commit
c7507725ea
|
@ -55,5 +55,8 @@
|
|||
"steps": "./packages/steps/index.js",
|
||||
"step": "./packages/step/index.js",
|
||||
"carousel": "./packages/carousel/index.js",
|
||||
"scrollbar": "./packages/scrollbar/index.js"
|
||||
"scrollbar": "./packages/scrollbar/index.js",
|
||||
"carousel-item": "./packages/carousel-item/index.js",
|
||||
"collapse": "./packages/collapse/index.js",
|
||||
"collapse-item": "./packages/collapse-item/index.js"
|
||||
}
|
||||
|
|
|
@ -1 +1,189 @@
|
|||
## carousel
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
const demos = document.querySelectorAll('.source');
|
||||
demos[0].style.padding = '0';
|
||||
demos[0].className += ' small';
|
||||
demos[3].className += ' medium';
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
## Carousel
|
||||
|
||||
Loop a series of images or texts in a limited space
|
||||
|
||||
### Basic usage
|
||||
|
||||
::: demo Combine `el-carousel` with `el-carousel-item`, and you'll get a carousel. Content of each slide is completely customizable, and you just need to place it inside `el-carousel-item` tag. By default the carousel switches when mouse hovers over an indicator. Set `trigger` to `click`, and the carousel switches only when an indicator is clicked.
|
||||
```html
|
||||
<template>
|
||||
<div class="block">
|
||||
<span class="demonstration">Switch when indicator is hovered (default)</span>
|
||||
<el-carousel height="150px">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Switch when indicator is clicked</span>
|
||||
<el-carousel trigger="click" height="150px">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
line-height: 150px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### Indicators
|
||||
|
||||
Indicators can be displayed outside the carousel
|
||||
|
||||
::: demo The `indicator-position` attribute determines where the indicators are located. By default they are inside the carousel, and setting `indicator-position` to `outside` moves them outside; setting `indicator-position` to `none` hides the indicators.
|
||||
```html
|
||||
<template>
|
||||
<el-carousel indicator-position="outside">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 18px;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### Arrows
|
||||
|
||||
You can define when arrows are displayed
|
||||
|
||||
::: demo The `arrow` attribute determines when arrows are displayed. By default they appear when mouse hovers over the carousel. Setting `arrow` to `always` or `never` shows/hides the arrows permanently.
|
||||
```html
|
||||
<template>
|
||||
<el-carousel :interval="5000" arrow="always">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 18px;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### Card mode
|
||||
|
||||
When a page is wide enough but has limited height, you can activate card mode for carousels
|
||||
|
||||
::: demo Setting `type` to `card` activates the card mode. Apart from the appearance, the biggest difference between card mode and common mode is that clicking the slides at both sides directly switches the carousel in card mode.
|
||||
```html
|
||||
<template>
|
||||
<el-carousel :interval="4000" type="card" height="200px">
|
||||
<el-carousel-item v-for="item in 6">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
line-height: 200px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### Carousel Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| height | height of the carousel | number | — | 300 |
|
||||
| initial-index | index of the initially active slide (starting from 0) | number | — | 0 |
|
||||
| trigger | how indicators are triggered | string | click | — |
|
||||
| autoplay | whether automatically loop the slides | boolean | — | true |
|
||||
| interval | interval of the auto loop, in milliseconds | number | — | 3000 |
|
||||
| indicator-position | position of the indicators | string | outside/none | — |
|
||||
| arrow | when arrows are shown | string | always/hover/never | hover |
|
||||
| type | type of the Carousel | string | card | — |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|---------|---------|---------|
|
||||
| change | triggers when the active slide switches | index of the new active slide, index of the old active slide |
|
||||
|
||||
### Methods
|
||||
| Method | Description | Parameters |
|
||||
|---------- |-------------- | - |
|
||||
| setActiveItem | manually switch slide | index of the slide to be switched to, starting from 0; or the `name` of corresponding `el-carousel-item` |
|
||||
| prev | switch to the previous slide | — |
|
||||
| next | switch to the next slide | — |
|
||||
|
||||
### Carousel-Item Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| name | name of the item, can be used in `setActiveItem` | string | — | — |
|
||||
|
|
|
@ -40,7 +40,7 @@ Checkbox can be used alone to switch between two states.
|
|||
```
|
||||
:::
|
||||
|
||||
## Disabled State
|
||||
### Disabled State
|
||||
|
||||
Disabled state for checkbox.
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1'],
|
||||
activeName: '1'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleChange(val) {
|
||||
console.log(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.demo-collapse {
|
||||
.el-collapse-item__header {
|
||||
.header-icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
## Collapse
|
||||
|
||||
Use Collapse to storage content.
|
||||
|
||||
### Basic usage
|
||||
|
||||
可同时展开多个面板,面板之间不影响
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-collapse v-model="activeNames" @change="handleChange">
|
||||
<el-collapse-item title="Consistency" name="1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Efficiency" name="3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1']
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Accordion
|
||||
|
||||
At the same time only one item can be opened.
|
||||
|
||||
:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。
|
||||
```html
|
||||
<el-collapse v-model="activeName" accordion>
|
||||
<el-collapse-item title="Consistency" name="1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Efficiency" name="3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeName: '1'
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Customize Title
|
||||
|
||||
除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-collapse accordion>
|
||||
<el-collapse-item title="Consistency">
|
||||
<template slot="title" scope="props">
|
||||
{{props.title}}<i class="header-icon el-icon-information"></i>
|
||||
</template>
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Feedback">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Efficiency">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Controllability">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
```
|
||||
:::
|
||||
|
||||
### Collapse Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| accordion | 是否手风琴模式 | boolean | — | false |
|
||||
| value | 当前激活的面板(如果是手风琴模式,绑定值类型需要为`string`,否则为`array`) | string/array | — | — |
|
||||
|
||||
### Collapse Events
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|---------|---------|---------|
|
||||
| change | 当前激活面板改变时触发(如果是手风琴模式,参数 `activeNames` 类型为`string`,否则为`array`) | (activeNames: array\|string) |
|
||||
|
||||
### Collapse Item Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| name | 唯一标志符 | string/number | — | — |
|
||||
| title | 面板标题 | string | — | — |
|
|
@ -809,11 +809,11 @@ Form component allows you to verify your data, helping you find and correct erro
|
|||
|
||||
### Form Methods
|
||||
|
||||
| Method | Description |
|
||||
| ---- | ---- |
|
||||
| validate(cb) | the method to validate the whole form |
|
||||
| validateField(prop, cb) | the method to validate a certain form item |
|
||||
| resetFields | reset all the fields and remove validation result |
|
||||
| Method | Description | Parameters |
|
||||
| ---- | ---- | ---- |
|
||||
| validate | the method to validate the whole form | Function(callback: Function(boolean)) |
|
||||
| validateField | the method to validate a certain form item | Function(prop: string, callback: Function(errorMessage: string)) |
|
||||
| resetFields | reset all the fields and remove validation result | — |
|
||||
|
||||
### Form-Item Attributes
|
||||
|
||||
|
|
|
@ -1382,7 +1382,7 @@ Customize table column so it can be integrated with other components.
|
|||
| current-change | triggers when current row changes | currentRow, oldCurrentRow |
|
||||
|
||||
### Table Methods
|
||||
| Method | Description | Parameter |
|
||||
| Method | Description | Parameters |
|
||||
|------|--------|-------|
|
||||
| clearSelection | clear selection, might be useful when `reserve-selection` is on | selection |
|
||||
| toggleRowSelection | toggle if a certain row is selected. With the second parameter, you can directly set if this row is selected | row, selected |
|
||||
|
|
|
@ -161,6 +161,7 @@ Can pick an arbitrary time range.
|
|||
| end | end time | string | — | 18:00 |
|
||||
| step | time step | string | — | 00:30 |
|
||||
| minTime | minimum time, any time before this time will be disabled | string | — | 00:00 |
|
||||
| maxTime | maximum time, any time after this time will be disabled | string | — | - |
|
||||
|
||||
### Time Picker Options
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|
|
|
@ -1 +1,239 @@
|
|||
## 走马灯
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
const demos = document.querySelectorAll('.source');
|
||||
demos[0].style.padding = '0';
|
||||
demos[0].className += ' small';
|
||||
demos[3].className += ' medium';
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.demo-carousel .block {
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
border-right: solid 1px #EFF2F6;
|
||||
float: left;
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-carousel .demonstration {
|
||||
display: block;
|
||||
color: #8492a6;
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.demo-carousel .el-carousel__container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.demo-carousel .el-carousel__item {
|
||||
h3 {
|
||||
color: #475669;
|
||||
font-size: 18px;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
&:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
&:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-carousel .small h3 {
|
||||
font-size: 14px;
|
||||
line-height: 150px;
|
||||
}
|
||||
|
||||
.demo-carousel .medium h3 {
|
||||
font-size: 14px;
|
||||
line-height: 200px;
|
||||
}
|
||||
</style>
|
||||
## Carousel 走马灯
|
||||
|
||||
在有限空间内,循环播放同一类型的图片、文字等内容
|
||||
|
||||
### 基础用法
|
||||
|
||||
适用广泛的基础用法
|
||||
|
||||
::: demo 结合使用`el-carousel`和`el-carousel-item`标签就得到了一个走马灯。幻灯片的内容是任意的,需要放在`el-carousel-item`标签中。默认情况下,在鼠标 hover 底部的指示器时就会触发切换。通过设置`trigger`属性为`click`,可以达到点击触发的效果。
|
||||
```html
|
||||
<template>
|
||||
<div class="block">
|
||||
<span class="demonstration">默认 Hover 指示器触发</span>
|
||||
<el-carousel height="150px">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Click 指示器触发</span>
|
||||
<el-carousel trigger="click" height="150px">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
line-height: 150px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### 指示器
|
||||
|
||||
可以将指示器的显示位置设置在容器外部
|
||||
|
||||
::: demo `indicator-position`属性定义了指示器的位置。默认情况下,它会显示在走马灯内部,设置为`outside`则会显示在外部;设置为`none`则不会显示指示器。
|
||||
```html
|
||||
<template>
|
||||
<el-carousel indicator-position="outside">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 18px;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### 切换箭头
|
||||
可以设置切换箭头的显示时机
|
||||
|
||||
::: demo `arrow`属性定义了切换箭头的显示时机。默认情况下,切换箭头只有在鼠标 hover 到走马灯上时才会显示;若将`arrow`设置为`always`,则会一直显示;设置为`never`,则会一直隐藏。
|
||||
```html
|
||||
<template>
|
||||
<el-carousel :interval="5000" arrow="always">
|
||||
<el-carousel-item v-for="item in 4">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 18px;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### 卡片化
|
||||
当页面宽度方向空间空余,但高度方向空间匮乏时,可使用卡片风格
|
||||
|
||||
::: demo 将`type`属性设置为`card`即可启用卡片模式。从交互上来说,卡片模式和一般模式的最大区别在于,可以通过直接点击两侧的幻灯片进行切换。
|
||||
```html
|
||||
<template>
|
||||
<el-carousel :interval="4000" type="card" height="200px">
|
||||
<el-carousel-item v-for="item in 6">
|
||||
<h3>{{ item }}</h3>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.el-carousel__item h3 {
|
||||
color: #475669;
|
||||
font-size: 14px;
|
||||
opacity: 0.75;
|
||||
line-height: 200px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n) {
|
||||
background-color: #99a9bf;
|
||||
}
|
||||
|
||||
.el-carousel__item:nth-child(2n+1) {
|
||||
background-color: #d3dce6;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
:::
|
||||
|
||||
### Carousel Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| height | 走马灯的高度 | number | — | 300 |
|
||||
| initial-index | 初始状态激活的幻灯片的索引,从 0 开始 | number | — | 0 |
|
||||
| trigger | 指示器的触发方式 | string | click | — |
|
||||
| autoplay | 是否自动切换 | boolean | — | true |
|
||||
| interval | 自动切换的时间间隔,单位为毫秒 | number | — | 3000 |
|
||||
| indicator-position | 指示器的位置 | string | outside/none | — |
|
||||
| arrow | 切换箭头的显示时机 | string | always/hover/never | hover |
|
||||
| type | 走马灯的类型 | string | card | — |
|
||||
|
||||
### Carousel Events
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|---------|---------|---------|
|
||||
| change | 幻灯片切换时触发 | 目前激活的幻灯片的索引,原幻灯片的索引 |
|
||||
|
||||
### Carousel Methods
|
||||
| 方法名 | 说明 | 参数 |
|
||||
|---------- |-------------- | - |
|
||||
| setActiveItem | 手动切换幻灯片 | 需要切换的幻灯片的索引,从 0 开始;或相应 `el-carousel-item` 的 `name` 属性值 |
|
||||
| prev | 切换至上一张幻灯片 | — |
|
||||
| next | 切换至下一张幻灯片 | — |
|
||||
|
||||
### Carousel-Item Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| name | 幻灯片的名字,可用作 `setActiveItem` 的参数 | string | — | — |
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
```
|
||||
:::
|
||||
|
||||
## 禁用状态
|
||||
### 禁用状态
|
||||
|
||||
多选框不可用状态。
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1'],
|
||||
activeName: '1'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleChange(val) {
|
||||
console.log(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.demo-collapse {
|
||||
.el-collapse-item__header {
|
||||
.header-icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
## Collapse 折叠面板
|
||||
|
||||
通过折叠面板收纳内容区域
|
||||
|
||||
### 基础用法
|
||||
|
||||
可同时展开多个面板,面板之间不影响
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-collapse v-model="activeNames" @change="handleChange">
|
||||
<el-collapse-item title="一致性 Consistency" name="1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="反馈 Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="效率 Efficiency" name="3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可控 Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1']
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 手风琴效果
|
||||
|
||||
每次只能展开一个面板
|
||||
|
||||
:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。
|
||||
```html
|
||||
<el-collapse v-model="activeName" accordion>
|
||||
<el-collapse-item title="一致性 Consistency" name="1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="反馈 Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="效率 Efficiency" name="3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可控 Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeName: '1'
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 自定义面板标题
|
||||
|
||||
除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-collapse accordion>
|
||||
<el-collapse-item title="一致性 Consistency">
|
||||
<template slot="title" scope="props">
|
||||
{{props.title}}<i class="header-icon el-icon-information"></i>
|
||||
</template>
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="反馈 Feedback">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="效率 Efficiency">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可控 Controllability">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
```
|
||||
:::
|
||||
|
||||
### Collapse Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| accordion | 是否手风琴模式 | boolean | — | false |
|
||||
| value | 当前激活的面板(如果是手风琴模式,绑定值类型需要为`string`,否则为`array`) | string/array | — | — |
|
||||
|
||||
### Collapse Events
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|---------|---------|---------|
|
||||
| change | 当前激活面板改变时触发(如果是手风琴模式,参数 `activeNames` 类型为`string`,否则为`array`) | (activeNames: array\|string) |
|
||||
|
||||
### Collapse Item Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| name | 唯一标志符 | string/number | — | — |
|
||||
| title | 面板标题 | string | — | — |
|
|
@ -168,6 +168,7 @@
|
|||
| end | 结束时间 | string | — | 18:00 |
|
||||
| step | 间隔时间 | string | — | 00:30 |
|
||||
| minTime | 最小时间,小于该时间的时间段将被禁用 | string | — | 00:00 |
|
||||
| maxTime | 最大时间,大于该时间的时间段将被禁用 | string | — | - |
|
||||
|
||||
### Time Picker Options
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|
|
|
@ -19,5 +19,10 @@
|
|||
|
||||
ga('create', 'UA-84335471-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
window.addEventListener('hashchange', function () {
|
||||
ga('set', 'page', window.location.href);
|
||||
ga('send', 'pageview');
|
||||
});
|
||||
</script><% } %>
|
||||
</html>
|
||||
|
|
|
@ -211,6 +211,10 @@
|
|||
{
|
||||
"path": "/carousel",
|
||||
"title": "Carousel 走马灯"
|
||||
},
|
||||
{
|
||||
"path": "/collapse",
|
||||
"title": "Collapse 折叠面板"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -429,6 +433,10 @@
|
|||
{
|
||||
"path": "/carousel",
|
||||
"title": "Carousel"
|
||||
},
|
||||
{
|
||||
"path": "/collapse",
|
||||
"title": "Collapse"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/ElemeFE/element/issues"
|
||||
},
|
||||
"unpkg": "lib/index.js",
|
||||
"style": "lib/theme-default/index.css",
|
||||
"dependencies": {
|
||||
"async-validator": "^1.6.6",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import ElCarouselItem from '../carousel/src/item';
|
||||
|
||||
/* istanbul ignore next */
|
||||
ElCarouselItem.install = function(Vue) {
|
||||
Vue.component(ElCarouselItem.name, ElCarouselItem);
|
||||
};
|
||||
|
||||
export default ElCarouselItem;
|
|
@ -0,0 +1,10 @@
|
|||
import ElCarousel from './src/main';
|
||||
import ElCarouselItem from './src/item';
|
||||
|
||||
/* istanbul ignore next */
|
||||
export default function(Vue) {
|
||||
Vue.component(ElCarousel.name, ElCarousel);
|
||||
Vue.component(ElCarouselItem.name, ElCarouselItem);
|
||||
};
|
||||
|
||||
export { ElCarousel, ElCarouselItem };
|
|
@ -4,7 +4,7 @@ var config = require('../../build/config');
|
|||
|
||||
cooking.set({
|
||||
entry: {
|
||||
index: path.join(__dirname, 'index.js')
|
||||
index: path.join(__dirname, '_index.js')
|
||||
},
|
||||
dist: path.join(__dirname, 'lib'),
|
||||
template: false,
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
"name": "element-carousel",
|
||||
"version": "0.0.0",
|
||||
"description": "A carousel component for Vue.js.",
|
||||
"main": "lib/index.js",
|
||||
"keywords": [
|
||||
"element",
|
||||
"vue",
|
||||
"component"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"repository": "https://github.com/ElemeFE/element/tree/master/packages/carousel",
|
||||
"author": "elemefe",
|
||||
"license": "MIT",
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"throttle-debounce": "^1.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div
|
||||
v-show="ready"
|
||||
class="el-carousel__item"
|
||||
:class="{
|
||||
'is-active': active,
|
||||
'el-carousel__item--card': $parent.type === 'card',
|
||||
'is-in-stage': inStage
|
||||
}"
|
||||
@click="handleItemClick"
|
||||
:style="{
|
||||
msTransform: `translateX(${ translate }px) scale(${ scale })`,
|
||||
webkitTransform: `translateX(${ translate }px) scale(${ scale })`,
|
||||
transform: `translateX(${ translate }px) scale(${ scale })`
|
||||
}">
|
||||
<div
|
||||
v-if="$parent.type === 'card'"
|
||||
v-show="!active"
|
||||
class="el-carousel__mask">
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const CARD_SCALE = 0.83;
|
||||
export default {
|
||||
name: 'ElCarouselItem',
|
||||
|
||||
props: {
|
||||
name: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
translate: 0,
|
||||
scale: 1,
|
||||
active: false,
|
||||
ready: false,
|
||||
inStage: false
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
processIndex(index, activeIndex, length) {
|
||||
if (activeIndex === 0 && index === length - 1) {
|
||||
return -1;
|
||||
} else if (activeIndex === length - 1 && index === 0) {
|
||||
return length;
|
||||
} else if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
|
||||
return length + 1;
|
||||
} else if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
|
||||
return -2;
|
||||
}
|
||||
return index;
|
||||
},
|
||||
|
||||
calculateTranslate(index, activeIndex, parentWidth) {
|
||||
if (this.inStage) {
|
||||
return parentWidth * ((2 - CARD_SCALE) * (index - activeIndex) + 1) / 4;
|
||||
} else if (index < activeIndex) {
|
||||
return -(1 + CARD_SCALE) * parentWidth / 4;
|
||||
} else {
|
||||
return (3 + CARD_SCALE) * parentWidth / 4;
|
||||
}
|
||||
},
|
||||
|
||||
translateItem(index, activeIndex) {
|
||||
const parentWidth = this.$parent.$el.offsetWidth;
|
||||
const length = this.$parent.items.length;
|
||||
|
||||
if (this.$parent.type === 'card') {
|
||||
if (index !== activeIndex && length > 2) {
|
||||
index = this.processIndex(index, activeIndex, length);
|
||||
}
|
||||
this.inStage = Math.round(Math.abs(index - activeIndex)) <= 1;
|
||||
this.active = index === activeIndex;
|
||||
this.translate = this.calculateTranslate(index, activeIndex, parentWidth);
|
||||
this.scale = this.active ? 1 : CARD_SCALE;
|
||||
} else {
|
||||
this.active = index === activeIndex;
|
||||
this.translate = parentWidth * (index - activeIndex);
|
||||
}
|
||||
this.ready = true;
|
||||
},
|
||||
|
||||
handleItemClick() {
|
||||
const parent = this.$parent;
|
||||
if (parent && parent.type === 'card') {
|
||||
const index = parent.items.indexOf(this);
|
||||
parent.setActiveItem(index);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$parent && this.$parent.handleItemChange();
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
this.$parent && this.$parent.handleItemChange();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,9 +1,211 @@
|
|||
<template>
|
||||
<div class="el-carousel"></div>
|
||||
<div
|
||||
class="el-carousel"
|
||||
:class="{ 'el-carousel--card': type === 'card' }"
|
||||
@mouseenter.stop="handleMouseEnter"
|
||||
@mouseleave.stop="handleMouseLeave">
|
||||
<div
|
||||
class="el-carousel__container"
|
||||
:style="{ height: height }">
|
||||
<transition name="carousel-arrow-left">
|
||||
<button
|
||||
v-if="arrow !== 'never'"
|
||||
v-show="arrow === 'always' || hover"
|
||||
@click.stop="throttledArrowClick(activeIndex - 1)"
|
||||
class="el-carousel__arrow el-carousel__arrow--left">
|
||||
<i class="el-icon-arrow-left"></i>
|
||||
</button>
|
||||
</transition>
|
||||
<transition name="carousel-arrow-right">
|
||||
<button
|
||||
v-if="arrow !== 'never'"
|
||||
v-show="arrow === 'always' || hover"
|
||||
@click.stop="throttledArrowClick(activeIndex + 1)"
|
||||
class="el-carousel__arrow el-carousel__arrow--right">
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</button>
|
||||
</transition>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<ul
|
||||
class="el-carousel__indicators"
|
||||
v-if="indicatorPosition !== 'none'"
|
||||
:class="{ 'el-carousel__indicators--outside': indicatorPosition === 'outside' || type === 'card' }">
|
||||
<li
|
||||
v-for="(item, index) in items"
|
||||
class="el-carousel__indicator"
|
||||
:class="{ 'is-active': index === activeIndex }"
|
||||
@mouseenter="throttledIndicatorHover(index)"
|
||||
@click.stop="handleIndicatorClick(index)">
|
||||
<button class="el-carousel__button"></button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import throttle from 'throttle-debounce/throttle';
|
||||
import debounce from 'throttle-debounce/debounce';
|
||||
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
|
||||
|
||||
export default {
|
||||
name: 'ElCarousel'
|
||||
name: 'ElCarousel',
|
||||
|
||||
props: {
|
||||
initialIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
height: String,
|
||||
trigger: {
|
||||
type: String,
|
||||
default: 'hover'
|
||||
},
|
||||
autoPlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
interval: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
},
|
||||
indicatorPosition: String,
|
||||
indicator: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
arrow: {
|
||||
type: String,
|
||||
default: 'hover'
|
||||
},
|
||||
type: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
items: [],
|
||||
activeIndex: -1,
|
||||
containerWidth: 0,
|
||||
timer: null,
|
||||
hover: false
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
activeIndex(val, oldVal) {
|
||||
this.resetItemPosition();
|
||||
this.$emit('change', val, oldVal);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleMouseEnter() {
|
||||
this.hover = true;
|
||||
this.pauseTimer();
|
||||
},
|
||||
|
||||
handleMouseLeave() {
|
||||
this.hover = false;
|
||||
this.startTimer();
|
||||
},
|
||||
|
||||
handleItemChange() {
|
||||
debounce(100, () => {
|
||||
this.updateItems();
|
||||
});
|
||||
},
|
||||
|
||||
updateItems() {
|
||||
this.items = this.$children.filter(child => child.$options.name === 'ElCarouselItem');
|
||||
},
|
||||
|
||||
resetItemPosition() {
|
||||
this.items.forEach((item, index) => {
|
||||
item.translateItem(index, this.activeIndex);
|
||||
});
|
||||
},
|
||||
|
||||
playSlides() {
|
||||
if (this.activeIndex < this.items.length - 1) {
|
||||
this.activeIndex++;
|
||||
} else {
|
||||
this.activeIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
pauseTimer() {
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
startTimer() {
|
||||
if (this.interval <= 0 || !this.autoPlay) return;
|
||||
this.timer = setInterval(this.playSlides, this.interval);
|
||||
},
|
||||
|
||||
setActiveItem(index) {
|
||||
if (typeof index === 'string') {
|
||||
const filteredItems = this.items.filter(item => item.name === index);
|
||||
if (filteredItems.length > 0) {
|
||||
index = this.items.indexOf(filteredItems[0]);
|
||||
}
|
||||
}
|
||||
index = Number(index);
|
||||
if (isNaN(index) || index !== Math.floor(index)) {
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
console.warn('[Element Warn][Carousel]index must be an integer.');
|
||||
return;
|
||||
}
|
||||
let length = this.items.length;
|
||||
if (index < 0) {
|
||||
this.activeIndex = length - 1;
|
||||
} else if (index >= length) {
|
||||
this.activeIndex = 0;
|
||||
} else {
|
||||
this.activeIndex = index;
|
||||
}
|
||||
},
|
||||
|
||||
prev() {
|
||||
this.setActiveItem(this.activeIndex - 1);
|
||||
},
|
||||
|
||||
next() {
|
||||
this.setActiveItem(this.activeIndex + 1);
|
||||
},
|
||||
|
||||
handleIndicatorClick(index) {
|
||||
this.activeIndex = index;
|
||||
},
|
||||
|
||||
handleIndicatorHover(index) {
|
||||
if (this.trigger === 'hover' && index !== this.activeIndex) {
|
||||
this.activeIndex = index;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.throttledArrowClick = throttle(300, true, index => {
|
||||
this.setActiveItem(index);
|
||||
});
|
||||
this.throttledIndicatorHover = throttle(300, index => {
|
||||
this.handleIndicatorHover(index);
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.updateItems();
|
||||
this.$nextTick(() => {
|
||||
addResizeListener(this.$el, this.resetItemPosition);
|
||||
if (this.initialIndex < this.items.length && this.initialIndex >= 0) {
|
||||
this.activeIndex = this.initialIndex;
|
||||
}
|
||||
this.startTimer();
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
if (this.$el) removeResizeListener(this.$el, this.resetItemPosition);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import ElCollapseItem from '../collapse/src/collapse-item.vue';
|
||||
|
||||
/* istanbul ignore next */
|
||||
ElCollapseItem.install = function(Vue) {
|
||||
Vue.component(ElCollapseItem.name, ElCollapseItem);
|
||||
};
|
||||
|
||||
export default ElCollapseItem;
|
|
@ -0,0 +1,13 @@
|
|||
import ElCollapse from './src/collapse';
|
||||
import ElCollapseItem from './src/collapse-item.vue';
|
||||
|
||||
/* istanbul ignore next */
|
||||
export default function install(Vue) {
|
||||
Vue.component(ElCollapseItem.name, ElCollapseItem);
|
||||
Vue.component(ElCollapse.name, ElCollapse);
|
||||
};
|
||||
|
||||
export {
|
||||
ElCollapse,
|
||||
ElCollapseItem
|
||||
};
|
|
@ -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: 'ElCollapse',
|
||||
extends: ['vue2'],
|
||||
alias: config.alias,
|
||||
externals: { vue: config.vue }
|
||||
});
|
||||
|
||||
module.exports = cooking.resolve();
|
|
@ -0,0 +1,9 @@
|
|||
import ElCollapse from './src/collapse';
|
||||
|
||||
/* istanbul ignore next */
|
||||
ElCollapse.install = function(Vue) {
|
||||
Vue.component(ElCollapse.name, ElCollapse);
|
||||
};
|
||||
|
||||
export default ElCollapse;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "element-collapse",
|
||||
"version": "1.0.0",
|
||||
"description": "A row component for Vue.",
|
||||
"keywords": [
|
||||
"element",
|
||||
"vue",
|
||||
"component"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"repository": "https://github.com/ElemeFE/element/tree/master/packages/collapse",
|
||||
"author": "haiping.zeng@ele.me",
|
||||
"license": "MIT",
|
||||
"dependencies": {}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<div class="el-collapse-item" :class="{'is-active': isActive}">
|
||||
<div class="el-collapse-item__header" @click="handleHeaderClick">
|
||||
<i class="el-collapse-item__header__arrow el-icon-arrow-right"></i>
|
||||
<slot name="title" :title="title">{{title}}</slot>
|
||||
</div>
|
||||
<div class="el-collapse-item__wrap" ref="content" :style="contentStyle">
|
||||
<div class="el-collapse-item__content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { once } from 'wind-dom';
|
||||
import Emitter from 'element-ui/src/mixins/emitter';
|
||||
|
||||
function getTransitionendEvent(el) {
|
||||
let t;
|
||||
let transitions = {
|
||||
'transition': 'transitionend',
|
||||
'OTransition': 'oTransitionEnd',
|
||||
'MozTransition': 'transitionend',
|
||||
'WebkitTransition': 'webkitTransitionEnd'
|
||||
};
|
||||
|
||||
for (t in transitions) {
|
||||
if (el.style[t] !== undefined) {
|
||||
return transitions[t];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'ElCollapseItem',
|
||||
|
||||
componentName: 'ElCollapseItem',
|
||||
|
||||
mixins: [Emitter],
|
||||
|
||||
data() {
|
||||
return {
|
||||
contentStyle: {},
|
||||
contentHeight: 0
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
title: String,
|
||||
name: {
|
||||
type: [String, Number],
|
||||
default() {
|
||||
return this._uid;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
isActive() {
|
||||
return this.$parent.activeNames.indexOf(this.name) > -1;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'isActive'(value) {
|
||||
value ? this.open() : this.close();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
open() {
|
||||
const contentElm = this.$refs.content;
|
||||
const contentStyle = this.contentStyle;
|
||||
|
||||
contentStyle.display = 'block';
|
||||
this.$nextTick(_ => {
|
||||
contentStyle.height = this.contentHeight + 'px';
|
||||
once(contentElm, getTransitionendEvent(contentElm), () => {
|
||||
contentStyle.height = 'auto';
|
||||
});
|
||||
});
|
||||
},
|
||||
close() {
|
||||
const contentElm = this.$refs.content;
|
||||
const contentHeight = contentElm.clientHeight;
|
||||
const contentStyle = this.contentStyle;
|
||||
|
||||
this.contentHeight = contentHeight;
|
||||
this.$set(this.contentStyle, 'height', contentHeight + 'px');
|
||||
|
||||
this.$nextTick(_ => {
|
||||
contentStyle.height = '0';
|
||||
once(contentElm, getTransitionendEvent(contentElm), () => {
|
||||
this.$set(this.contentStyle, 'display', 'none');
|
||||
});
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.contentHeight = this.$refs.content.clientHeight;
|
||||
|
||||
if (!this.isActive) {
|
||||
this.$set(this.contentStyle, 'height', '0');
|
||||
this.$set(this.contentStyle, 'display', 'none');
|
||||
}
|
||||
},
|
||||
handleHeaderClick() {
|
||||
this.dispatch('ElCollapse', 'item-click', this);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<div class="el-collapse">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'ElCollapse',
|
||||
|
||||
componentName: 'ElCollapse',
|
||||
|
||||
props: {
|
||||
accordion: Boolean,
|
||||
value: {
|
||||
type: [Array, String],
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
activeNames: [].concat(this.value)
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(value) {
|
||||
this.activeNames = [].concat(value);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
setActiveNames(activeNames) {
|
||||
let value = this.accordion ? activeNames[0] : activeNames;
|
||||
this.activeNames = [].concat(value);
|
||||
this.$emit('input', value);
|
||||
this.$emit('change', value);
|
||||
},
|
||||
handleItemClick(item) {
|
||||
if (this.accordion) {
|
||||
this.setActiveNames(this.activeNames[0] === item.name ? '' : item.name);
|
||||
} else {
|
||||
let activeNames = this.activeNames.slice(0);
|
||||
let index = activeNames.indexOf(item.name);
|
||||
|
||||
if (index > -1) {
|
||||
activeNames.splice(index, 1);
|
||||
} else {
|
||||
activeNames.push(item.name);
|
||||
}
|
||||
this.setActiveNames(activeNames);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$on('item-click', this.handleItemClick);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -74,8 +74,11 @@
|
|||
components: { ElScrollbar },
|
||||
|
||||
watch: {
|
||||
minTime(val) {
|
||||
if (this.value && val && compareTime(this.value, val) === -1) {
|
||||
value(val) {
|
||||
if (!val) return;
|
||||
if (this.minTime && compareTime(val, this.minTime) < 0) {
|
||||
this.$emit('pick');
|
||||
} else if (this.maxTime && compareTime(val, this.maxTime) > 0) {
|
||||
this.$emit('pick');
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +105,7 @@
|
|||
value: '',
|
||||
visible: false,
|
||||
minTime: '',
|
||||
maxTime: '',
|
||||
width: 0
|
||||
};
|
||||
},
|
||||
|
@ -119,7 +123,8 @@
|
|||
while (compareTime(current, end) <= 0) {
|
||||
result.push({
|
||||
value: current,
|
||||
disabled: compareTime(current, this.minTime || '-1:-1') <= 0
|
||||
disabled: compareTime(current, this.minTime || '-1:-1') <= 0 ||
|
||||
compareTime(current, this.maxTime || '100:100') > 0
|
||||
});
|
||||
current = nextTime(current, step);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
@charset "UTF-8";
|
||||
@import "./common/var.css";
|
||||
|
||||
@component-namespace el {
|
||||
|
||||
@b carousel {
|
||||
@e item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
transition: .4s ease-in-out;
|
||||
overflow: hidden;
|
||||
|
||||
@modifier card {
|
||||
width: 50%;
|
||||
z-index: calc(var(--index-normal) - 1);
|
||||
&.is-in-stage {
|
||||
cursor: pointer;
|
||||
z-index: var(--index-normal);
|
||||
&:hover .el-carousel__mask {
|
||||
opacity: 0.12;
|
||||
}
|
||||
}
|
||||
&.is-active {
|
||||
z-index: calc(var(--index-normal) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@e mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: var(--color-white);
|
||||
opacity: 0.24;
|
||||
transition: .2s;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
@charset "UTF-8";
|
||||
@import "./common/var.css";
|
||||
|
||||
@component-namespace el {
|
||||
|
||||
@b carousel {
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
|
||||
@e container {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
@e arrow {
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
size: var(--carousel-arrow-size);
|
||||
cursor: pointer;
|
||||
transition: .3s;
|
||||
border-radius: 50%;
|
||||
background-color: var(--carousel-arrow-background);
|
||||
color: var(--color-white);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
z-index: 10;
|
||||
transform: translateY(-50%);
|
||||
text-align: center;
|
||||
font-size: var(--carousel-arrow-font-size);
|
||||
|
||||
@modifier left {
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
@modifier right {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--carousel-arrow-hover-background);
|
||||
}
|
||||
|
||||
& i {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@e indicators {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@modifier outside {
|
||||
bottom: calc(var(--carousel-indicator-height) + var(--carousel-indicator-padding-vertical) * 2);
|
||||
text-align: center;
|
||||
position: static;
|
||||
transform: none;
|
||||
.el-carousel__indicator:hover button {
|
||||
opacity: 0.64;
|
||||
}
|
||||
button {
|
||||
background-color: var(--carousel-indicator-out-color);
|
||||
opacity: 0.24;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@e indicator {
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
padding: var(--carousel-indicator-padding-vertical) var(--carousel-indicator-padding-horizontal);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover button {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
@when active {
|
||||
button {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@e button {
|
||||
display: block;
|
||||
opacity: 0.48;
|
||||
size: var(--carousel-indicator-width) var(--carousel-indicator-height);
|
||||
background-color: var(--color-white);
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
transition: .3s;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-arrow-left-enter,
|
||||
.carousel-arrow-left-leave-active {
|
||||
transform: translateY(-50%) translateX(-10px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.carousel-arrow-right-enter,
|
||||
.carousel-arrow-right-leave-active {
|
||||
transform: translateY(-50%) translateX(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
@charset "UTF-8";
|
||||
@import "./common/var.css";
|
||||
|
||||
@component-namespace el {
|
||||
@b collapse {
|
||||
border: 1px solid var(--collapse-border-color);
|
||||
border-radius: var(--collapse-border-radius);
|
||||
}
|
||||
@b collapse-item {
|
||||
@e header {
|
||||
height: var(--collapse-header-height);
|
||||
line-height: @height;
|
||||
padding-left: 15px;
|
||||
background-color: var(--collapse-header-fill);
|
||||
color: var(--collapse-header-color);
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid var(--collapse-border-color);
|
||||
font-size: var(--collapse-header-size);
|
||||
|
||||
@e arrow {
|
||||
margin-right: 8px;
|
||||
transition: transform .3s;
|
||||
}
|
||||
}
|
||||
|
||||
@e wrap {
|
||||
will-change: height;
|
||||
background-color: var(--collapse-content-fill);
|
||||
transition: height .3s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid var(--collapse-border-color);
|
||||
}
|
||||
|
||||
@e content {
|
||||
padding: 10px 15px;
|
||||
font-size: var(--collapse-content-size);
|
||||
color: var(--collapse-content-color);
|
||||
line-height: 1.769230769230769;
|
||||
}
|
||||
|
||||
@when active {
|
||||
.el-collapse-item__header__arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -549,4 +549,29 @@
|
|||
--------------------------*/
|
||||
--scrollbar-background-color: rgba(#99a9bf, .3);
|
||||
--scrollbar-hover-background-color: rgba(#99a9bf, .5);
|
||||
|
||||
/* Carousel
|
||||
--------------------------*/
|
||||
--carousel-arrow-font-size: 12px;
|
||||
--carousel-arrow-size: 36px;
|
||||
--carousel-arrow-background: rgba(31, 45, 61, 0.11);
|
||||
--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23);
|
||||
--carousel-indicator-width: 30px;
|
||||
--carousel-indicator-height: 2px;
|
||||
--carousel-indicator-padding-horizontal: 4px;
|
||||
--carousel-indicator-padding-vertical: 12px;
|
||||
--carousel-indicator-out-color: var(--border-color-hover);
|
||||
|
||||
/* Collapse
|
||||
--------------------------*/
|
||||
--collapse-border-color: #e0e6ed;
|
||||
--collapse-header-height: 43px;
|
||||
--collapse-border-radius: 0;
|
||||
--collapse-header-padding: 20px;
|
||||
--collapse-header-fill: #fff;
|
||||
--collapse-header-color: #475669;
|
||||
--collapse-header-size: 13px;
|
||||
--collapse-content-fill: #f9fafc;
|
||||
--collapse-content-size: 13px;
|
||||
--collapse-content-color: #1f2d3d;
|
||||
}
|
||||
|
|
|
@ -41,3 +41,6 @@
|
|||
@import "./steps.css";
|
||||
@import "./step.css";
|
||||
@import "./scrollbar.css";
|
||||
@import "./carousel.css";
|
||||
@import "./carousel-item.css";
|
||||
@import "./collapse.css";
|
||||
|
|
11
src/index.js
11
src/index.js
|
@ -57,6 +57,9 @@ import Steps from '../packages/steps';
|
|||
import Step from '../packages/step';
|
||||
import Carousel from '../packages/carousel';
|
||||
import Scrollbar from '../packages/scrollbar';
|
||||
import CarouselItem from '../packages/carousel-item';
|
||||
import Collapse from '../packages/collapse';
|
||||
import CollapseItem from '../packages/collapse-item';
|
||||
import locale from 'element-ui/src/locale';
|
||||
|
||||
const install = function(Vue, opts = {}) {
|
||||
|
@ -117,6 +120,9 @@ const install = function(Vue, opts = {}) {
|
|||
Vue.component(Step.name, Step);
|
||||
Vue.component(Carousel.name, Carousel);
|
||||
Vue.component(Scrollbar.name, Scrollbar);
|
||||
Vue.component(CarouselItem.name, CarouselItem);
|
||||
Vue.component(Collapse.name, Collapse);
|
||||
Vue.component(CollapseItem.name, CollapseItem);
|
||||
|
||||
Vue.use(Loading.directive);
|
||||
|
||||
|
@ -194,5 +200,8 @@ module.exports = {
|
|||
Steps,
|
||||
Step,
|
||||
Carousel,
|
||||
Scrollbar
|
||||
Scrollbar,
|
||||
CarouselItem,
|
||||
Collapse,
|
||||
CollapseItem
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { createTest, destroyVM } from '../util';
|
||||
import Carousel from 'packages/carousel';
|
||||
import { createVue, destroyVM } from '../util';
|
||||
|
||||
describe('Carousel', () => {
|
||||
let vm;
|
||||
|
@ -8,8 +7,236 @@ describe('Carousel', () => {
|
|||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createTest(Carousel, true);
|
||||
expect(vm.$el).to.exist;
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel>
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
expect(vm.$el.querySelectorAll('.el-carousel__item').length).to.equal(3);
|
||||
});
|
||||
|
||||
it('auto play', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :interval="50">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const items = vm.$el.querySelectorAll('.el-carousel__item');
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
setTimeout(() => {
|
||||
expect(items[1].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 60);
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('initial index', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false" :initial-index="1">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelectorAll('.el-carousel__item')[1].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('reset timer', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :interval="20">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const carousel = vm.$children[0];
|
||||
const items = vm.$el.querySelectorAll('.el-carousel__item');
|
||||
carousel.handleMouseEnter();
|
||||
setTimeout(() => {
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
carousel.handleMouseLeave();
|
||||
setTimeout(() => {
|
||||
expect(items[1].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 30);
|
||||
}, 20);
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('change', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :interval="50" @change="handleChange">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
val: -1,
|
||||
oldVal: -1
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleChange(val, oldVal) {
|
||||
this.val = val;
|
||||
this.oldVal = oldVal;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.val).to.equal(1);
|
||||
expect(vm.oldVal).to.equal(0);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
describe('manual control', () => {
|
||||
it('hover', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
vm.$children[0].throttledIndicatorHover(1);
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelectorAll('.el-carousel__item')[1].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('click', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false" trigger="click">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const items = vm.$el.querySelectorAll('.el-carousel__item');
|
||||
vm.$el.querySelectorAll('.el-carousel__indicator')[2].click();
|
||||
setTimeout(() => {
|
||||
expect(items[2].classList.contains('is-active')).to.true;
|
||||
vm.$el.querySelector('.el-carousel__arrow--right').click();
|
||||
setTimeout(() => {
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
it('setActiveItem', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
vm.$children[0].setActiveItem(1);
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelectorAll('.el-carousel__item')[1].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
||||
|
||||
it('slide', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false">
|
||||
<el-carousel-item v-for="item in 3"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
vm.$children[0].prev(1);
|
||||
const items = vm.$el.querySelectorAll('.el-carousel__item');
|
||||
setTimeout(() => {
|
||||
expect(items[2].classList.contains('is-active')).to.true;
|
||||
vm.$children[0].next(1);
|
||||
setTimeout(() => {
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
it('card', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-carousel :autoplay="false" type="card">
|
||||
<el-carousel-item v-for="item in 7"></el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const items = vm.$el.querySelectorAll('.el-carousel__item');
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
expect(items[1].classList.contains('is-in-stage')).to.true;
|
||||
expect(items[6].classList.contains('is-in-stage')).to.true;
|
||||
items[1].click();
|
||||
setTimeout(() => {
|
||||
expect(items[1].classList.contains('is-active')).to.true;
|
||||
vm.$el.querySelector('.el-carousel__arrow--left').click();
|
||||
setTimeout(() => {
|
||||
expect(items[0].classList.contains('is-active')).to.true;
|
||||
items[6].click();
|
||||
setTimeout(() => {
|
||||
expect(items[6].classList.contains('is-active')).to.true;
|
||||
done();
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import { createVue, destroyVM } from '../util';
|
||||
|
||||
describe('Collapse', () => {
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
destroyVM(vm);
|
||||
});
|
||||
|
||||
it('create', done => {
|
||||
vm = createVue({
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1']
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<el-collapse v-model="activeNames" ref="collapse">
|
||||
<el-collapse-item title="一致性 Consistency" name="1" ref="item1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="反馈 Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="效率 Efficiency" name="3" ref="item3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可控 Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
`
|
||||
}, true);
|
||||
const collapse = vm.$refs.collapse;
|
||||
const spy = sinon.spy();
|
||||
|
||||
collapse.$on('change', spy);
|
||||
expect(vm.$refs.item1.isActive).to.be.true;
|
||||
vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click();
|
||||
vm.$nextTick(_ => {
|
||||
expect(vm.$refs.item1.isActive).to.be.true;
|
||||
expect(vm.$refs.item3.isActive).to.be.true;
|
||||
expect(spy.calledOnce).to.be.true;
|
||||
|
||||
vm.$refs.item1.$el.querySelector('.el-collapse-item__header').click();
|
||||
|
||||
vm.$nextTick(_ => {
|
||||
expect(vm.$refs.item1.isActive).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('accordion', done => {
|
||||
vm = createVue({
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1']
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<el-collapse accordion v-model="activeNames" ref="collapse">
|
||||
<el-collapse-item title="一致性 Consistency" name="1" ref="item1">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="反馈 Feedback" name="2">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="效率 Efficiency" name="3" ref="item3">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可控 Controllability" name="4">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
`
|
||||
}, true);
|
||||
|
||||
expect(vm.$refs.item1.isActive).to.be.true;
|
||||
vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click();
|
||||
vm.$nextTick(_ => {
|
||||
expect(vm.$refs.item1.isActive).to.be.false;
|
||||
expect(vm.$refs.item3.isActive).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -140,4 +140,62 @@ describe('TimeSelect', () => {
|
|||
}, 50);
|
||||
}, 50);
|
||||
});
|
||||
|
||||
it('set maxTime', done => {
|
||||
vm = createVue(`
|
||||
<el-time-select
|
||||
ref="picker"
|
||||
:picker-options="{
|
||||
maxTime: '14:30',
|
||||
step: '00:30'
|
||||
}">
|
||||
</el-time-select>
|
||||
`, true);
|
||||
const input = vm.$el.querySelector('input');
|
||||
const picker = vm.$refs.picker;
|
||||
|
||||
input.focus();
|
||||
input.blur();
|
||||
|
||||
setTimeout(_ => {
|
||||
const elm = picker.picker.$el.querySelector('.disabled');
|
||||
|
||||
expect(elm.textContent).to.equal('15:00');
|
||||
destroyVM(vm);
|
||||
done();
|
||||
}, 50);
|
||||
});
|
||||
|
||||
it('maxTime > value', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<el-time-select
|
||||
ref="picker"
|
||||
v-model="value"
|
||||
:picker-options="{
|
||||
maxTime: '14:30'
|
||||
}">
|
||||
</el-time-select>
|
||||
`,
|
||||
data() {
|
||||
return { value: '09:30' };
|
||||
}
|
||||
}, true);
|
||||
const input = vm.$el.querySelector('input');
|
||||
const picker = vm.$refs.picker;
|
||||
|
||||
input.focus();
|
||||
input.blur();
|
||||
|
||||
setTimeout(_ => {
|
||||
vm.value = '10:30';
|
||||
|
||||
setTimeout(_ => {
|
||||
expect(picker.picker.value).to.equal('09:30');
|
||||
destroyVM(vm);
|
||||
done();
|
||||
}, 50);
|
||||
}, 50);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
28
yarn.lock
28
yarn.lock
|
@ -1317,11 +1317,12 @@ cooking-lint@^0.1.3:
|
|||
eslint-plugin-react "*"
|
||||
eslint-plugin-vue "*"
|
||||
|
||||
cooking-vue2@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/cooking-vue2/-/cooking-vue2-0.1.4.tgz#4344650f1252daace5955e60cd48a07adf876750"
|
||||
cooking-vue2@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/cooking-vue2/-/cooking-vue2-0.3.0.tgz#a38062164d80df49a788b1669dcb45eddab91238"
|
||||
dependencies:
|
||||
vue-loader "^9.4.2"
|
||||
vue-loader ">=9.4.2"
|
||||
vue-template-compiler "*"
|
||||
|
||||
cooking@^1.2.0:
|
||||
version "1.2.7"
|
||||
|
@ -6835,9 +6836,9 @@ vue-hot-reload-api@^2.0.1:
|
|||
version "2.0.6"
|
||||
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@^9.9.0:
|
||||
version "9.9.5"
|
||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-9.9.5.tgz#0893e3093e90c8fbe852053b2b0f4854a3bf4651"
|
||||
vue-loader@^10.0.2, vue-loader@>=9.4.2:
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-10.0.2.tgz#6fe7bcefb32c5439bd0338464aa22673ad62299c"
|
||||
dependencies:
|
||||
consolidate "^0.14.0"
|
||||
hash-sum "^1.0.2"
|
||||
|
@ -6850,7 +6851,6 @@ vue-loader@^9.4.2, vue-loader@^9.9.0:
|
|||
source-map "^0.5.6"
|
||||
vue-hot-reload-api "^2.0.1"
|
||||
vue-style-loader "^1.0.0"
|
||||
vue-template-compiler "^2.0.5"
|
||||
vue-template-es2015-compiler "^1.2.2"
|
||||
|
||||
vue-markdown-loader@^0.5.1:
|
||||
|
@ -6879,9 +6879,9 @@ vue-style-loader@^1.0.0:
|
|||
dependencies:
|
||||
loader-utils "^0.2.7"
|
||||
|
||||
vue-template-compiler@^2.0.5, vue-template-compiler@2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.0.5.tgz#6a8c454e7d4ed03cc295ae9733a432e31df25ea3"
|
||||
vue-template-compiler@*, vue-template-compiler@2.1.6:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.1.6.tgz#f96f968652fc1e861bb0052f61993ba1fdc18ad3"
|
||||
dependencies:
|
||||
de-indent "^1.0.2"
|
||||
he "^1.1.0"
|
||||
|
@ -6890,9 +6890,9 @@ vue-template-es2015-compiler@^1.2.2:
|
|||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.4.0.tgz#7b88853ca4bf8d84ae54ab9e56771de271e60198"
|
||||
|
||||
vue@2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.0.5.tgz#b99dc7180a802d1148a508db3d84b52c09b5ca8e"
|
||||
vue@2.1.6:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.1.6.tgz#2fc0024c07479ac6bc7d34a2cd5ef9ca5e90b143"
|
||||
|
||||
watchpack@^0.2.1:
|
||||
version "0.2.9"
|
||||
|
|
Loading…
Reference in New Issue