Skip to content

Commit

Permalink
API change: split scope into data and methods
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 23, 2013
1 parent c75aa42 commit 7c1d196
Show file tree
Hide file tree
Showing 26 changed files with 155 additions and 148 deletions.
8 changes: 5 additions & 3 deletions examples/firebase/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Users.on('child_removed', function (snapshot) {
var app = new Vue({
el: '#app',
filters: validators,
scope: {
data: {
users: [],
newUser: {
name: '',
Expand All @@ -40,7 +40,9 @@ var app = new Vue({
}
return valid
}
},
}
},
methods: {
addUser: function (e) {
e.preventDefault()
if (this.isValid) {
Expand All @@ -49,7 +51,7 @@ var app = new Vue({
}
},
removeUser: function (e) {
new Firebase(baseURL + 'users/' + e.item.id).remove()
new Firebase(baseURL + 'users/' + e.targetVM.id).remove()
}
}
})
4 changes: 2 additions & 2 deletions examples/firebase/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<body>
<div id="app">
<ul>
<li class="user" v-repeat="user:users" v-transition>
<span>{{user.name}} - {{user.email}}</span>
<li class="user" v-repeat="users" v-transition>
<span>{{name}} - {{email}}</span>
<button v-on="click:removeUser">X</button>
</li>
</ul>
Expand Down
32 changes: 17 additions & 15 deletions examples/todomvc/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,25 @@ var app = new Vue({
}).length
},

scope: {
data: {

todos: todoStorage.fetch(),

allDone: {
$get: function () {
return this.remaining === 0
},
$set: function (value) {
this.todos.forEach(function (todo) {
todo.completed = value
})
this.remaining = value ? 0 : this.todos.length
todoStorage.save()
}
}
},

methods: {
updateFilter: function () {
var filter = location.hash.slice(2)
this.filter = (filter in filters) ? filter : 'all'
Expand All @@ -45,7 +60,7 @@ var app = new Vue({
},

removeTodo: function (e) {
this.todos.remove(e.targetVM.$scope)
this.todos.remove(e.targetVM.$data)
this.remaining -= e.targetVM.completed ? 0 : 1
todoStorage.save()
},
Expand Down Expand Up @@ -78,19 +93,6 @@ var app = new Vue({
return todo.completed
})
todoStorage.save()
},

allDone: {
$get: function () {
return this.remaining === 0
},
$set: function (value) {
this.todos.forEach(function (todo) {
todo.completed = value
})
this.remaining = value ? 0 : this.todos.length
todoStorage.save()
}
}
}
})
Expand Down
57 changes: 28 additions & 29 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var Emitter = require('./emitter'),
slice = Array.prototype.slice,
log = utils.log,
makeHash = utils.hash,
extend = utils.extend,
def = utils.defProtected,
hasOwn = Object.prototype.hasOwnProperty

Expand All @@ -30,21 +31,20 @@ function Compiler (vm, options) {

// process and extend options
options = compiler.options = options || makeHash()
var data = compiler.data = options.data || {}
utils.processOptions(options)
utils.extend(compiler, options.compilerOptions)
extend(compiler, options.compilerOptions)
extend(vm, options.data, true)
extend(vm, options.methods, true)

// initialize element
var el = compiler.setupElement(options)
log('\nnew VM instance:', el.tagName, '\n')

// init scope
var scope = compiler.scope = options.scope || {}
utils.extend(vm, scope, true)

compiler.vm = vm
def(vm, '$', makeHash())
def(vm, '$el', el)
def(vm, '$scope', scope)
def(vm, '$data', data)
def(vm, '$compiler', compiler)

// keep track of directives and expressions
Expand Down Expand Up @@ -87,16 +87,16 @@ function Compiler (vm, options) {
// beforeCompile hook
compiler.execHook('beforeCompile', 'created')
// the user might have set some props on the vm
// so copy it back to the scope...
utils.extend(scope, vm)
// observe the scope
Observer.observe(scope, '', compiler.observer)
// so copy it back to the data...
extend(data, vm)
// observe the data
Observer.observe(data, '', compiler.observer)

// for repeated items, create an index binding
// which should be inenumerable but configurable
if (compiler.repeat) {
//scope.$index = compiler.repeatIndex
def(scope, '$index', compiler.repeatIndex, false, true)
//data.$index = compiler.repeatIndex
def(data, '$index', compiler.repeatIndex, false, true)
compiler.createBinding('$index')
}

Expand Down Expand Up @@ -369,7 +369,7 @@ CompilerProto.bindDirective = function (directive) {
// expression bindings are always created on current compiler
binding = compiler.createBinding(key, true, directive.isFn)
} else if (
hasOwn.call(compiler.scope, baseKey) ||
hasOwn.call(compiler.data, baseKey) ||
hasOwn.call(compiler.vm, baseKey)
) {
// If the directive's compiler's VM has the base key,
Expand Down Expand Up @@ -409,7 +409,7 @@ CompilerProto.bindDirective = function (directive) {
CompilerProto.createBinding = function (key, isExp, isFn) {

var compiler = this,
scope = compiler.scope,
data = compiler.data,
bindings = compiler.bindings,
binding = new Binding(compiler, key, isExp, isFn)

Expand All @@ -434,8 +434,8 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
// this is a root level binding. we need to define getter/setters for it.
compiler.define(key, binding)
} else {
// ensure path in scope so it can be observed
Observer.ensurePath(scope, key)
// ensure path in data so it can be observed
Observer.ensurePath(data, key)
var parentKey = key.slice(0, key.lastIndexOf('.'))
if (!hasOwn.call(bindings, parentKey)) {
// this is a nested value binding, but the binding for its parent
Expand All @@ -456,41 +456,40 @@ CompilerProto.define = function (key, binding) {
log(' defined root binding: ' + key)

var compiler = this,
scope = compiler.scope,
data = compiler.data,
vm = compiler.vm,
value = binding.value = scope[key] // save the value before redefinening it
value = binding.value = data[key] // save the value before redefinening it

if (utils.typeOf(value) === 'Object' && value.$get) {
compiler.markComputed(binding)
}

// $index is inenumerable
if (!(key in scope) && key !== '$index') {
scope[key] = undefined
if (!(key in data)) {
data[key] = undefined
}

// if the scope object is already observed, that means
// if the data object is already observed, that means
// this binding is created late. we need to observe it now.
if (scope.__observer__) {
Observer.convert(scope, key)
if (data.__observer__) {
Observer.convert(data, key)
}

Object.defineProperty(vm, key, {
get: binding.isComputed
? function () {
return scope[key].$get()
return data[key].$get()
}
: function () {
return scope[key]
return data[key]
},
set: binding.isComputed
? function (val) {
if (scope[key].$set) {
scope[key].$set(val)
if (data[key].$set) {
data[key].$set(val)
}
}
: function (val) {
scope[key] = val
data[key] = val
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/directives/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
if (!Ctor) utils.warn('unknown component: ' + this.arg)
var options = {
el: this.el,
scope: value,
data: value,
compilerOptions: {
parentCompiler: this.compiler
}
Expand Down
6 changes: 3 additions & 3 deletions src/directives/repeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var mutationHandlers = {
data = col[i]
for (j = 0; j < l; j++) {
vm = vms[j]
if (vm.$scope === data) {
if (vm.$data === data) {
sorted[i] = vm
break
}
Expand Down Expand Up @@ -171,7 +171,7 @@ module.exports = {

item = new this.ChildVM({
el: node,
scope: data,
data: data,
compilerOptions: {
repeat: true,
repeatIndex: index,
Expand All @@ -196,7 +196,7 @@ module.exports = {
updateIndexes: function () {
var i = this.vms.length
while (i--) {
this.vms[i].$scope.$index = i
this.vms[i].$data.$index = i
}
},

Expand Down
4 changes: 2 additions & 2 deletions src/exp-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function getRel (path, compiler) {
: path
while (true) {
if (
hasOwn.call(vm.$scope, key) ||
hasOwn.call(vm.$data, key) ||
hasOwn.call(vm, key)
) {
break
Expand All @@ -85,7 +85,7 @@ function getRel (path, compiler) {
/**
* Create a function from a string...
* this looks like evil magic but since all variables are limited
* to the VM's scope it's actually properly sandboxed
* to the VM's data it's actually properly sandboxed
*/
function makeGetter (exp, raw) {
/* jshint evil: true */
Expand Down
17 changes: 10 additions & 7 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,14 @@ function extend (options) {
utils.defProtected(proto, 'constructor', ExtendedVM)

// copy prototype props
var protoMixins = options.proto
if (protoMixins) {
for (var key in protoMixins) {
if (!(key in ViewModel.prototype)) {
proto[key] = protoMixins[key]
var methods = options.methods
if (methods) {
for (var key in methods) {
if (
!(key in ViewModel.prototype) &&
typeof methods[key] === 'function'
) {
proto[key] = methods[key]
}
}
}
Expand All @@ -105,7 +108,7 @@ function extend (options) {
/**
* Inherit options
*
* For options such as `scope`, `vms`, `directives`, 'partials',
* For options such as `data`, `vms`, `directives`, 'partials',
* they should be further extended. However extending should only
* be done at top level.
*
Expand All @@ -119,7 +122,7 @@ function inheritOptions (child, parent, topLevel) {
child = child || utils.hash()
if (!parent) return child
for (var key in parent) {
if (key === 'el' || key === 'proto') continue
if (key === 'el' || key === 'methods') continue
var val = child[key],
parentVal = parent[key],
type = utils.typeOf(val)
Expand Down
6 changes: 3 additions & 3 deletions test/functional/fixtures/expression.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
Vue.config({debug:true})
var normal = new Vue({
el: '#normal',
scope: {
data: {
one: 'Hello',
two: {
three: 'World'
Expand All @@ -38,7 +38,7 @@
var lazy = new Vue({
el: '#lazy',
lazy: true,
scope: {
data: {
one: 'Hi',
two: {
three: 'Ho'
Expand All @@ -48,7 +48,7 @@

var conditional = new Vue({
el: '#conditional',
scope: {
data: {
ok: true,
yesMsg: 'YES',
noMsg: 'NO'
Expand Down
6 changes: 3 additions & 3 deletions test/functional/fixtures/extend.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
},
components: {
'vm-test': {
scope: {
data: {
vmMsg: 'component works'
}
},
'vm-w-model': {
scope : {
data : {
selfMsg: 'component with model '
}
}
Expand Down Expand Up @@ -63,7 +63,7 @@
})
new T({
el: '#test',
scope: {
data: {
dirMsg: 'directive',
filterMsg: 'fi43l132ter5 w12345orks',
partialMsg: 'partial works',
Expand Down
2 changes: 1 addition & 1 deletion test/functional/fixtures/forms.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
var test = new Vue({
el: 'body',
lazy: true,
scope: {
data: {
text: 'some text',
checked: true,
radio: 'b',
Expand Down

0 comments on commit 7c1d196

Please sign in to comment.