mirror of https://github.com/vuejs/vue.git
separate storage in todos example, expose some utils methods
This commit is contained in:
parent
d0c96c5c25
commit
cfc27d89f1
|
|
@ -6,7 +6,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="common/base.css">
|
||||
</head>
|
||||
<body>
|
||||
<section id="todoapp" sd-controller="Todos">
|
||||
<section id="todoapp" sd-controller="todos">
|
||||
<header id="header">
|
||||
<h1>todos</h1>
|
||||
<input
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
sd-checked="todo.completed"
|
||||
sd-on="change:updateCount"
|
||||
>
|
||||
<label sd-text="todo.title" sd-on="dblclick:edit"></label>
|
||||
<label sd-text="todo.title" sd-on="dblclick:editTodo"></label>
|
||||
<button class="destroy" sd-on="click:removeTodo"></button>
|
||||
</div>
|
||||
<input
|
||||
|
|
@ -71,6 +71,7 @@
|
|||
<p>Created by <a href="http://evanyou.me">Evan You</a></p>
|
||||
</footer>
|
||||
<script src="../../dist/seed.js"></script>
|
||||
<script src="js/todoStorage.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +1,7 @@
|
|||
Seed.controller('Todos', function (scope) {
|
||||
|
||||
// data persistence -------------------------------------------------------
|
||||
var STORAGE_KEY = 'todos-seedjs'
|
||||
function sync () {
|
||||
localStorage.setItem(STORAGE_KEY, scope.$serialize('todos'))
|
||||
}
|
||||
|
||||
// filters ----------------------------------------------------------------
|
||||
var filters = {
|
||||
all: function () { return true },
|
||||
active: function (v) { return !v },
|
||||
completed: function (v) { return v }
|
||||
}
|
||||
updateFilter()
|
||||
window.addEventListener('hashchange', updateFilter)
|
||||
function updateFilter () {
|
||||
scope.filter = location.hash ? location.hash.slice(2) : 'all'
|
||||
}
|
||||
Seed.controller('todos', function (scope) {
|
||||
|
||||
// regular properties -----------------------------------------------------
|
||||
scope.todos = JSON.parse(localStorage.getItem(STORAGE_KEY)) || []
|
||||
scope.todos = todoStorage.fetch()
|
||||
scope.remaining = scope.todos.reduce(function (n, todo) {
|
||||
return n + (todo.completed ? 0 : 1)
|
||||
}, 0)
|
||||
|
|
@ -63,23 +45,23 @@ Seed.controller('Todos', function (scope) {
|
|||
scope.todos.unshift({ title: value, completed: false })
|
||||
scope.newTodo = ''
|
||||
scope.remaining++
|
||||
sync()
|
||||
todoStorage.save(scope.todos)
|
||||
}
|
||||
}
|
||||
|
||||
scope.removeTodo = function (e) {
|
||||
scope.todos.remove(e.scope)
|
||||
scope.remaining -= e.scope.completed ? 0 : 1
|
||||
sync()
|
||||
todoStorage.save(scope.todos)
|
||||
}
|
||||
|
||||
scope.updateCount = function (e) {
|
||||
scope.remaining += e.scope.completed ? -1 : 1
|
||||
sync()
|
||||
todoStorage.save(scope.todos)
|
||||
}
|
||||
|
||||
var beforeEditCache
|
||||
scope.edit = function (e) {
|
||||
scope.editTodo = function (e) {
|
||||
beforeEditCache = e.scope.title
|
||||
e.scope.editing = true
|
||||
}
|
||||
|
|
@ -89,7 +71,7 @@ Seed.controller('Todos', function (scope) {
|
|||
e.scope.editing = false
|
||||
e.scope.title = e.scope.title.trim()
|
||||
if (!e.scope.title) scope.removeTodo(e)
|
||||
sync()
|
||||
todoStorage.save(scope.todos)
|
||||
}
|
||||
|
||||
scope.cancelEdit = function (e) {
|
||||
|
|
@ -103,11 +85,23 @@ Seed.controller('Todos', function (scope) {
|
|||
scope.todos = scope.todos.filter(function (todo) {
|
||||
return !todo.completed
|
||||
})
|
||||
sync()
|
||||
todoStorage.save(scope.todos)
|
||||
}
|
||||
|
||||
// filters ----------------------------------------------------------------
|
||||
var filters = {
|
||||
all: function () { return true },
|
||||
active: function (v) { return !v },
|
||||
completed: function (v) { return v }
|
||||
}
|
||||
|
||||
function updateFilter () {
|
||||
scope.filter = location.hash ? location.hash.slice(2) : 'all'
|
||||
}
|
||||
|
||||
updateFilter()
|
||||
window.addEventListener('hashchange', updateFilter)
|
||||
|
||||
})
|
||||
|
||||
var s = Date.now()
|
||||
Seed.bootstrap({ debug: false })
|
||||
console.log(Date.now() - s)
|
||||
Seed.bootstrap()
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
var todoStorage = (function () {
|
||||
var STORAGE_KEY = 'todos-seedjs'
|
||||
return {
|
||||
fetch: function () {
|
||||
return JSON.parse(localStorage.getItem(this.STORAGE_KEY) || '[]')
|
||||
},
|
||||
save: function (todos) {
|
||||
localStorage.setItem(this.STORAGE_KEY, Seed.utils.serialize(todos))
|
||||
}
|
||||
}
|
||||
}())
|
||||
38
src/main.js
38
src/main.js
|
|
@ -2,7 +2,8 @@ var config = require('./config'),
|
|||
Seed = require('./seed'),
|
||||
directives = require('./directives'),
|
||||
filters = require('./filters'),
|
||||
textParser = require('./text-parser')
|
||||
textParser = require('./text-parser'),
|
||||
utils = require('./utils')
|
||||
|
||||
var controllers = config.controllers,
|
||||
datum = config.datum,
|
||||
|
|
@ -10,6 +11,11 @@ var controllers = config.controllers,
|
|||
reserved = ['datum', 'controllers'],
|
||||
booted = false
|
||||
|
||||
/*
|
||||
* expose utils
|
||||
*/
|
||||
api.utils = utils
|
||||
|
||||
/*
|
||||
* Store a piece of plain data in config.datum
|
||||
* so it can be consumed by sd-data
|
||||
|
|
@ -45,12 +51,9 @@ api.filter = function (name, fn) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Bootstrap the whole thing
|
||||
* by creating a Seed instance for top level nodes
|
||||
* that has either sd-controller or sd-data
|
||||
* Set config options
|
||||
*/
|
||||
api.bootstrap = function (opts) {
|
||||
if (booted) return
|
||||
api.config = function (opts) {
|
||||
if (opts) {
|
||||
for (var key in opts) {
|
||||
if (reserved.indexOf(key) === -1) {
|
||||
|
|
@ -59,16 +62,31 @@ api.bootstrap = function (opts) {
|
|||
}
|
||||
}
|
||||
textParser.buildRegex()
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile a single element
|
||||
*/
|
||||
api.compile = function (el) {
|
||||
new Seed(el)
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootstrap the whole thing
|
||||
* by creating a Seed instance for top level nodes
|
||||
* that has either sd-controller or sd-data
|
||||
*/
|
||||
api.bootstrap = function (opts) {
|
||||
if (booted) return
|
||||
api.config(opts)
|
||||
var el,
|
||||
ctrlSlt = '[' + config.prefix + '-controller]',
|
||||
dataSlt = '[' + config.prefix + '-data]',
|
||||
seeds = []
|
||||
dataSlt = '[' + config.prefix + '-data]'
|
||||
/* jshint boss: true */
|
||||
while (el = document.querySelector(ctrlSlt) || document.querySelector(dataSlt)) {
|
||||
seeds.push((new Seed(el)).scope)
|
||||
new Seed(el)
|
||||
}
|
||||
booted = true
|
||||
return seeds.length > 1 ? seeds : seeds[0]
|
||||
}
|
||||
|
||||
module.exports = api
|
||||
|
|
@ -56,7 +56,7 @@ ScopeProto.$unwatch = function (key) {
|
|||
*/
|
||||
ScopeProto.$dump = function (key) {
|
||||
var bindings = this.$seed._bindings
|
||||
return utils.dumpValue(key ? bindings[key].value : this)
|
||||
return utils.dump(key ? bindings[key].value : this)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -64,9 +64,10 @@ function Seed (el, options) {
|
|||
var ctrlID = el.getAttribute(ctrlAttr)
|
||||
if (ctrlID) {
|
||||
el.removeAttribute(ctrlAttr)
|
||||
var factory = config.controllers[ctrlID]
|
||||
if (factory) {
|
||||
factory(this.scope)
|
||||
var controller = config.controllers[ctrlID]
|
||||
if (controller) {
|
||||
this._controller = controller
|
||||
controller(this.scope)
|
||||
} else {
|
||||
config.warn('controller "' + ctrlID + '" is not defined.')
|
||||
}
|
||||
|
|
@ -86,6 +87,7 @@ function Seed (el, options) {
|
|||
if (this._computed.length) depsParser.parse(this._computed)
|
||||
delete this._computed
|
||||
|
||||
// extract dependencies for computed properties with dynamic context
|
||||
if (this._contextBindings.length) this._bindContexts(this._contextBindings)
|
||||
delete this._contextBindings
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ module.exports = {
|
|||
* Parse a piece of text, return an array of tokens
|
||||
*/
|
||||
parse: function (node) {
|
||||
if (!BINDING_RE) module.exports.buildRegex()
|
||||
var text = node.nodeValue
|
||||
if (!BINDING_RE.test(text)) return null
|
||||
var m, i, tokens = []
|
||||
|
|
|
|||
22
src/utils.js
22
src/utils.js
|
|
@ -24,21 +24,22 @@ function typeOf (obj) {
|
|||
/*
|
||||
* Recursively dump stuff...
|
||||
*/
|
||||
function dumpValue (val) {
|
||||
function dump (val) {
|
||||
var type = typeOf(val)
|
||||
if (type === 'Array') {
|
||||
return val.map(dumpValue)
|
||||
return val.map(dump)
|
||||
} else if (type === 'Object') {
|
||||
if (val.get) { // computed property
|
||||
return val.get()
|
||||
} else { // object / child scope
|
||||
var ret = {}
|
||||
var ret = {}, prop
|
||||
for (var key in val) {
|
||||
if (val.hasOwnProperty(key) &&
|
||||
typeof val[key] !== 'function' &&
|
||||
prop = val[key]
|
||||
if (typeof prop !== 'function' &&
|
||||
val.hasOwnProperty(key) &&
|
||||
key.charAt(0) !== '$')
|
||||
{
|
||||
ret[key] = dumpValue(val[key])
|
||||
ret[key] = dump(prop)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
|
|
@ -51,7 +52,14 @@ function dumpValue (val) {
|
|||
module.exports = {
|
||||
|
||||
typeOf: typeOf,
|
||||
dumpValue: dumpValue,
|
||||
dump: dump,
|
||||
|
||||
/*
|
||||
* shortcut for JSON.stringify-ing a dumped value
|
||||
*/
|
||||
serialize: function (val) {
|
||||
return JSON.stringify(dump(val))
|
||||
},
|
||||
|
||||
/*
|
||||
* Get a value from an object based on a path array
|
||||
|
|
|
|||
Loading…
Reference in New Issue