mirror of https://github.com/vuejs/vue.git
text parser started, features, optional oneway binding for input
This commit is contained in:
parent
f9077cfa6a
commit
7fd557ccc8
|
|
@ -1,5 +1,11 @@
|
|||
WIP, playing with data binding
|
||||
|
||||
- DOM based templates with precise and efficient manipulation
|
||||
- Keep logic expressions outside of the templates.
|
||||
- POJSO (plain old javascript objects) FTW.
|
||||
- Auto dependency extraction for computed properties.
|
||||
- Auto event delegation on repeated items.
|
||||
|
||||
### Template
|
||||
|
||||
### Controller
|
||||
|
|
|
|||
4
TODO.md
4
TODO.md
|
|
@ -1,4 +1,4 @@
|
|||
- parse textNodes
|
||||
- more directives / filters
|
||||
- sd-with
|
||||
- sd-with
|
||||
- standarized way to reuse components (sd-component?)
|
||||
- nested properties in scope (kinda hard, maybe later)
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
"src/seed.js",
|
||||
"src/binding.js",
|
||||
"src/directive.js",
|
||||
"src/textnode-parser.js",
|
||||
"src/text-parser.js",
|
||||
"src/filters.js",
|
||||
"src/directives/index.js",
|
||||
"src/directives/each.js",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
<script src="../dist/seed.js"></script>
|
||||
</head>
|
||||
<body sd-controller="hello">
|
||||
<span sd-text="hello" sd-style="text-transform:format"></span>
|
||||
<input type="checkbox" sd-checked="ok" checked>
|
||||
<span sd-text="hello" sd-style="text-transform:format" sd-if="ok"></span>
|
||||
<script>
|
||||
var Seed = require('seed')
|
||||
Seed.controller('hello', function (scope) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ Seed.controller('Todos', function (scope) {
|
|||
scope.remaining = todos.reduce(function (count, todo) {
|
||||
return count + (todo.done ? 0 : 1)
|
||||
}, 0)
|
||||
scope.allDone = scope.remaining === 0
|
||||
|
||||
// computed properties ----------------------------------------------------
|
||||
scope.total = {get: function () {
|
||||
|
|
@ -30,6 +29,10 @@ Seed.controller('Todos', function (scope) {
|
|||
return scope.remaining > 1 ? 'items' : 'item'
|
||||
}}
|
||||
|
||||
scope.allDone = {get: function () {
|
||||
return scope.remaining === 0
|
||||
}}
|
||||
|
||||
// event handlers ---------------------------------------------------------
|
||||
scope.addTodo = function (e) {
|
||||
var val = e.el.value
|
||||
|
|
@ -47,7 +50,6 @@ Seed.controller('Todos', function (scope) {
|
|||
|
||||
scope.updateCount = function (e) {
|
||||
scope.remaining += e.scope.done ? -1 : 1
|
||||
scope.allDone = scope.remaining === 0
|
||||
}
|
||||
|
||||
scope.edit = function (e) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<input
|
||||
id="toggle-all"
|
||||
type="checkbox"
|
||||
sd-checked="allDone"
|
||||
sd-checked-oneway="allDone"
|
||||
sd-on="change:toggleAll"
|
||||
>
|
||||
<ul id="todo-list">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
module.exports = {
|
||||
prefix: 'sd',
|
||||
interpolateTags: {
|
||||
open: '{{',
|
||||
close: '}}'
|
||||
},
|
||||
controllers: {},
|
||||
datum: {}
|
||||
}
|
||||
|
|
@ -7,13 +7,14 @@ var KEY_RE = /^[^\|<]+/,
|
|||
FILTERS_RE = /\|[^\|<]+/g,
|
||||
FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
|
||||
INVERSE_RE = /^!/,
|
||||
NESTING_RE = /^\^+/
|
||||
NESTING_RE = /^\^+/,
|
||||
ONEWAY_RE = /-oneway$/
|
||||
|
||||
/*
|
||||
* Directive class
|
||||
* represents a single directive instance in the DOM
|
||||
*/
|
||||
function Directive (directiveName, expression) {
|
||||
function Directive (directiveName, expression, oneway) {
|
||||
|
||||
var prop, directive = directives[directiveName]
|
||||
if (typeof directive === 'function') {
|
||||
|
|
@ -28,6 +29,7 @@ function Directive (directiveName, expression) {
|
|||
}
|
||||
}
|
||||
|
||||
this.oneway = !!oneway
|
||||
this.directiveName = directiveName
|
||||
this.expression = expression.trim()
|
||||
this.rawKey = expression.match(KEY_RE)[0]
|
||||
|
|
@ -160,6 +162,11 @@ module.exports = {
|
|||
if (dirname.indexOf(prefix) === -1) return null
|
||||
dirname = dirname.slice(prefix.length + 1)
|
||||
|
||||
var oneway = ONEWAY_RE.test(dirname)
|
||||
if (oneway) {
|
||||
dirname = dirname.slice(0, -7)
|
||||
}
|
||||
|
||||
var dir = directives[dirname],
|
||||
valid = KEY_RE.test(expression)
|
||||
|
||||
|
|
@ -167,7 +174,7 @@ module.exports = {
|
|||
if (!valid) console.warn('invalid directive expression: ' + expression)
|
||||
|
||||
return dir && valid
|
||||
? new Directive(dirname, expression)
|
||||
? new Directive(dirname, expression, oneway)
|
||||
: null
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ module.exports = {
|
|||
|
||||
value: {
|
||||
bind: function () {
|
||||
if (this.oneway) return
|
||||
var el = this.el, self = this
|
||||
this.change = function () {
|
||||
self.seed.scope[self.key] = el.value
|
||||
|
|
@ -65,12 +66,14 @@ module.exports = {
|
|||
this.el.value = value
|
||||
},
|
||||
unbind: function () {
|
||||
if (this.oneway) return
|
||||
this.el.removeEventListener('change', this.change)
|
||||
}
|
||||
},
|
||||
|
||||
checked: {
|
||||
bind: function () {
|
||||
if (this.oneway) return
|
||||
var el = this.el, self = this
|
||||
this.change = function () {
|
||||
self.seed.scope[self.key] = el.checked
|
||||
|
|
@ -81,6 +84,7 @@ module.exports = {
|
|||
this.el.checked = !!value
|
||||
},
|
||||
unbind: function () {
|
||||
if (this.oneway) return
|
||||
this.el.removeEventListener('change', this.change)
|
||||
}
|
||||
},
|
||||
|
|
@ -88,7 +92,13 @@ module.exports = {
|
|||
'if': {
|
||||
bind: function () {
|
||||
this.parent = this.el.parentNode
|
||||
this.ref = this.el.nextSibling
|
||||
this.ref = document.createComment('sd-if-' + this.key)
|
||||
var next = this.el.nextSibling
|
||||
if (next) {
|
||||
this.parent.insertBefore(this.ref, next)
|
||||
} else {
|
||||
this.parent.appendChild(this.ref)
|
||||
}
|
||||
},
|
||||
update: function (value) {
|
||||
if (!value) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
var config = require('./config'),
|
||||
Seed = require('./seed'),
|
||||
directives = require('./directives'),
|
||||
filters = require('./filters')
|
||||
filters = require('./filters'),
|
||||
textParser = require('./text-parser')
|
||||
|
||||
var controllers = config.controllers,
|
||||
datum = config.datum,
|
||||
|
|
@ -61,6 +62,7 @@ api.bootstrap = function (opts) {
|
|||
}
|
||||
}
|
||||
}
|
||||
textParser.buildRegex()
|
||||
var el,
|
||||
ctrlSlt = '[' + config.prefix + '-controller]',
|
||||
dataSlt = '[' + config.prefix + '-data]'
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ var config = require('./config'),
|
|||
Emitter = require('emitter'),
|
||||
Binding = require('./binding'),
|
||||
Directive = require('./directive'),
|
||||
TextNodeParser = require('./textnode-parser')
|
||||
TextParser = require('./text-parser')
|
||||
|
||||
var slice = Array.prototype.slice,
|
||||
ctrlAttr = config.prefix + '-controller',
|
||||
|
|
@ -122,6 +122,8 @@ Seed.prototype._compileNode = function (node, root) {
|
|||
|
||||
// parse if has attributes
|
||||
if (node.attributes && node.attributes.length) {
|
||||
// forEach vs for loop perf comparison: http://jsperf.com/for-vs-foreach-case
|
||||
// takeaway: not worth it to wrtie manual loops.
|
||||
slice.call(node.attributes).forEach(function (attr) {
|
||||
if (attr.name === ctrlAttr) return
|
||||
var valid = false
|
||||
|
|
@ -151,7 +153,7 @@ Seed.prototype._compileNode = function (node, root) {
|
|||
* Compile a text node
|
||||
*/
|
||||
Seed.prototype._compileTextNode = function (node) {
|
||||
return TextNodeParser.parse(node)
|
||||
return TextParser.parse(node)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
var config = require('./config')
|
||||
|
||||
var ESCAPE_RE = /[-.*+?^${}()|[\]\/\\]/g,
|
||||
BINDING_RE = undefined
|
||||
|
||||
function escapeRegex (val) {
|
||||
return val.replace(ESCAPE_RE, '\\$&')
|
||||
}
|
||||
|
||||
"this is {{cool}} hahah {{todo.but}} 123 {{total}}"
|
||||
|
||||
module.exports = {
|
||||
|
||||
parse: function (node) {
|
||||
|
||||
},
|
||||
|
||||
buildRegex: function () {
|
||||
var open = escapeRegex(config.interpolateTags.open),
|
||||
close = escapeRegex(config.interpolateTags.close)
|
||||
BINDING_RE = new RegExp(open + '(.*?)' + close)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
parse: function (node) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue