perf: input icon grid

pull/398/head
tangjinzhou 2019-01-03 20:51:56 +08:00
parent 4d6627dcd4
commit 0178c35de9
9 changed files with 112 additions and 49 deletions

View File

@ -105,7 +105,7 @@ export default {
getGutter () { getGutter () {
const { gutter } = this const { gutter } = this
if (typeof gutter === 'object') { if (typeof gutter === 'object') {
for (let i = 0; i <= responsiveArray.length; i++) { for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint = responsiveArray[i] const breakpoint = responsiveArray[i]
if (this.screens[breakpoint] && gutter[breakpoint] !== undefined) { if (this.screens[breakpoint] && gutter[breakpoint] !== undefined) {
return gutter[breakpoint] return gutter[breakpoint]

View File

@ -112,7 +112,7 @@ const Icon = {
` the 'theme' prop '${theme}' will be ignored.`) ` the 'theme' prop '${theme}' will be ignored.`)
} }
computedType = withThemeSuffix( computedType = withThemeSuffix(
removeTypeTheme(alias(type)), removeTypeTheme(alias(computedType)),
dangerousTheme || theme || defaultTheme, dangerousTheme || theme || defaultTheme,
) )
innerNode = ( innerNode = (

View File

@ -171,6 +171,8 @@ export default {
'addonAfter', 'addonAfter',
'prefix', 'prefix',
'suffix', 'suffix',
'value',
'defaultValue',
]) ])
const { stateValue, getInputClassName, handleKeyDown, handleChange, $listeners } = this const { stateValue, getInputClassName, handleKeyDown, handleChange, $listeners } = this
const inputProps = { const inputProps = {

View File

@ -1,5 +1,6 @@
import omit from 'omit.js' import omit from 'omit.js'
import ResizeObserver from 'resize-observer-polyfill'
import inputProps from './inputProps' import inputProps from './inputProps'
import calculateNodeHeight from './calculateNodeHeight' import calculateNodeHeight from './calculateNodeHeight'
import hasProp from '../_util/props-util' import hasProp from '../_util/props-util'
@ -47,22 +48,53 @@ export default {
}, },
watch: { watch: {
value (val) { value (val) {
this.$nextTick(() => {
this.resizeOnNextFrame()
})
this.stateValue = fixControlledValue(val) this.stateValue = fixControlledValue(val)
if (this.nextFrameActionId) { },
clearNextFrameAction(this.nextFrameActionId) autosize (val) {
if (!val && this.$refs.textArea) {
this.textareaStyles = omit(this.textareaStyles, ['overflowY'])
} }
this.nextFrameActionId = onNextFrame(this.resizeTextarea)
}, },
}, },
mounted () { mounted () {
this.$nextTick(() => { this.$nextTick(() => {
this.resizeTextarea() this.resizeTextarea()
this.updateResizeObserverHook()
if (this.autoFocus) { if (this.autoFocus) {
this.focus() this.focus()
} }
}) })
}, },
updated () {
this.updateResizeObserverHook()
},
beforeDestroy () {
if (this.resizeObserver) {
this.resizeObserver.disconnect()
}
},
methods: { methods: {
resizeOnNextFrame () {
if (this.nextFrameActionId) {
clearNextFrameAction(this.nextFrameActionId)
}
this.nextFrameActionId = onNextFrame(this.resizeTextarea)
},
// We will update hooks if `autosize` prop change
updateResizeObserverHook () {
if (!this.resizeObserver && this.$props.autosize) {
// Add resize observer
this.resizeObserver = new ResizeObserver(this.resizeOnNextFrame)
this.resizeObserver.observe(this.$refs.textArea)
} else if (this.resizeObserver && !this.$props.autosize) {
// Remove resize observer
this.resizeObserver.disconnect()
this.resizeObserver = null
}
},
handleKeyDown (e) { handleKeyDown (e) {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.$emit('pressEnter', e) this.$emit('pressEnter', e)
@ -91,9 +123,7 @@ export default {
handleTextareaChange (e) { handleTextareaChange (e) {
if (!hasProp(this, 'value')) { if (!hasProp(this, 'value')) {
this.stateValue = e.target.value this.stateValue = e.target.value
this.$nextTick(() => { this.resizeTextarea()
this.resizeTextarea()
})
} else { } else {
this.$forceUpdate() this.$forceUpdate()
} }
@ -126,6 +156,8 @@ export default {
'prefixCls', 'prefixCls',
'autosize', 'autosize',
'type', 'type',
'value',
'defaultValue',
]) ])
const textareaProps = { const textareaProps = {
attrs: { ...otherProps, ...$attrs }, attrs: { ...otherProps, ...$attrs },

View File

@ -5,15 +5,15 @@
*/ */
const HIDDEN_TEXTAREA_STYLE = ` const HIDDEN_TEXTAREA_STYLE = `
min-height:0 !important; min-height:0 !important;
max-height:none !important; max-height:none !important;
height:0 !important; height:0 !important;
visibility:hidden !important; visibility:hidden !important;
overflow:hidden !important; overflow:hidden !important;
position:absolute !important; position:absolute !important;
z-index:-1000 !important; z-index:-1000 !important;
top:0 !important; top:0 !important;
right:0 !important right:0 !important
` `
const SIZING_STYLE = [ const SIZING_STYLE = [
@ -38,11 +38,9 @@ const computedStyleCache = {}
let hiddenTextarea let hiddenTextarea
function calculateNodeStyling (node, useCache = false) { function calculateNodeStyling (node, useCache = false) {
const nodeRef = ( const nodeRef = (node.getAttribute('id') ||
node.getAttribute('id') || node.getAttribute('data-reactid') ||
node.getAttribute('data-reactid') || node.getAttribute('name'))
node.getAttribute('name')
)
if (useCache && computedStyleCache[nodeRef]) { if (useCache && computedStyleCache[nodeRef]) {
return computedStyleCache[nodeRef] return computedStyleCache[nodeRef]
@ -50,25 +48,20 @@ function calculateNodeStyling (node, useCache = false) {
const style = window.getComputedStyle(node) const style = window.getComputedStyle(node)
const boxSizing = ( const boxSizing =
style.getPropertyValue('box-sizing') || style.getPropertyValue('box-sizing') ||
style.getPropertyValue('-moz-box-sizing') || style.getPropertyValue('-moz-box-sizing') ||
style.getPropertyValue('-webkit-box-sizing') style.getPropertyValue('-webkit-box-sizing')
)
const paddingSize = ( const paddingSize =
parseFloat(style.getPropertyValue('padding-bottom')) + parseFloat(style.getPropertyValue('padding-bottom')) +
parseFloat(style.getPropertyValue('padding-top')) parseFloat(style.getPropertyValue('padding-top'))
)
const borderSize = ( const borderSize =
parseFloat(style.getPropertyValue('border-bottom-width')) + parseFloat(style.getPropertyValue('border-bottom-width')) +
parseFloat(style.getPropertyValue('border-top-width')) parseFloat(style.getPropertyValue('border-top-width'))
)
const sizingStyle = SIZING_STYLE const sizingStyle = SIZING_STYLE.map(name => `${name}:${style.getPropertyValue(name)}`).join(';')
.map(name => `${name}:${style.getPropertyValue(name)}`)
.join(';')
const nodeInfo = { const nodeInfo = {
sizingStyle, sizingStyle,
@ -105,10 +98,10 @@ export default function calculateNodeHeight (
// Copy all CSS properties that have an impact on the height of the content in // Copy all CSS properties that have an impact on the height of the content in
// the textbox // the textbox
const { const { paddingSize, borderSize, boxSizing, sizingStyle } = calculateNodeStyling(
paddingSize, borderSize, uiTextNode,
boxSizing, sizingStyle, useCache,
} = calculateNodeStyling(uiTextNode, useCache) )
// Need to have the overflow attribute to hide the scrollbar otherwise // Need to have the overflow attribute to hide the scrollbar otherwise
// text-lines will not calculated properly as the shadow will technically be // text-lines will not calculated properly as the shadow will technically be
@ -116,22 +109,22 @@ export default function calculateNodeHeight (
hiddenTextarea.setAttribute('style', `${sizingStyle};${HIDDEN_TEXTAREA_STYLE}`) hiddenTextarea.setAttribute('style', `${sizingStyle};${HIDDEN_TEXTAREA_STYLE}`)
hiddenTextarea.value = uiTextNode.value || uiTextNode.placeholder || '' hiddenTextarea.value = uiTextNode.value || uiTextNode.placeholder || ''
let minHeight = -Infinity let minHeight = Number.MIN_SAFE_INTEGER
let maxHeight = Infinity let maxHeight = Number.MAX_SAFE_INTEGER
let height = hiddenTextarea.scrollHeight let height = hiddenTextarea.scrollHeight
let overflowY let overflowY
if (boxSizing === 'border-box') { if (boxSizing === 'border-box') {
// border-box: add border, since height = content + padding + border // border-box: add border, since height = content + padding + border
height = height + borderSize height = height + borderSize
} else if (boxSizing === 'content-box') { } else if (boxSizing === 'content-box') {
// remove padding, since height = content // remove padding, since height = content
height = height - paddingSize height = height - paddingSize
} }
if (minRows !== null || maxRows !== null) { if (minRows !== null || maxRows !== null) {
// measure height of a textarea with a single row // measure height of a textarea with a single row
hiddenTextarea.value = '' hiddenTextarea.value = ' '
const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize
if (minRows !== null) { if (minRows !== null) {
minHeight = singleRowHeight * minRows minHeight = singleRowHeight * minRows
@ -150,6 +143,7 @@ export default function calculateNodeHeight (
} }
} }
// Remove scroll bar flash when autosize without maxRows // Remove scroll bar flash when autosize without maxRows
// donot remove in vue
if (!maxRows) { if (!maxRows) {
overflowY = 'hidden' overflowY = 'hidden'
} }

View File

@ -0,0 +1,28 @@
<cn>
#### 文本域
用于多行输入。
</cn>
<us>
#### TextArea
For multi-line input.
</us>
```html
<template>
<div>
<a-button @click="() => this.autoResize = !autoResize">
Auto Resize: {String(autoResize)}
</a-button>
<a-textarea :rows="4" :autosize="autoResize" :defaultValue="defaultValue" />
</div>
</template>
<script>
export default {
data:()=>({
autoResize: false,
defaultValue: 'autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。autosize 属性适用于 textarea 节点,并且只有高度会自动变化。另外 autosize 可以设定为一个对象指定最小行数和最大行数。ending',
})
}
</script>
```

View File

@ -178,7 +178,7 @@
"mutationobserver-shim": "^0.3.2", "mutationobserver-shim": "^0.3.2",
"omit.js": "^1.0.0", "omit.js": "^1.0.0",
"raf": "^3.4.0", "raf": "^3.4.0",
"resize-observer-polyfill": "^1.5.0", "resize-observer-polyfill": "^1.5.1",
"shallow-equal": "^1.0.0", "shallow-equal": "^1.0.0",
"shallowequal": "^1.0.2", "shallowequal": "^1.0.2",
"vue-ref": "^1.0.3", "vue-ref": "^1.0.3",

7
types/badge.d.ts vendored
View File

@ -3,13 +3,14 @@
// Definitions: https://github.com/vueComponent/ant-design-vue/types // Definitions: https://github.com/vueComponent/ant-design-vue/types
import { AntdComponent } from './component'; import { AntdComponent } from './component';
import { VNode } from 'vue';
export declare class Badge extends AntdComponent { export declare class Badge extends AntdComponent {
/** /**
* Number to show in badge * Number to show in badge, support slot
* @type number | string * @type number | string | VNode
*/ */
count: number | string; count: number | string | VNode;
/** /**
* to display a red dot instead of count * to display a red dot instead of count

6
types/cascader.d.ts vendored
View File

@ -38,6 +38,12 @@ export interface ShowSearchType {
* @type boolean * @type boolean
*/ */
matchInputWidth?: boolean; matchInputWidth?: boolean;
/**
* Set the count of filtered items
* @type number | false
*/
limit?: number | false;
} }
export declare class Cascader extends AntdComponent { export declare class Cascader extends AntdComponent {