mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-30 11:16:12 +08:00
feat(affix): new component affix (#1260)
* feat(affix): new component affix re #1247 * feat: add test * perf: update state n * docs: update docs * perf: pref the component
This commit is contained in:
parent
30f1947c47
commit
8bda98b075
158
packages/affix/__tests__/affix.spec.ts
Normal file
158
packages/affix/__tests__/affix.spec.ts
Normal file
@ -0,0 +1,158 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Affix from '../src/index.vue'
|
||||
import { defineGetter, makeScroll } from '@element-plus/test-utils'
|
||||
|
||||
let clientHeightRestore = null
|
||||
|
||||
const _mount = (template: string) => mount({
|
||||
components: {
|
||||
'el-affix': Affix,
|
||||
},
|
||||
template,
|
||||
}, { attachTo: document.body })
|
||||
|
||||
const AXIOM = 'Rem is the best girl'
|
||||
|
||||
beforeAll(() => {
|
||||
clientHeightRestore = defineGetter(window.HTMLElement.prototype, 'clientHeight', 1000, 0)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
clientHeightRestore()
|
||||
})
|
||||
|
||||
describe('Affix.vue', () => {
|
||||
test('render test', async () => {
|
||||
const wrapper = _mount(`
|
||||
<el-affix>${AXIOM}</el-affix>
|
||||
`)
|
||||
expect(wrapper.text()).toEqual(AXIOM)
|
||||
const mockAffixRect = jest.spyOn(wrapper.find('.el-affix').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -100,
|
||||
bottom: -80,
|
||||
} as DOMRect)
|
||||
const mockDocumentRect = jest.spyOn(document.documentElement, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 200,
|
||||
width: 1000,
|
||||
top: 0,
|
||||
bottom: 200,
|
||||
} as DOMRect)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(false)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 200)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(true)
|
||||
mockAffixRect.mockRestore()
|
||||
mockDocumentRect.mockRestore()
|
||||
})
|
||||
|
||||
test('should render offset props', async () => {
|
||||
const wrapper = _mount(`
|
||||
<el-affix :offset="30">${AXIOM}</el-affix>
|
||||
`)
|
||||
const mockAffixRect = jest.spyOn(wrapper.find('.el-affix').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -100,
|
||||
bottom: -80,
|
||||
} as DOMRect)
|
||||
const mockDocumentRect = jest.spyOn(document.documentElement, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 200,
|
||||
width: 1000,
|
||||
top: 0,
|
||||
bottom: 200,
|
||||
} as DOMRect)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 200)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(true)
|
||||
expect(wrapper.find('.el-affix--fixed').attributes('style')).toContain('top: 30px;')
|
||||
mockAffixRect.mockRestore()
|
||||
mockDocumentRect.mockRestore()
|
||||
})
|
||||
|
||||
test('should render position props', async () => {
|
||||
const wrapper = _mount(`
|
||||
<el-affix position="bottom" :offset="20">${AXIOM}</el-affix>
|
||||
`)
|
||||
|
||||
const mockAffixRect = jest.spyOn(wrapper.find('.el-affix').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: 2000,
|
||||
bottom: 2040,
|
||||
} as DOMRect)
|
||||
const mockDocumentRect = jest.spyOn(document.documentElement, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 200,
|
||||
width: 1000,
|
||||
top: 0,
|
||||
bottom: 200,
|
||||
} as DOMRect)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 0)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(true)
|
||||
expect(wrapper.find('.el-affix--fixed').attributes('style')).toContain('bottom: 20px;')
|
||||
mockAffixRect.mockRestore()
|
||||
mockDocumentRect.mockRestore()
|
||||
})
|
||||
|
||||
test('should render target props', async () => {
|
||||
const wrapper = _mount(`
|
||||
<div class="target" style="height: 200px">
|
||||
<el-affix target=".target">${AXIOM}</el-affix>
|
||||
</div>
|
||||
<div style="height: 1000px"></div>
|
||||
`)
|
||||
|
||||
const mockAffixRect = jest.spyOn(wrapper.find('.el-affix').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -100,
|
||||
bottom: -60,
|
||||
} as DOMRect)
|
||||
const mockTargetRect = jest.spyOn(wrapper.find('.target').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 200,
|
||||
width: 1000,
|
||||
top: -100,
|
||||
bottom: 100,
|
||||
} as DOMRect)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 100)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(true)
|
||||
mockAffixRect.mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -300,
|
||||
bottom: -260,
|
||||
} as DOMRect)
|
||||
mockTargetRect.mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -300,
|
||||
bottom: -260,
|
||||
} as DOMRect)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 300)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(false)
|
||||
mockAffixRect.mockRestore()
|
||||
mockTargetRect.mockRestore()
|
||||
})
|
||||
|
||||
test('should render z-index props', async () => {
|
||||
const wrapper = _mount(`
|
||||
<el-affix :z-index="1000">${AXIOM}</el-affix>
|
||||
`)
|
||||
const mockAffixRect = jest.spyOn(wrapper.find('.el-affix').element, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 40,
|
||||
width: 1000,
|
||||
top: -100,
|
||||
bottom: -80,
|
||||
} as DOMRect)
|
||||
const mockDocumentRect = jest.spyOn(document.documentElement, 'getBoundingClientRect').mockReturnValue({
|
||||
height: 200,
|
||||
width: 1000,
|
||||
top: 0,
|
||||
bottom: 200,
|
||||
} as DOMRect)
|
||||
await makeScroll(document.documentElement, 'scrollTop', 200)
|
||||
expect(wrapper.find('.el-affix--fixed').exists()).toBe(true)
|
||||
expect(wrapper.find('.el-affix--fixed').attributes('style')).toContain('z-index: 1000;')
|
||||
mockAffixRect.mockRestore()
|
||||
mockDocumentRect.mockRestore()
|
||||
})
|
||||
})
|
11
packages/affix/index.ts
Normal file
11
packages/affix/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { App } from 'vue'
|
||||
import type { SFCWithInstall } from '@element-plus/utils/types'
|
||||
import Affix from './src/index.vue'
|
||||
|
||||
Affix.install = (app: App): void => {
|
||||
app.component(Affix.name, Affix)
|
||||
}
|
||||
|
||||
const _Affix: SFCWithInstall<typeof Affix> = Affix
|
||||
|
||||
export default _Affix
|
12
packages/affix/package.json
Normal file
12
packages/affix/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@element-plus/affix",
|
||||
"version": "0.0.0",
|
||||
"main": "dist/index.js",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/test-utils": "^2.0.0-beta.3"
|
||||
}
|
||||
}
|
141
packages/affix/src/index.vue
Normal file
141
packages/affix/src/index.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div ref="root" class="el-affix" :style="rootStyle">
|
||||
<div :class="{'el-affix--fixed': state.fixed}" :style="affixStyle">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onBeforeUnmount, onMounted, PropType, reactive, ref, watch } from 'vue'
|
||||
import { getScrollContainer, off, on } from '@element-plus/utils/dom'
|
||||
import { addResizeListener, removeResizeListener } from '@element-plus/utils/resize-event'
|
||||
|
||||
type Position = 'top' | 'bottom'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ElAffix',
|
||||
props: {
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
offset: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
position: {
|
||||
type: String as PropType<Position>,
|
||||
default: 'top',
|
||||
},
|
||||
},
|
||||
emits: ['scroll', 'change'],
|
||||
setup(props, { emit }) {
|
||||
const target = ref(null)
|
||||
const root = ref(null)
|
||||
const scrollContainer = ref(null)
|
||||
|
||||
const state = reactive({
|
||||
fixed: false,
|
||||
height: 0, // height of root
|
||||
width: 0, // width of root
|
||||
scrollTop: 0, // scrollTop of documentElement
|
||||
clientHeight: 0, // clientHeight of documentElement
|
||||
transform: 0,
|
||||
})
|
||||
|
||||
const rootStyle = computed(() => {
|
||||
return {
|
||||
height: state.fixed ? `${state.height}px` : '',
|
||||
width: state.fixed ? `${state.width}px` : '',
|
||||
}
|
||||
})
|
||||
|
||||
const affixStyle = computed(() => {
|
||||
if (!state.fixed) {
|
||||
return
|
||||
}
|
||||
const offset = props.offset ? `${props.offset}px` : 0
|
||||
const transform = state.transform ? `translateY(${state.transform}px)` : ''
|
||||
|
||||
return {
|
||||
height: `${state.height}px`,
|
||||
width: `${state.width}px`,
|
||||
top: props.position === 'top' ? offset : '',
|
||||
bottom: props.position === 'bottom' ? offset : '',
|
||||
transform: transform,
|
||||
zIndex: props.zIndex,
|
||||
}
|
||||
})
|
||||
|
||||
const updateState = () => {
|
||||
const rootRect = root.value.getBoundingClientRect()
|
||||
const targetRect = target.value.getBoundingClientRect()
|
||||
state.height = rootRect.height
|
||||
state.width = rootRect.width
|
||||
state.scrollTop = scrollContainer.value === window ? document.documentElement.scrollTop : scrollContainer.value.scrollTop
|
||||
state.clientHeight = document.documentElement.clientHeight
|
||||
|
||||
if (props.position === 'top') {
|
||||
if (target.value) {
|
||||
const difference = targetRect.bottom - props.offset - state.height
|
||||
state.fixed = props.offset > rootRect.top && targetRect.bottom > 0
|
||||
state.transform = difference < 0 ? difference : 0
|
||||
} else {
|
||||
state.fixed = props.offset > rootRect.top
|
||||
}
|
||||
} else {
|
||||
if (target.value) {
|
||||
const difference = state.clientHeight - targetRect.top - props.offset - state.height
|
||||
state.fixed = state.clientHeight - props.offset < rootRect.bottom && state.clientHeight > targetRect.top
|
||||
state.transform = difference < 0 ? -difference : 0
|
||||
} else {
|
||||
state.fixed = state.clientHeight - props.offset < rootRect.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onScroll = () => {
|
||||
updateState()
|
||||
|
||||
emit('scroll', {
|
||||
scrollTop: state.scrollTop,
|
||||
fixed: state.fixed,
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => state.fixed, () => {
|
||||
emit('change', state.fixed)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.target) {
|
||||
target.value = document.querySelector(props.target)
|
||||
if (!target.value) {
|
||||
throw new Error(`target is not existed: ${props.target}`)
|
||||
}
|
||||
} else {
|
||||
target.value = document.documentElement
|
||||
}
|
||||
scrollContainer.value = getScrollContainer(root.value)
|
||||
on(scrollContainer.value, 'scroll', onScroll)
|
||||
addResizeListener(root.value, updateState)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
off(scrollContainer.value, 'scroll', onScroll)
|
||||
removeResizeListener(root.value, updateState)
|
||||
})
|
||||
|
||||
return {
|
||||
root,
|
||||
state,
|
||||
rootStyle,
|
||||
affixStyle,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
@ -1,4 +1,5 @@
|
||||
import type { App } from 'vue'
|
||||
import ElAffix from '@element-plus/affix'
|
||||
import ElAlert from '@element-plus/alert'
|
||||
import ElAside from '@element-plus/aside'
|
||||
import ElAutocomplete from '@element-plus/autocomplete'
|
||||
@ -92,19 +93,20 @@ import { use } from '@element-plus/locale'
|
||||
// if you encountered problems alike "Can't resolve './version'"
|
||||
// please run `yarn bootstrap` first
|
||||
import { version as version_ } from './version'
|
||||
import { setConfig } from '@element-plus/utils/config'
|
||||
import type { InstallOptions } from '@element-plus/utils/config'
|
||||
import { setConfig } from '@element-plus/utils/config'
|
||||
|
||||
const version = version_ // version_ to fix tsc issue
|
||||
|
||||
const locale = use
|
||||
|
||||
const defaultInstallOpt: InstallOptions = {
|
||||
const defaultInstallOpt: InstallOptions = {
|
||||
size: '' as ComponentSize,
|
||||
zIndex: 2000,
|
||||
}
|
||||
|
||||
const components = [
|
||||
ElAffix,
|
||||
ElAlert,
|
||||
ElAside,
|
||||
ElAutocomplete,
|
||||
@ -215,6 +217,7 @@ const install = (app: App, opt: InstallOptions): void => {
|
||||
}
|
||||
|
||||
export {
|
||||
ElAffix,
|
||||
ElAlert,
|
||||
ElAside,
|
||||
ElAutocomplete,
|
||||
|
7
packages/theme-chalk/src/affix.scss
Normal file
7
packages/theme-chalk/src/affix.scss
Normal file
@ -0,0 +1,7 @@
|
||||
@import "mixins/mixins";
|
||||
|
||||
@include b(affix) {
|
||||
@include m(fixed) {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
@ -85,3 +85,4 @@
|
||||
@import "./skeleton.scss";
|
||||
@import "./skeleton-item.scss";
|
||||
@import "./empty.scss";
|
||||
@import "./affix.scss";
|
||||
|
8
website/demo-styles/affix.scss
Normal file
8
website/demo-styles/affix.scss
Normal file
@ -0,0 +1,8 @@
|
||||
.demo-block.demo-affix {
|
||||
.affix-container {
|
||||
text-align: center;
|
||||
height: 400px;
|
||||
border-radius: 4px;
|
||||
background: #ECF5FF;
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
@import "./affix.scss";
|
||||
@import "./alert.scss";
|
||||
@import "./badge.scss";
|
||||
@import "./border.scss";
|
||||
|
55
website/docs/en-US/affix.md
Normal file
55
website/docs/en-US/affix.md
Normal file
@ -0,0 +1,55 @@
|
||||
## Affix
|
||||
|
||||
Fix the element to a specific visible area.
|
||||
|
||||
### Basic usage
|
||||
|
||||
Affix is fixed at the top of the page by default.
|
||||
|
||||
:::demo You can set `offset` attribute to change the offset top,the default value is 0。
|
||||
```html
|
||||
<el-affix :offset="120">
|
||||
<el-button type="primary">Offset top 120px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Target container
|
||||
|
||||
You can set `target` attribute to keep the affix in the container at all times. It will be hidden if out of range.
|
||||
|
||||
:::demo Please notice that the container avoid having scrollbar.
|
||||
```html
|
||||
<div class="affix-container">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<el-button type="primary">Target container</el-button>
|
||||
</el-affix>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### Fixed position
|
||||
|
||||
The affix component provides two fixed positions: `top` and `bottom`.
|
||||
|
||||
:::demo You can set `position` attribute to change the fixed position, the default value is `top`.
|
||||
```html
|
||||
<el-affix position="bottom" :offset="20">
|
||||
<el-button type="primary">Offset bottom 20px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| offset | offset distance | number | — | 0 |
|
||||
| position | position of affix | string | top / bottom | top |
|
||||
| target | target container (CSS selector) | string | — | — |
|
||||
| z-index | z-index of affix | number | — | 100 |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|---------- |-------- |---------- |
|
||||
| change | triggers when fixed state changed | (value: boolean) |
|
||||
| scroll | triggers when scrolling | scroll top and fixed state |
|
55
website/docs/es/affix.md
Normal file
55
website/docs/es/affix.md
Normal file
@ -0,0 +1,55 @@
|
||||
## Affix
|
||||
|
||||
Fix the element to a specific visible area.
|
||||
|
||||
### Basic usage
|
||||
|
||||
Affix is fixed at the top of the page by default.
|
||||
|
||||
:::demo You can set `offset` attribute to change the offset top,the default value is 0。
|
||||
```html
|
||||
<el-affix :offset="120">
|
||||
<el-button type="primary">Offset top 120px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Target container
|
||||
|
||||
You can set `target` attribute to keep the affix in the container at all times. It will be hidden if out of range.
|
||||
|
||||
:::demo Please notice that the container avoid having scrollbar.
|
||||
```html
|
||||
<div class="affix-container">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<el-button type="primary">Target container</el-button>
|
||||
</el-affix>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### Fixed position
|
||||
|
||||
The affix component provides two fixed positions: `top` and `bottom`.
|
||||
|
||||
:::demo You can set `position` attribute to change the fixed position, the default value is `top`.
|
||||
```html
|
||||
<el-affix position="bottom" :offset="20">
|
||||
<el-button type="primary">Offset bottom 20px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| offset | offset distance | number | — | 0 |
|
||||
| position | position of affix | string | top / bottom | top |
|
||||
| target | target container (CSS selector) | string | — | — |
|
||||
| z-index | z-index of affix | number | — | 100 |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|---------- |-------- |---------- |
|
||||
| change | triggers when fixed state changed | (value: boolean) |
|
||||
| scroll | triggers when scrolling | scroll top and fixed state |
|
55
website/docs/fr-FR/affix.md
Normal file
55
website/docs/fr-FR/affix.md
Normal file
@ -0,0 +1,55 @@
|
||||
## Affix
|
||||
|
||||
Fix the element to a specific visible area.
|
||||
|
||||
### Basic usage
|
||||
|
||||
Affix is fixed at the top of the page by default.
|
||||
|
||||
:::demo You can set `offset` attribute to change the offset top,the default value is 0。
|
||||
```html
|
||||
<el-affix :offset="120">
|
||||
<el-button type="primary">Offset top 120px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Target container
|
||||
|
||||
You can set `target` attribute to keep the affix in the container at all times. It will be hidden if out of range.
|
||||
|
||||
:::demo Please notice that the container avoid having scrollbar.
|
||||
```html
|
||||
<div class="affix-container">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<el-button type="primary">Target container</el-button>
|
||||
</el-affix>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### Fixed position
|
||||
|
||||
The affix component provides two fixed positions: `top` and `bottom`.
|
||||
|
||||
:::demo You can set `position` attribute to change the fixed position, the default value is `top`.
|
||||
```html
|
||||
<el-affix position="bottom" :offset="20">
|
||||
<el-button type="primary">Offset bottom 20px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| offset | offset distance | number | — | 0 |
|
||||
| position | position of affix | string | top / bottom | top |
|
||||
| target | target container (CSS selector) | string | — | — |
|
||||
| z-index | z-index of affix | number | — | 100 |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|---------- |-------- |---------- |
|
||||
| change | triggers when fixed state changed | (value: boolean) |
|
||||
| scroll | triggers when scrolling | scroll top and fixed state |
|
55
website/docs/jp/affix.md
Normal file
55
website/docs/jp/affix.md
Normal file
@ -0,0 +1,55 @@
|
||||
## Affix
|
||||
|
||||
Fix the element to a specific visible area.
|
||||
|
||||
### Basic usage
|
||||
|
||||
Affix is fixed at the top of the page by default.
|
||||
|
||||
:::demo You can set `offset` attribute to change the offset top,the default value is 0。
|
||||
```html
|
||||
<el-affix :offset="120">
|
||||
<el-button type="primary">Offset top 120px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Target container
|
||||
|
||||
You can set `target` attribute to keep the affix in the container at all times. It will be hidden if out of range.
|
||||
|
||||
:::demo Please notice that the container avoid having scrollbar.
|
||||
```html
|
||||
<div class="affix-container">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<el-button type="primary">Target container</el-button>
|
||||
</el-affix>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### Fixed position
|
||||
|
||||
The affix component provides two fixed positions: `top` and `bottom`.
|
||||
|
||||
:::demo You can set `position` attribute to change the fixed position, the default value is `top`.
|
||||
```html
|
||||
<el-affix position="bottom" :offset="20">
|
||||
<el-button type="primary">Offset bottom 20px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| offset | offset distance | number | — | 0 |
|
||||
| position | position of affix | string | top / bottom | top |
|
||||
| target | target container (CSS selector) | string | — | — |
|
||||
| z-index | z-index of affix | number | — | 100 |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|---------- |-------- |---------- |
|
||||
| change | triggers when fixed state changed | (value: boolean) |
|
||||
| scroll | triggers when scrolling | scroll top and fixed state |
|
55
website/docs/zh-CN/affix.md
Normal file
55
website/docs/zh-CN/affix.md
Normal file
@ -0,0 +1,55 @@
|
||||
## Affix 固钉
|
||||
|
||||
将页面元素固定在特定可视区域。
|
||||
|
||||
### 基本用法
|
||||
|
||||
固钉默认固定在页面顶部。
|
||||
|
||||
:::demo 通过设置 `offset` 属性来改变吸顶距离,默认值为 0。
|
||||
```html
|
||||
<el-affix :offset="120">
|
||||
<el-button type="primary">距离顶部 120px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### 指定容器
|
||||
|
||||
通过设置 `target` 属性,让固钉始终保持在容器内,超过范围则隐藏。
|
||||
|
||||
:::demo 请注意容器避免出现滚动条。
|
||||
```html
|
||||
<div class="affix-container">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<el-button type="primary">指定容器</el-button>
|
||||
</el-affix>
|
||||
</div>
|
||||
```
|
||||
:::
|
||||
|
||||
### 固定位置
|
||||
|
||||
Affix 组件提供了两个固定位置:`top` 和 `bottom`。
|
||||
|
||||
:::demo 通过设置 `position` 属性来改变固定位置,默认值为 `top` 。
|
||||
```html
|
||||
<el-affix position="bottom" :offset="20">
|
||||
<el-button type="primary">距离底部 20px</el-button>
|
||||
</el-affix>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| offset | 偏移距离 | number | — | 0 |
|
||||
| position | 固钉位置 | string | top / bottom | top |
|
||||
| target | 指定容器(CSS 选择器) | string | — | — |
|
||||
| z-index | 固钉层级 | number | — | 100 |
|
||||
|
||||
### Events
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|---------- |-------- |---------- |
|
||||
| change | 固钉状态改变时触发的事件 | (value: boolean) |
|
||||
| scroll | 滚动时触发的事件 | 滚动距离和固钉状态 |
|
@ -227,6 +227,10 @@
|
||||
{
|
||||
"groupName": "Navigation",
|
||||
"list": [
|
||||
{
|
||||
"path": "/affix",
|
||||
"title": "Affix 固钉"
|
||||
},
|
||||
{
|
||||
"path": "/menu",
|
||||
"title": "NavMenu 导航菜单"
|
||||
@ -541,6 +545,10 @@
|
||||
{
|
||||
"groupName": "Navigation",
|
||||
"list": [
|
||||
{
|
||||
"path": "/affix",
|
||||
"title": "Affix"
|
||||
},
|
||||
{
|
||||
"path": "/menu",
|
||||
"title": "NavMenu"
|
||||
@ -859,6 +867,10 @@
|
||||
{
|
||||
"groupName": "Navigation",
|
||||
"list": [
|
||||
{
|
||||
"path": "/affix",
|
||||
"title": "Affix"
|
||||
},
|
||||
{
|
||||
"path": "/menu",
|
||||
"title": "NavMenu"
|
||||
@ -1177,6 +1189,10 @@
|
||||
{
|
||||
"groupName": "Navigation",
|
||||
"list": [
|
||||
{
|
||||
"path": "/affix",
|
||||
"title": "Affix"
|
||||
},
|
||||
{
|
||||
"path": "/menu",
|
||||
"title": "NavMenu"
|
||||
@ -1495,6 +1511,10 @@
|
||||
{
|
||||
"groupName": "Navigation",
|
||||
"list": [
|
||||
{
|
||||
"path": "/affix",
|
||||
"title": "Affix"
|
||||
},
|
||||
{
|
||||
"path": "/menu",
|
||||
"title": "NavMenu"
|
||||
|
Loading…
Reference in New Issue
Block a user