mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-11-27 04:09:51 +08:00
refactor(collapse): support vue3
This commit is contained in:
parent
cf33f6c586
commit
c016bad589
@ -1,7 +1,7 @@
|
||||
# 手风琴
|
||||
像一个手风琴
|
||||
```html
|
||||
<n-collapse v-model="activeNames" accordion>
|
||||
<n-collapse v-model:expandedNames="activeNames" accordion>
|
||||
<n-collapse-item title="动态类型" name="1">
|
||||
<div>Python</div>
|
||||
</n-collapse-item>
|
||||
|
@ -2,7 +2,7 @@
|
||||
使用 `arrow-placement` 来设定箭头的位置。
|
||||
```html
|
||||
<n-collapse
|
||||
v-model="activeNames"
|
||||
v-model:expandedNames="activeNames"
|
||||
arrow-placement="right"
|
||||
>
|
||||
<n-collapse-item title="青铜" name="1">
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 基础
|
||||
```html
|
||||
<n-collapse v-model="activeNames">
|
||||
<n-collapse v-model:expandedNames="activeNames">
|
||||
<n-collapse-item title="青铜" name="1">
|
||||
<div>可以</div>
|
||||
</n-collapse-item>
|
||||
|
@ -1,9 +1,9 @@
|
||||
# 显示指令
|
||||
设定 `display-directive` 为 `if` 或 `show` 来控制 `n-collapse-item` 里面的 DOM 是否保持。
|
||||
```html
|
||||
<n-collapse v-model="activeNames" display-directive="show">
|
||||
<n-collapse v-model:expandedNames="activeNames" display-directive="show">
|
||||
<n-collapse-item title="绿灯" name="1">
|
||||
<n-collapse v-model="activeNames2">
|
||||
<n-collapse v-model:expandedNames="activeNames2">
|
||||
<n-collapse-item title="常亮" name="1">
|
||||
<div>通过</div>
|
||||
</n-collapse-item>
|
||||
|
@ -9,11 +9,6 @@ nested
|
||||
display-directive
|
||||
item-header-click
|
||||
```
|
||||
## V-model
|
||||
|Prop|Event|
|
||||
|-|-|
|
||||
|expanded-names|expanded-names-change|
|
||||
|
||||
## Props
|
||||
### Collapse Props
|
||||
|名称|类型|默认值|说明|
|
||||
@ -23,6 +18,8 @@ item-header-click
|
||||
|display-directive|`'if' \| 'show'`|`'if'`|内部 `n-collapse-item` 在控制内容是否渲染时使用的指令,`'if'` 对应 `v-if`,`'show'` 对应 `v-show`|
|
||||
|expanded-names|`Array<string \| number>`|`null`||
|
||||
|theme|`'light' \| 'dark' \| null \| string`|`null`||
|
||||
|on-update-expanded-names|`(expandedNames: Array<string>) => any`|`() => {}`||
|
||||
|on-item-header-click|`(data: { name: string, expanded: boolean, event: MouseEvent }) => any`|`() => {}`||
|
||||
|
||||
|
||||
### Collapse Item Props
|
||||
@ -45,9 +42,3 @@ item-header-click
|
||||
|header|`()`||
|
||||
|arrow|`(options: { collapsed: boolean })`||
|
||||
|
||||
## Event
|
||||
### Collapse Event
|
||||
|名称|参数|说明|
|
||||
|-|-|-|
|
||||
|expanded-names-change|`(expandedNames: Array<string>)`||
|
||||
|item-header-click|`(data: { name: string, expanded: boolean, event: MouseEvent })`||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# 点击标题
|
||||
```html
|
||||
<n-collapse
|
||||
v-model="activeNames"
|
||||
v-model:expandedNames="activeNames"
|
||||
@item-header-click="handleItemHeaderClick"
|
||||
>
|
||||
<n-collapse-item name="1">
|
||||
@ -26,6 +26,7 @@
|
||||
```
|
||||
```js
|
||||
export default {
|
||||
inject: ['message'],
|
||||
data () {
|
||||
return {
|
||||
activeNames: []
|
||||
@ -36,7 +37,7 @@ export default {
|
||||
name,
|
||||
expanded
|
||||
}) {
|
||||
this.$NMessage.info(`Name: ${name}, Expanded: ${expanded}`)
|
||||
this.message.info(`Name: ${name}, Expanded: ${expanded}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
# 嵌套
|
||||
可以嵌套。
|
||||
```html
|
||||
<n-collapse v-model="activeNames">
|
||||
<n-collapse v-model:expandedNames="activeNames">
|
||||
<n-collapse-item title="绿灯" name="1">
|
||||
<n-collapse v-model="activeNames2">
|
||||
<n-collapse v-model:expandedNames="activeNames2">
|
||||
<n-collapse-item title="常亮" name="1">
|
||||
<div>通过</div>
|
||||
</n-collapse-item>
|
||||
|
@ -28,8 +28,13 @@ body {
|
||||
max-width: 680px;
|
||||
}
|
||||
|
||||
.api-table .n-table__td:first-child {
|
||||
.api-table .n-table__td:nth-child(1),
|
||||
.api-table .n-table__td:nth-child(2) {
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
font-family: naive-ui-mono, monospace;
|
||||
}
|
||||
|
||||
.api-table .n-text.n-text--code {
|
||||
font-size: 13px;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* istanbul ignore file */
|
||||
import Collapse from './src/Collapse.vue'
|
||||
import Collapse from './src/Collapse.js'
|
||||
import CollapseItem from './src/CollapseItem.vue'
|
||||
|
||||
Collapse.install = function (app, naive) {
|
||||
|
@ -1,8 +1,7 @@
|
||||
<script>
|
||||
import { h, markRaw } from 'vue'
|
||||
import intersection from 'lodash-es/intersection'
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import getDefaultSlot from '../../_utils/vue/getDefaultSlot'
|
||||
import usecssr from '../../_mixins/usecssr'
|
||||
import styles from './styles/index.js'
|
||||
|
||||
@ -18,10 +17,6 @@ export default {
|
||||
themeable,
|
||||
usecssr(styles)
|
||||
],
|
||||
model: {
|
||||
prop: 'expandedNames',
|
||||
event: 'expanded-names-change'
|
||||
},
|
||||
props: {
|
||||
expandedNames: {
|
||||
type: [Array, String],
|
||||
@ -42,50 +37,73 @@ export default {
|
||||
return ['if', 'show'].includes(value)
|
||||
},
|
||||
default: 'if'
|
||||
},
|
||||
onItemHeaderClick: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
},
|
||||
'onUpdate:expandedNames': {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
},
|
||||
// deprecated
|
||||
onExpandedNamesChange: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
setup () {
|
||||
return {
|
||||
collectedItemNames: []
|
||||
collectedItemNames: markRaw([])
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleItem (collapse, name, event) {
|
||||
if (this.accordion) {
|
||||
if (collapse) {
|
||||
this.$emit('expanded-names-change', [name])
|
||||
this.$emit('item-header-click', { name, expanded: true, event })
|
||||
this['onUpdate:expandedNames']([name])
|
||||
|
||||
this.onExpandedNamesChange([name])
|
||||
this.onItemHeaderClick({ name, expanded: true, event })
|
||||
} else {
|
||||
this.$emit('expanded-names-change', [])
|
||||
this.$emit('item-header-click', { name, expanded: false, event })
|
||||
this['onUpdate:expandedNames']([])
|
||||
this.onExpandedNamesChange([])
|
||||
this.onItemHeaderClick({ name, expanded: false, event })
|
||||
}
|
||||
} else {
|
||||
if (!Array.isArray(this.expandedNames)) {
|
||||
this.$emit('expanded-names-change', [name])
|
||||
this.$emit('item-header-click', { name, expanded: true, event })
|
||||
this['onUpdate:expandedNames']([name])
|
||||
this.onExpandedNamesChange([name])
|
||||
this.onItemHeaderClick({ name, expanded: true, event })
|
||||
} else {
|
||||
const activeNames = intersection(this.expandedNames, this.collectedItemNames)
|
||||
const index = activeNames.findIndex(activeName => name === activeName)
|
||||
if (~index) {
|
||||
activeNames.splice(index, 1)
|
||||
this.$emit('expanded-names-change', activeNames)
|
||||
this.$emit('item-header-click', { name, expanded: false, event })
|
||||
this['onUpdate:expandedNames'](activeNames)
|
||||
this.onExpandedNamesChange(activeNames)
|
||||
this.onItemHeaderClick({ name, expanded: false, event })
|
||||
} else {
|
||||
activeNames.push(name)
|
||||
this.$emit('expanded-names-change', activeNames)
|
||||
this.$emit('item-header-click', { name, expanded: true, event })
|
||||
this['onUpdate:expandedNames'](activeNames)
|
||||
this.onExpandedNamesChange(activeNames)
|
||||
this.onItemHeaderClick({ name, expanded: true, event })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
render () {
|
||||
const { syntheticTheme } = this
|
||||
return h('div', {
|
||||
staticClass: 'n-collapse',
|
||||
class: {
|
||||
[`n-${this.syntheticTheme}-theme`]: this.syntheticTheme
|
||||
}
|
||||
}, getDefaultSlot(this))
|
||||
class: [
|
||||
'n-collapse',
|
||||
{
|
||||
[`n-${syntheticTheme}-theme`]: syntheticTheme
|
||||
}
|
||||
]
|
||||
}, {
|
||||
...this.$slots
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
@ -19,7 +19,7 @@
|
||||
<div class="n-collapse-item-arrow">
|
||||
<slot name="arrow" :collapsed="collapsed">
|
||||
<n-icon type="ios-arrow-forward">
|
||||
<ios-arrow-forward />
|
||||
<arrow-icon />
|
||||
</n-icon>
|
||||
</slot>
|
||||
</div>
|
||||
@ -37,19 +37,19 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toRef } from 'vue'
|
||||
import NIcon from '../../icon'
|
||||
import iosArrowForward from '../../_icons/ios-arrow-forward'
|
||||
import collectable from '../../_mixins/collectable'
|
||||
import NCollapseItemContent from './CollapseItemContent'
|
||||
import ArrowIcon from '../../_icons/ios-arrow-forward'
|
||||
import NCollapseItemContent from './CollapseItemContent.js'
|
||||
import { useInjectionCollection } from '../../_utils/composition'
|
||||
|
||||
export default {
|
||||
name: 'CollapseItem',
|
||||
components: {
|
||||
NIcon,
|
||||
NCollapseItemContent,
|
||||
iosArrowForward
|
||||
ArrowIcon
|
||||
},
|
||||
mixins: [collectable('NCollapse', 'collectedItemNames', 'name')],
|
||||
inject: {
|
||||
NCollapse: {
|
||||
default: null
|
||||
@ -71,20 +71,23 @@ export default {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
useInjectionCollection('NCollapse', 'collectedItemNames', toRef(props, 'name'))
|
||||
},
|
||||
computed: {
|
||||
syntheticDisplayDirective () {
|
||||
const displayDirective = this.displayDirective
|
||||
const { displayDirective, NCollapse } = this
|
||||
if (displayDirective !== null) {
|
||||
return this.NCollapse.displayDirective
|
||||
} else {
|
||||
return displayDirective
|
||||
} else {
|
||||
return NCollapse.displayDirective
|
||||
}
|
||||
},
|
||||
arrowPlacement () {
|
||||
return this.NCollapse.arrowPlacement
|
||||
},
|
||||
collapsed () {
|
||||
const NCollapse = this.NCollapse
|
||||
const { NCollapse } = this
|
||||
if (NCollapse && Array.isArray(NCollapse.expandedNames)) {
|
||||
const itemName = this.name
|
||||
return !~NCollapse.expandedNames.findIndex(name => name === itemName)
|
||||
@ -94,9 +97,13 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleClick (e) {
|
||||
const NCollapse = this.NCollapse
|
||||
const { NCollapse } = this
|
||||
if (NCollapse) {
|
||||
NCollapse.toggleItem(this.collapsed, this.name, e)
|
||||
NCollapse.toggleItem(
|
||||
this.collapsed,
|
||||
this.name,
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
src/collapse/src/CollapseItemContent.js
Normal file
43
src/collapse/src/CollapseItemContent.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { h, withDirectives, vShow } from 'vue'
|
||||
import NFadeInHeightExpandTransition from '../../_transition/FadeInHeightExpandTransition'
|
||||
|
||||
export default {
|
||||
name: 'NCollapseItemContent',
|
||||
props: {
|
||||
displayDirective: {
|
||||
validator () {
|
||||
// already validated outside
|
||||
return true
|
||||
},
|
||||
required: true
|
||||
},
|
||||
show: {
|
||||
validator () {
|
||||
// already validated outside
|
||||
return true
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { show, displayDirective } = this
|
||||
const useVShow = displayDirective === 'show'
|
||||
const directives = useVShow ? [
|
||||
[vShow, show]
|
||||
] : []
|
||||
return h(NFadeInHeightExpandTransition, null, {
|
||||
default: () => (useVShow || show) ? withDirectives(
|
||||
h('div', {
|
||||
class: 'n-collapse-item__content-wrapper'
|
||||
}, [
|
||||
h('div', {
|
||||
class: 'n-collapse-item__content-inner'
|
||||
}, {
|
||||
...this.$slots
|
||||
})
|
||||
]),
|
||||
directives
|
||||
) : null
|
||||
})
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<script>
|
||||
import NFadeInHeightExpandTransition from '../../_transition/FadeInHeightExpandTransition'
|
||||
import getDefaultSlot from '../../_utils/vue/getDefaultSlot'
|
||||
|
||||
export default {
|
||||
name: 'NCollapseItemContent',
|
||||
components: {
|
||||
NFadeInHeightExpandTransition
|
||||
},
|
||||
props: {
|
||||
displayDirective: {
|
||||
validator (value) {
|
||||
// already validated outside
|
||||
return true
|
||||
},
|
||||
required: true
|
||||
},
|
||||
show: {
|
||||
validator (value) {
|
||||
// already validated outside
|
||||
return true
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
const defaultSlot = getDefaultSlot(this)
|
||||
const vIf = this.displayDirective === 'if'
|
||||
return h('n-fade-in-height-expand-transition', (vIf && !this.show) ? [] : [
|
||||
h('div', {
|
||||
staticClass: 'n-collapse-item__content-wrapper',
|
||||
directives: [
|
||||
!vIf ? {
|
||||
name: 'show',
|
||||
value: this.show
|
||||
} : null
|
||||
].filter(v => v)
|
||||
}, [
|
||||
h('div', {
|
||||
staticClass: 'n-collapse-item__content-inner'
|
||||
}, defaultSlot)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
6
vue3.md
6
vue3.md
@ -27,7 +27,11 @@ placeable 进行了大调整
|
||||
- [ ] cascader
|
||||
- [ ] checkbox
|
||||
- [ ] code
|
||||
- [ ] collapse
|
||||
- [x] collapse
|
||||
- deprecate
|
||||
- `on-expanded-names-change` => `on-update:expanded-names`
|
||||
- removed
|
||||
- `v-model` => `v-model:expanded-names`
|
||||
- [ ] config-consumer
|
||||
- [ ] config-provider
|
||||
- [ ] confirm
|
||||
|
Loading…
Reference in New Issue
Block a user