mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-02-17 13:20:52 +08:00
refactor(checkbox): support vue3
This commit is contained in:
parent
aa61c7c5f6
commit
b460a9f4b8
@ -1,13 +1,13 @@
|
||||
# 基础用法
|
||||
```html
|
||||
<n-checkbox v-model="value">复选框</n-checkbox>
|
||||
<n-checkbox v-model="value"/>
|
||||
<n-checkbox v-model="value" :disabled="disabled">复选框</n-checkbox>
|
||||
<n-checkbox v-model:checked="value">复选框</n-checkbox>
|
||||
<n-checkbox v-model:checked="value"/>
|
||||
<n-checkbox v-model:checked="value" :disabled="disabled">复选框</n-checkbox>
|
||||
<n-button @click="disabled = !disabled" size="small">禁用</n-button>
|
||||
```
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
value: false,
|
||||
disabled: true
|
||||
|
@ -1,11 +1,11 @@
|
||||
# 受控状态
|
||||
```html
|
||||
<n-checkbox :checked="value">复选框</n-checkbox>
|
||||
<n-switch v-model="value"/>
|
||||
<n-switch v-model:value="value"/>
|
||||
```
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
value: false
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
# 事件
|
||||
```html
|
||||
<n-checkbox v-model="value" @change="handleChange" label="事件" />
|
||||
<n-checkbox-group v-model="cities" @change="handleChange">
|
||||
<n-checkbox :checked="checked" @update:checked="handleCheckedChange" label="事件" />
|
||||
<n-checkbox-group :value="cities" @update:value="handleUpdateValue">
|
||||
<n-checkbox value="Beijing" label="北京" />
|
||||
<n-checkbox value="Shanghai" label="上海" />
|
||||
<n-checkbox value="Guangzhou" label="广州" />
|
||||
@ -10,15 +10,21 @@
|
||||
```
|
||||
```js
|
||||
export default {
|
||||
inject: ['message'],
|
||||
data () {
|
||||
return {
|
||||
value: false,
|
||||
checked: false,
|
||||
cities: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (v) {
|
||||
this.$NMessage.info(JSON.stringify(v))
|
||||
handleCheckedChange (checked) {
|
||||
this.checked = checked
|
||||
this.message.info(JSON.stringify(checked))
|
||||
},
|
||||
handleUpdateValue (value) {
|
||||
this.cities = value
|
||||
this.message.info(JSON.stringify(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
# 栅格
|
||||
和栅格一起使用。
|
||||
```html
|
||||
<n-checkbox-group v-model="value">
|
||||
<n-checkbox-group v-model:value="value">
|
||||
<n-row>
|
||||
<n-col :span="12">
|
||||
<n-checkbox value="Prosperity" label="富强" />
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 选项组
|
||||
```html
|
||||
<n-checkbox-group v-model="cities">
|
||||
<n-checkbox-group v-model:value="cities">
|
||||
<n-checkbox value="Beijing" label="北京" />
|
||||
<n-checkbox value="Shanghai" label="上海" />
|
||||
<n-checkbox value="Guangzhou" label="广州" />
|
||||
|
@ -1,8 +1,8 @@
|
||||
# 部分选中
|
||||
```html
|
||||
<n-checkbox v-model="value" :indeterminate="indeterminate">复选框</n-checkbox>
|
||||
<n-checkbox v-model="value" :indeterminate="indeterminate"/>
|
||||
<n-checkbox v-model="value" :indeterminate="indeterminate" disabled/>
|
||||
<n-checkbox v-model:checked="value" :indeterminate="indeterminate">复选框</n-checkbox>
|
||||
<n-checkbox v-model:checked="value" :indeterminate="indeterminate"/>
|
||||
<n-checkbox v-model:checked="value" :indeterminate="indeterminate" disabled/>
|
||||
<n-button @click="value = !value" size="small">选中</n-button>
|
||||
<n-button @click="indeterminate = !indeterminate" size="small">部分选中</n-button>
|
||||
```
|
||||
|
@ -1,5 +1,6 @@
|
||||
# 复选框 Checkbox
|
||||
哟,哟,Check it out。
|
||||
|
||||
## 演示
|
||||
```demo
|
||||
basic
|
||||
@ -9,16 +10,6 @@ indeterminate
|
||||
controlled
|
||||
event
|
||||
```
|
||||
## V-model
|
||||
### Checkbox V-model
|
||||
|Prop|Event|
|
||||
|-|-|
|
||||
|change|checked|
|
||||
|
||||
### Checkbox Group V-model
|
||||
|Prop|Event|
|
||||
|-|-|
|
||||
|change|value|
|
||||
|
||||
## Props
|
||||
### Checkbox Props
|
||||
@ -29,6 +20,7 @@ event
|
||||
|checked|`boolean`|`false`||
|
||||
|disabled|`boolean`|`false`||
|
||||
|label|`string \| function`|`null`|可以是渲染函数|
|
||||
|on-update:checked|`(checked: boolean)`|`undefined`||
|
||||
|
||||
### Checkbox Group Props
|
||||
|名称|类型|默认值|说明|
|
||||
@ -36,6 +28,7 @@ event
|
||||
|theme|`'light' \| 'dark' \| null \| string`|`null`||
|
||||
|value|`Array<string \| number>`|`null`||
|
||||
|disabled|`boolean`|`false`||
|
||||
|on-update:value|`(value: string \| number)`|`undefined`||
|
||||
|
||||
## Slots
|
||||
### Checkbox Slots
|
||||
@ -53,14 +46,3 @@ event
|
||||
|名称|参数|说明|
|
||||
|-|-|-|
|
||||
|default|`()`||
|
||||
|
||||
## Events
|
||||
### Checkbox Events
|
||||
|名称|参数|说明|
|
||||
|-|-|-|
|
||||
|change|`(checked: boolean)`||
|
||||
|
||||
### Checkbox Group Events
|
||||
|名称|参数|说明|
|
||||
|-|-|-|
|
||||
|change|`(value: string \| number)`||
|
@ -102,7 +102,8 @@ export function onFontReady (callback) {
|
||||
}
|
||||
|
||||
export function useInjectionCollection (injectionName, collectionKey, valueRef) {
|
||||
const injection = inject(injectionName)
|
||||
const injection = inject(injectionName, null)
|
||||
if (injection === null) return
|
||||
if (!(collectionKey in injection)) {
|
||||
injection[collectionKey] = []
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* istanbul ignore file */
|
||||
import NCheckbox from './src/Checkbox.vue'
|
||||
import NCheckboxGroup from './src/CheckboxGroup.vue'
|
||||
import NCheckboxGroup from './src/CheckboxGroup.js'
|
||||
|
||||
NCheckbox.install = function (app, naive) {
|
||||
app.component(naive.componentPrefix + NCheckbox.name, NCheckbox)
|
||||
|
@ -51,17 +51,18 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, inject } from 'vue'
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import asformitem from '../../_mixins/asformitem'
|
||||
import collectable from '../../_mixins/collectable'
|
||||
import simulatedComputed from '../../_mixins/simulatedComputed'
|
||||
import render from '../../_utils/vue/render'
|
||||
import CheckMark from './CheckMark'
|
||||
import LineMark from './LineMark'
|
||||
import NIconSwitchTransition from '../../_transition/IconSwitchTransition'
|
||||
import usecssr from '../../_mixins/usecssr'
|
||||
import styles from './styles'
|
||||
import { useMemo } from '../../_utils/composition'
|
||||
import { warn } from '../../_utils/naive/warn'
|
||||
|
||||
export default {
|
||||
name: 'Checkbox',
|
||||
@ -79,14 +80,9 @@ export default {
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable,
|
||||
asformitem(
|
||||
{
|
||||
change: 'change',
|
||||
blur: 'blur',
|
||||
focus: 'focus'
|
||||
},
|
||||
'medium',
|
||||
function () {
|
||||
asformitem({
|
||||
defaultSize: 'medium',
|
||||
syntheticSize () {
|
||||
const size = this.size
|
||||
if (size) return size
|
||||
const NCheckboxGroup = this.NCheckboxGroup
|
||||
@ -103,25 +99,9 @@ export default {
|
||||
}
|
||||
return 'medium'
|
||||
}
|
||||
),
|
||||
collectable('NCheckboxGroup', 'collectedCheckboxValues'),
|
||||
simulatedComputed({
|
||||
renderSafeChecked: {
|
||||
default: false,
|
||||
get () {
|
||||
return this.syntheticChecked
|
||||
},
|
||||
deps: [
|
||||
'syntheticChecked'
|
||||
]
|
||||
}
|
||||
}),
|
||||
usecssr(styles)
|
||||
],
|
||||
model: {
|
||||
prop: 'checked',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
validator (value) {
|
||||
@ -145,50 +125,81 @@ export default {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Function],
|
||||
default: null
|
||||
},
|
||||
onClick: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:checked': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// private
|
||||
tableHeader: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Function],
|
||||
default: null
|
||||
// deprecated
|
||||
onChange: {
|
||||
validator () {
|
||||
warn('checkbox', '`on-change` is deprecated, please use `on-update:checked` instead.')
|
||||
return true
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const NCheckboxGroup = inject('NCheckboxGroup', null)
|
||||
const syntheticCheckedRef = computed(() => {
|
||||
if (NCheckboxGroup) {
|
||||
const groupValueSet = NCheckboxGroup.valueSet
|
||||
if (groupValueSet) {
|
||||
return groupValueSet.has(props.value)
|
||||
}
|
||||
return false
|
||||
} else {
|
||||
return props.checked
|
||||
}
|
||||
})
|
||||
return {
|
||||
renderSafeChecked: useMemo(() => syntheticCheckedRef.value, [
|
||||
syntheticCheckedRef
|
||||
])
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
syntheticDisabled () {
|
||||
if (this.disabled || (this.NCheckboxGroup && this.NCheckboxGroup.disabled)) return true
|
||||
return false
|
||||
},
|
||||
syntheticChecked () {
|
||||
if (this.NCheckboxGroup) {
|
||||
const checkboxGroupValueSet = this.NCheckboxGroup.valueAsSet
|
||||
if (checkboxGroupValueSet) {
|
||||
return checkboxGroupValueSet.has(this.value)
|
||||
}
|
||||
return false
|
||||
} else {
|
||||
return this.checked
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerValue (value = undefined, oldValue = undefined) {
|
||||
if (this.NCheckboxGroup) {
|
||||
const values = new Set(this.NCheckboxGroup.collectedCheckboxValues)
|
||||
if (oldValue !== undefined) values.delete(oldValue)
|
||||
if (value !== undefined) values.add(value)
|
||||
this.NCheckboxGroup.collectedCheckboxValues = Array.from(values)
|
||||
}
|
||||
},
|
||||
toggle () {
|
||||
if (this.NCheckboxGroup) {
|
||||
this.NCheckboxGroup.toggleCheckbox(!this.syntheticChecked, this.value)
|
||||
this.NCheckboxGroup.toggleCheckbox(!this.renderSafeChecked, this.value)
|
||||
} else {
|
||||
this.$emit('change', !this.syntheticChecked, this.syntheticChecked)
|
||||
const {
|
||||
onChange,
|
||||
'onUpdate:checked': onUpdateChecked,
|
||||
__triggerFormInput,
|
||||
__triggerFormChange
|
||||
} = this
|
||||
const nextChecked = !this.renderSafeChecked
|
||||
if (onUpdateChecked) onUpdateChecked(nextChecked)
|
||||
if (onChange) onChange(nextChecked) // deprecated
|
||||
__triggerFormInput()
|
||||
__triggerFormChange()
|
||||
}
|
||||
},
|
||||
handleClick (e) {
|
||||
this.$emit('click', e)
|
||||
const {
|
||||
onClick
|
||||
} = this
|
||||
if (onClick) onClick(e)
|
||||
if (!this.syntheticDisabled) {
|
||||
this.toggle()
|
||||
}
|
||||
|
104
src/checkbox/src/CheckboxGroup.js
Normal file
104
src/checkbox/src/CheckboxGroup.js
Normal file
@ -0,0 +1,104 @@
|
||||
import { h } from 'vue'
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import asformitem from '../../_mixins/asformitem'
|
||||
import { getSlot } from '../../_utils/vue'
|
||||
import { warn } from '../../_utils/naive/warn'
|
||||
|
||||
export default {
|
||||
name: 'CheckboxGroup',
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable,
|
||||
asformitem()
|
||||
],
|
||||
provide () {
|
||||
return {
|
||||
NCheckboxGroup: this
|
||||
}
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
validator (value) {
|
||||
return ['small', 'medium', 'large'].includes(value)
|
||||
},
|
||||
default: null
|
||||
},
|
||||
value: {
|
||||
type: Array,
|
||||
default: null
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:value': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// deprecated
|
||||
onChange: {
|
||||
validator () {
|
||||
if (__DEV__) warn('checkbox-group', '`on-change` is deprecated, please use `on-update:value` instead.')
|
||||
return true
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valueSet () {
|
||||
if (Array.isArray(this.value)) return new Set(this.value)
|
||||
return null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleCheckbox (checked, checkboxValue) {
|
||||
const {
|
||||
onChange,
|
||||
'onUpdate:value': onUpdateValue,
|
||||
__triggerFormInput,
|
||||
__triggerFormChange
|
||||
} = this
|
||||
if (Array.isArray(this.value)) {
|
||||
let groupValue = Array.from(this.value)
|
||||
const index = groupValue.findIndex(value => value === checkboxValue)
|
||||
if (checked) {
|
||||
if (!~index) {
|
||||
groupValue.push(checkboxValue)
|
||||
if (onUpdateValue) onUpdateValue(groupValue)
|
||||
__triggerFormInput()
|
||||
__triggerFormChange()
|
||||
// deprecated
|
||||
if (onChange) onChange(groupValue)
|
||||
}
|
||||
} else {
|
||||
if (~index) {
|
||||
groupValue.splice(index, 1)
|
||||
if (onUpdateValue) onUpdateValue(groupValue)
|
||||
if (onChange) onChange(groupValue) // deprecated
|
||||
__triggerFormInput()
|
||||
__triggerFormChange()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (checked) {
|
||||
if (onUpdateValue) onUpdateValue([checkboxValue])
|
||||
if (onChange) onChange([checkboxValue]) // deprecated
|
||||
__triggerFormInput()
|
||||
__triggerFormChange()
|
||||
} else {
|
||||
if (onUpdateValue) onUpdateValue([])
|
||||
if (onChange) onChange([]) // deprecated
|
||||
__triggerFormInput()
|
||||
__triggerFormChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
render () {
|
||||
return h('div', {
|
||||
class: 'n-checkbox-group'
|
||||
}, getSlot(this))
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
<script>
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import asformitem from '../../_mixins/asformitem'
|
||||
import getDefaultSlot from '../../_utils/vue/getDefaultSlot'
|
||||
|
||||
export default {
|
||||
name: 'CheckboxGroup',
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable,
|
||||
asformitem()
|
||||
],
|
||||
provide () {
|
||||
return {
|
||||
NFormItem: null,
|
||||
NCheckboxGroup: this
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
validator (value) {
|
||||
return ['small', 'medium', 'large'].includes(value)
|
||||
},
|
||||
default: null
|
||||
},
|
||||
value: {
|
||||
type: Array,
|
||||
default: null
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
collectedCheckboxValues: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valueAsSet () {
|
||||
if (Array.isArray(this.value)) return new Set(this.value)
|
||||
return null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleCheckbox (checked, checkboxValue) {
|
||||
if (Array.isArray(this.value)) {
|
||||
let groupValue = Array.from(this.value)
|
||||
const collectedCheckboxValues = new Set(this.collectedCheckboxValues)
|
||||
groupValue = groupValue.filter(value => collectedCheckboxValues.has(value))
|
||||
const index = groupValue.findIndex(value => value === checkboxValue)
|
||||
if (checked) {
|
||||
if (!~index) {
|
||||
groupValue.push(checkboxValue)
|
||||
this.$emit('change', groupValue)
|
||||
}
|
||||
} else {
|
||||
if (~index) {
|
||||
groupValue.splice(index, 1)
|
||||
this.$emit('change', groupValue)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (checked) {
|
||||
this.$emit('change', [checkboxValue])
|
||||
} else {
|
||||
this.$emit('change', [])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
return h('div', {
|
||||
staticClass: 'n-checkbox-group'
|
||||
}, getDefaultSlot(this))
|
||||
}
|
||||
}
|
||||
</script>
|
@ -88,11 +88,22 @@ export default {
|
||||
theme: {
|
||||
validator: createValidator(['string']),
|
||||
default: null
|
||||
},
|
||||
onClick: {
|
||||
validator: createValidator(['object']),
|
||||
default: undefined
|
||||
},
|
||||
onChange: {
|
||||
validator: createValidator(['object']),
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick (e) {
|
||||
this.$emit('click', e)
|
||||
const {
|
||||
onClick
|
||||
} = this
|
||||
if (onClick) onClick(e)
|
||||
if (!this.disabled) {
|
||||
this.toggle()
|
||||
}
|
||||
@ -103,7 +114,10 @@ export default {
|
||||
}
|
||||
},
|
||||
toggle () {
|
||||
this.$emit('change', !this.checked, this.checked)
|
||||
const {
|
||||
onChange
|
||||
} = this
|
||||
if (onChange) onChange(!this.checked)
|
||||
},
|
||||
handleKeyDownSpace (e) {
|
||||
e.preventDefault()
|
||||
|
@ -59,7 +59,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NCheckboxGroup from '../../../checkbox/src/CheckboxGroup'
|
||||
import NCheckboxGroup from '../../../checkbox/src/CheckboxGroup.js'
|
||||
import NCheckbox from '../../../checkbox/src/Checkbox'
|
||||
import NRadioGroup from '../../../radio/src/RadioGroup'
|
||||
import NRadio from '../../../radio/src/Radio'
|
||||
|
Loading…
Reference in New Issue
Block a user