Skip to content

Commit

Permalink
fix: improve Vue.set/Vue.delete API to support multi type of array in…
Browse files Browse the repository at this point in the history
…dex (#5973)

related #5884
  • Loading branch information
javoski authored and yyx990803 committed Jul 1, 2017
1 parent 458030a commit eea0920
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/core/observer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
def,
isObject,
isPlainObject,
isValidArrayIndex,
hasProto,
hasOwn,
warn,
Expand Down Expand Up @@ -189,7 +190,7 @@ export function defineReactive (
* already exist.
*/
export function set (target: Array<any> | Object, key: any, val: any): any {
if (Array.isArray(target) && (typeof key === 'number' || /^\d+$/.test(key))) {
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
Expand Down Expand Up @@ -219,7 +220,7 @@ export function set (target: Array<any> | Object, key: any, val: any): any {
* Delete a property and trigger change if necessary.
*/
export function del (target: Array<any> | Object, key: any) {
if (Array.isArray(target) && typeof key === 'number') {
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.splice(key, 1)
return
}
Expand Down
9 changes: 9 additions & 0 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function isTrue (v: any): boolean %checks {
export function isFalse (v: any): boolean %checks {
return v === false
}

/**
* Check if value is primitive
*/
Expand Down Expand Up @@ -47,6 +48,14 @@ export function isRegExp (v: any): boolean {
return _toString.call(v) === '[object RegExp]'
}

/**
* Check if val is a valid array index.
*/
export function isValidArrayIndex (val: any): boolean {
const n = parseFloat(val)
return n >= 0 && Math.floor(n) === n && isFinite(val)
}

/**
* Convert a value to a string that is actually rendered.
*/
Expand Down
30 changes: 28 additions & 2 deletions test/unit/features/global-api/set-delete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ describe('Global API: set/delete', () => {
Vue.set(vm.list, 1, 'd')
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-d</div><div>2-c</div>')
Vue.set(vm.list, '2', 'e')
}).then(() => {
expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-d</div><div>2-e</div>')
/* eslint-disable no-new-wrappers */
Vue.set(vm.list, new Number(1), 'f')
}).then(() => {
expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-f</div><div>2-e</div>')
Vue.set(vm.list, '3g', 'g')
}).then(() => {
expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-f</div><div>2-e</div>')
}).then(done)
})

Expand Down Expand Up @@ -106,10 +116,26 @@ describe('Global API: set/delete', () => {
Vue.delete(vm.lists, 1)
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, 1)
Vue.delete(vm.lists, NaN)
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, -1)
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, '1.3')
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, true)
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, {})
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')
Vue.delete(vm.lists, '1')
}).then(() => {
expect(vm.$el.innerHTML).toBe('<p>A</p>')
Vue.delete(vm.lists, 0)
/* eslint-disable no-new-wrappers */
Vue.delete(vm.lists, new Number(0))
}).then(() => {
expect(vm.$el.innerHTML).toBe('')
}).then(done)
Expand Down

0 comments on commit eea0920

Please sign in to comment.