8000 support setting non-existent dynamic path e.g. "a[b]" · Snoopbobb/vue@34da031 · GitHub
[go: up one dir, main page]

Skip to content

Commit 34da031

Browse files
committed
support setting non-existent dynamic path e.g. "a[b]"
1 parent bf1553c commit 34da031

File tree

4 files changed

+42
-17
lines changed

4 files changed

+42
-17
lines changed

src/api/data.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
var _ = require('../util')
12
var Watcher = require('../watcher')
23
var Path = require('../parsers/path')
34
var textParser = require('../parsers/text')
@@ -43,6 +44,12 @@ exports.$set = function (exp, val) {
4344
*/
4445

4546
exports.$add = function (key, val) {
47+
_.warn(
48+
'You are dynamically adding a property "' + key + '" to ' +
49+
'a vm instance. Consider pre-initializing the property ' +
50+
'with the "data" option for more reliable reactivity ' +
51+
'and better performance.'
52+
)
4653
this._data.$add(key, val)
4754
}
4855

src/parsers/expression.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var wsRE = /\s/g
2424
var newlineRE = /\n/g
2525
var saveRE = /[\{,]\s*[\w\$_]+\s*:|('[^']*'|"[^"]*")|new |typeof |void /g
2626
var restoreRE = /"(\d+)"/g
27-
var pathTestRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\])*$/
27+
var pathTestRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/
2828
var pathReplaceRE = /[^\w$\.]([A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\])*)/g
2929
var booleanLiteralRE = /^(true|false)$/
3030

src/parsers/path.js

Lines changed: 29 additions & 16 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ var pathStateMachine = {
3434
'ws': ['inPath', 'push'],
3535
'.': ['beforeIdent', 'push'],
3636
'[': ['beforeElement', 'push'],
37-
'eof': ['afterPath', 'push']
37+
'eof': ['afterPath', 'push'],
38+
']': ['inPath', 'push']
3839
},
3940

4041
'beforeElement': {
4142
'ws': ['beforeElement'],
4243
'0': ['afterZero', 'append'],
4344
'number': ['inIndex', 'append'],
4445
"'": ['inSingleQuote', 'append', ''],
45-
'"': ['inDoubleQuote', 'append', '']
46+
'"': ['inDoubleQuote', 'append', ''],
47+
"ident": ['inIdent', 'append', '*']
4648
},
4749

4850
'afterZero': {
@@ -189,9 +191,12 @@ function parsePath (path) {
189191

190192
mode = transition[0]
191193
action = actions[transition[1]] || noop
192-
newChar = transition[2] === undefined
194+
newChar = transition[2]
195+
newChar = newChar === undefined
193196
? c
194-
: transition[2]
197+
: newChar === '*'
198+
? newChar + c
199+
: newChar
195200
action()
196201

197202
if (mode === 'afterPath') {
@@ -207,11 +212,13 @@ function parsePath (path) {
207212
* @return {Boolean}
208213
*/
209214

210-
function formatAccessor(key) {
215+
function formatAccessor (key) {
211216
if (identRE.test(key)) { // identifier
212217
return '.' + key
213218
} else if (+key === key >>> 0) { // bracket index
214219
return '[' + key + ']'
220+
} else if (key.charAt(0) === '*') {
221+
return '[o' + formatAccessor(key.slice(1)) + ']'
215222
} else { // bracket string
216223
return '["' + key.replace(/"/g, '\\"') + '"]'
217224
}
@@ -272,27 +279,33 @@ exports.get = function (obj, path) {
272279
*/
273280

274281
exports.set = function (obj, path, val) {
282+
var original = obj
275283
if (typeof path === 'string') {
276284
path = exports.parse(path)
277285
}
278286
if (!path || !_.isObject(obj)) {
279287
return false
280288
}
281289
var last, key
282-
for (var i = 0, l = path.length - 1; i < l; i++) {
290+
for (var i = 0, l = path.length; i < l; i++) {
283291
last = obj
284292
key = path[i]
285-
obj = obj[key]
286-
if (!_.isObject(obj)) {
287-
obj = {}
288-
last.$add(key, obj)
293+
if (key.charAt(0) === '*') {
294+
key = original[key.slice(1)]
295+
}
296+
if (i < l - 1) {
297+
obj = obj[key]
298+
if (!_.isObject(obj)) {
299+
obj = {}
300+
last.$add(key, obj)
301+
}
302+
} else {
303+
if (key in obj) {
304+
obj[key] = val
305+
} else {
306+
obj.$add(key, val)
307+
}
289308
}
290-
}
291-
key = path[i]
292-
if (key in obj) {
293-
obj[key] = val
294-
} else {
295-
obj.$add(key, val)
296309
}
297310
return true
298311
}

test/unit/specs/api/data_spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ describe('Data API', function () {
4040
// setting unexisting
4141
vm.$set('c.d', 2)
4242
expect(vm.c.d).toBe(2)
43+
// warn against setting unexisting
44+
expect(hasWarned(_, 'Consider pre-initializing')).toBe(true)
45+
})
46+
47+
it('$set invalid', function () {
4348
// invalid, should throw
4449
if (leftHandThrows()) {
4550
// if creating a function with invalid left hand

0 commit comments

Comments
 (0)
0