refactor wip

This commit is contained in:
Evan You 2016-04-19 03:52:58 -04:00
parent 0879e994e5
commit 2082eb9290
5 changed files with 77 additions and 131 deletions

View File

@ -1,8 +1,6 @@
import { addProp } from '../../helpers'
export function html (el, dir) { export function html (el, dir) {
if (!dir.value) return if (!dir.value) return
if (!el.props) el.props = [] addProp(el, 'innerHTML', `(${dir.value})`)
el.props.push({
name: 'innerHTML',
value: `(${dir.value})`
})
} }

View File

@ -1,8 +1,6 @@
import { addHandler } from '../../helpers' import { addHandler, addProp, getBindingAttr } from '../../helpers'
export function model (el, dir) { export function model (el, dir) {
if (!el.events) el.events = {}
if (!el.props) el.props = []
const value = dir.value const value = dir.value
const modifiers = dir.modifiers const modifiers = dir.modifiers
if (el.tag === 'select') { if (el.tag === 'select') {
@ -26,19 +24,13 @@ export function model (el, dir) {
} }
function genCheckboxModel (el, value) { function genCheckboxModel (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.checked`) addProp(el, 'checked', `!!(${value})`)
el.props.push({ addHandler(el, 'change', `${value}=$event.target.checked`)
name: 'checked',
value: `!!(${value})`
})
} }
function genRadioModel (el, value) { function genRadioModel (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.value`) addProp(el, 'checked', `(${value}==${getBindingAttr(el, 'value')})`)
el.props.push({ addHandler(el, 'change', `${value}=$event.target.value`)
name: 'checked',
value: `(${value}==${getInputValue(el)})`
})
} }
function genDefaultModel (el, value, modifiers) { function genDefaultModel (el, value, modifiers) {
@ -51,15 +43,11 @@ function genDefaultModel (el, value, modifiers) {
let code = number || type === 'number' let code = number || type === 'number'
? `${value}=Number($event.target.value)` ? `${value}=Number($event.target.value)`
: `${value}=$event.target.value` : `${value}=$event.target.value`
if (needCompositionGuard) { if (needCompositionGuard) {
code = `if($event.target.composing)return;${code}` code = `if($event.target.composing)return;${code}`
} }
addHandler(el.events, event, code) addProp(el, 'value', `(${value})`)
el.props.push({ addHandler(el, event, code)
name: 'value',
value: `(${value})`
})
if (needCompositionGuard) { if (needCompositionGuard) {
// return runtime directive code to help with composition events // return runtime directive code to help with composition events
return '{def:__resolveDirective__("model")},' return '{def:__resolveDirective__("model")},'
@ -67,15 +55,12 @@ function genDefaultModel (el, value, modifiers) {
} }
function genSelect (el, value) { function genSelect (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.value`) addProp(el, 'value', `(${value})`)
el.props.push({ addHandler(el, 'change', `${value}=$event.target.value`)
name: 'value',
value: `(${value})`
})
} }
function genMultiSelect (el, value) { function genMultiSelect (el, value) {
addHandler(el.events, 'change', addHandler(el, 'change',
`${value}=Array.prototype.filter `${value}=Array.prototype.filter
.call($event.target.options,function(o){return o.selected}) .call($event.target.options,function(o){return o.selected})
.map(function(o){return o.value})`) .map(function(o){return o.value})`)
@ -83,16 +68,7 @@ function genMultiSelect (el, value) {
for (let i = 0; i < el.children.length; i++) { for (let i = 0; i < el.children.length; i++) {
let c = el.children[i] let c = el.children[i]
if (c.tag === 'option') { if (c.tag === 'option') {
(c.props || (c.props = [])).push({ addProp(c, 'selected', `(${value}).indexOf(${getBindingAttr(c, 'value')})>-1`)
name: 'selected',
value: `(${value}).indexOf(${getInputValue(c)})>-1`
})
} }
} }
} }
function getInputValue (el) {
return el.attrsMap.value
? JSON.stringify(el.attrsMap.value)
: el.attrsMap['v-bind:value'] || el.attrsMap[':value']
}

View File

@ -1,6 +1,29 @@
import { isArray } from '../shared/util' import { isArray } from '../shared/util'
export function addHandler (events, name, value, modifiers) { export function getBindingAttr (el, name, getStatic) {
const staticValue = getStatic !== false && getAndRemoveAttr(el, name)
return staticValue
? JSON.stringify(staticValue)
: (getAndRemoveAttr(el, ':' + name) || getAndRemoveAttr(el, 'v-bind:' + name))
}
export function getAndRemoveAttr (el, name) {
let val
if ((val = el.attrsMap[name]) != null) {
el.attrsMap[name] = null
const list = el.attrsList
for (let i = 0, l = list.length; i < l; i++) {
if (list[i].name === name) {
list.splice(i, 1)
break
}
}
}
return val
}
export function addHandler (el, name, value, modifiers) {
const events = (el.events || (el.events = {}))
// check capture modifier // check capture modifier
if (modifiers && modifiers.capture) { if (modifiers && modifiers.capture) {
delete modifiers.capture delete modifiers.capture
@ -16,3 +39,19 @@ export function addHandler (events, name, value, modifiers) {
events[name] = newHandler events[name] = newHandler
} }
} }
export function addProp (el, name, value) {
(el.props || (el.props = [])).push({ name, value })
}
export function addAttr (el, name, value) {
(el.attrs || (el.attrs = [])).push({ name, value })
}
export function addDirective (el, name, value, arg, modifiers) {
(el.directives || (el.directives = [])).push({ name, value, arg, modifiers })
}
export function addStyle (el, name, value) {
}

View File

@ -1,8 +1,15 @@
import { decodeHTML } from 'entities' import { decodeHTML } from 'entities'
import { parseHTML } from './html-parser' import { parseHTML } from './html-parser'
import { parseText } from './text-parser' import { parseText } from './text-parser'
import { addHandler } from '../helpers'
import { hyphenate, makeMap } from '../../shared/util' import { hyphenate, makeMap } from '../../shared/util'
import {
getAndRemoveAttr,
addProp,
addAttr,
addHandler,
addDirective,
getBindingAttr
} from '../helpers'
const dirRE = /^v-|^@|^:/ const dirRE = /^v-|^@|^:/
const bindRE = /^:|^v-bind:/ const bindRE = /^:|^v-bind:/
@ -26,51 +33,6 @@ const baseWarn = msg => console.error(`[Vue parser]: ${msg}`)
/** /**
* Convert HTML string to AST. * Convert HTML string to AST.
* *
* There are 3 types of nodes:
*
* - Element: {
* // base info
* tag: String,
* plain: Boolean,
* attrsList: Array,
* attrsMap: Object,
* parent: Element,
* children: Array,
*
* attrs: Array
* props: Array
* directives: Array
*
* pre: Boolean
*
* if: String (expression)
* else: Boolean
* elseBlock: Element
*
* for: String
* iterator: String
* alias: String
*
* staticClass: String
* classBinding: String
*
* styleBinding: String
*
* render: Boolean
* renderName: String
* renderArgs: String
*
* slotName: String
* }
*
* - Expression: {
* expression: String (expression)
* }
*
* - Text: {
* text: String
* }
*
* @param {String} template * @param {String} template
* @param {Object} options * @param {Object} options
* @return {Object} * @return {Object}
@ -295,33 +257,24 @@ function processRender (el) {
function processSlot (el) { function processSlot (el) {
if (el.tag === 'slot') { if (el.tag === 'slot') {
el.slotName = el.attrsMap.name el.slotName = getBindingAttr(el, 'name')
? `"${el.attrsMap.name}"`
: (el.attrsMap[':name'] || el.attrsMap['v-bind:name'])
} }
} }
function processComponent (el) { function processComponent (el) {
if (el.tag === 'component') { if (el.tag === 'component') {
let staticName = getAndRemoveAttr(el, 'is') el.component = getBindingAttr(el, 'is')
el.component = staticName
? JSON.stringify(staticName)
: (getAndRemoveAttr(el, ':is') || getAndRemoveAttr(el, 'v-bind:is'))
} }
} }
function processClassBinding (el) { function processClassBinding (el) {
const staticClass = getAndRemoveAttr(el, 'class') const staticClass = getAndRemoveAttr(el, 'class')
el.staticClass = parseText(staticClass) || JSON.stringify(staticClass) el.staticClass = parseText(staticClass) || JSON.stringify(staticClass)
el.classBinding = el.classBinding = getBindingAttr(el, 'class', false /* getStatic */)
getAndRemoveAttr(el, ':class') ||
getAndRemoveAttr(el, 'v-bind:class')
} }
function processStyleBinding (el) { function processStyleBinding (el) {
el.styleBinding = el.styleBinding = getBindingAttr(el, 'style', false /* getStatic */)
getAndRemoveAttr(el, ':style') ||
getAndRemoveAttr(el, 'v-bind:style')
} }
function processAttrs (el) { function processAttrs (el) {
@ -339,32 +292,24 @@ function processAttrs (el) {
if (bindRE.test(name)) { // v-bind if (bindRE.test(name)) { // v-bind
name = name.replace(bindRE, '') name = name.replace(bindRE, '')
if (mustUseProp(name)) { if (mustUseProp(name)) {
(el.props || (el.props = [])).push({ name, value }) addProp(el, name, value)
} else { } else {
(el.attrs || (el.attrs = [])).push({ name, value }) addAttr(el, name, value)
} }
} else if (onRE.test(name)) { // v-on } else if (onRE.test(name)) { // v-on
name = name.replace(onRE, '') name = name.replace(onRE, '')
addHandler((el.events || (el.events = {})), name, value, modifiers) addHandler(el, name, value, modifiers)
} else { // normal directives } else { // normal directives
name = name.replace(dirRE, '') name = name.replace(dirRE, '')
// parse arg // parse arg
if ((arg = name.match(argRE)) && (arg = arg[1])) { if ((arg = name.match(argRE)) && (arg = arg[1])) {
name = name.slice(0, -(arg.length + 1)) name = name.slice(0, -(arg.length + 1))
} }
;(el.directives || (el.directives = [])).push({ addDirective(el, name, value, arg, modifiers)
name,
value,
arg,
modifiers
})
} }
} else { } else {
// literal attribute // literal attribute
(el.attrs || (el.attrs = [])).push({ addAttr(el, name, parseText(value) || JSON.stringify(value))
name,
value: parseText(value) || JSON.stringify(value)
})
} }
} }
} }
@ -389,21 +334,6 @@ function makeAttrsMap (attrs) {
return map return map
} }
function getAndRemoveAttr (el, attr) {
let val
if ((val = el.attrsMap[attr]) != null) {
el.attrsMap[attr] = null
const list = el.attrsList
for (let i = 0, l = list.length; i < l; i++) {
if (list[i].name === attr) {
list.splice(i, 1)
break
}
}
}
return val
}
function findPrevElement (children) { function findPrevElement (children) {
let i = children.length let i = children.length
while (i--) { while (i--) {

View File

@ -1,8 +1,10 @@
import { warn } from '../util/index' import { warn, inBrowser } from '../util/index'
let hasProxy, proxyHandlers, initProxy let hasProxy, proxyHandlers, initProxy
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
let context = inBrowser ? window : global
hasProxy = hasProxy =
typeof Proxy !== 'undefined' && typeof Proxy !== 'undefined' &&
Proxy.toString().match(/native code/) Proxy.toString().match(/native code/)
@ -12,13 +14,14 @@ if (process.env.NODE_ENV !== 'production') {
if (key === 'undefined') { if (key === 'undefined') {
return false return false
} }
if (!(key in target)) { let has = key in target
if (!has && !(key in context)) {
warn( warn(
`Trying to access non-existent property "${key}" while rendering.`, `Trying to access non-existent property "${key}" while rendering.`,
target target
) )
} }
return true return has
} }
} }