Skip to content

Commit

Permalink
feat: optimize Chinese input(just support v-model)
Browse files Browse the repository at this point in the history
  • Loading branch information
tangjinzhou committed Jul 27, 2018
1 parent 1367cfc commit 4a51544
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 4 deletions.
74 changes: 74 additions & 0 deletions components/_util/antInputDirective.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Not type checking this file because flow doesn't like attaching
* properties to Elements.
*/

export const inBrowser = typeof window !== 'undefined'
export const UA = inBrowser && window.navigator.userAgent.toLowerCase()
export const isIE9 = UA && UA.indexOf('msie 9.0') > 0
function makeMap (
str,
expectsLowerCase
) {
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
const isTextInputType = makeMap('text,number,password,search,email,tel,url')

function onCompositionStart (e) {
e.target.composing = true
}

function onCompositionEnd (e) {
// prevent triggering an input event for no reason
if (!e.target.composing) return
e.target.composing = false
trigger(e.target, 'input')
}

function trigger (el, type) {
const e = document.createEvent('HTMLEvents')
e.initEvent(type, true, true)
el.dispatchEvent(e)
}

/* istanbul ignore if */
if (isIE9) {
// http://www.matts411.com/post/internet-explorer-9-oninput/
document.addEventListener('selectionchange', () => {
const el = document.activeElement
if (el && el.vmodel) {
trigger(el, 'input')
}
})
}

export default {
install: (Vue, options) => {
Vue.directive('ant-input', {
inserted (el, binding, vnode, oldVnode) {
if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
if (!binding.modifiers || !binding.modifiers.lazy) {
el.addEventListener('compositionstart', onCompositionStart)
el.addEventListener('compositionend', onCompositionEnd)
// Safari < 10.2 & UIWebView doesn't fire compositionend when
// switching focus before confirming composition choice
// this also fixes the issue where some browsers e.g. iOS Chrome
// fires "change" instead of "input" on autocomplete.
el.addEventListener('change', onCompositionEnd)
/* istanbul ignore if */
if (isIE9) {
el.vmodel = true
}
}
}
},
})
},
}
12 changes: 11 additions & 1 deletion components/input/Input.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ export default {
} else {
this.$forceUpdate()
}
this.$emit('change.value', e.target.value)
if (!e.target.composing) {
this.$emit('change.value', e.target.value)
}
this.$emit('change', e)
this.$emit('input', e)
},
Expand Down Expand Up @@ -185,6 +187,9 @@ export default {
class: classNames(getInputClassName(), getClass(this)),
ref: 'input',
}
if ($listeners['change.value']) {
inputProps.directives = [{ name: 'ant-input' }]
}
return this.renderLabeledIcon(
<input
{...inputProps}
Expand All @@ -203,6 +208,11 @@ export default {
change: this.handleChange,
keydown: this.handleKeyDown,
},
directives: [
{
name: 'ant-input',
},
],
}
return <TextArea {...textareaProps} ref='input' />
}
Expand Down
7 changes: 6 additions & 1 deletion components/input/TextArea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ export default {
})
} else {
this.$forceUpdate()
}
if (!e.target.composing) {
this.$emit('change.value', e.target.value)
this.$emit('change', e)
}
this.$emit('change', e)
this.$emit('input', e)
},

Expand Down Expand Up @@ -133,6 +135,9 @@ export default {
input: handleTextareaChange,
},
}
if ($listeners['change.value']) {
textareaProps.directives = [{ name: 'ant-input' }]
}
return (
<textarea
{...textareaProps}
Expand Down
3 changes: 2 additions & 1 deletion components/input/__tests__/Search.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { mount } from '@vue/test-utils'
import { asyncExpect } from '@/tests/utils'
import Search from '../Search'
import Input from '../index'
import Button from '../../button'
import focusTest from '../../../tests/shared/focusTest'

const { Search } = Input
describe('Input.Search', () => {
focusTest(Search)

Expand Down
4 changes: 4 additions & 0 deletions components/input/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import Vue from 'vue'
import Input from './Input'
import Group from './Group'
import Search from './Search'
import TextArea from './TextArea'
import antInputDirective from '../_util/antInputDirective'

Vue.use(antInputDirective)

Input.Group = Group
Input.Search = Search
Expand Down
2 changes: 1 addition & 1 deletion site/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Api from './components/api'
import './components'
import demoBox from './components/demoBox'
import demoContainer from './components/demoContainer'
import Test from '../components/carousel/demo/index'
import Test from '../components/test/index'

Vue.use(VueClipboard)
Vue.use(VueRouter)
Expand Down

0 comments on commit 4a51544

Please sign in to comment.