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) {
if (!dir.value) return
if (!el.props) el.props = []
el.props.push({
name: 'innerHTML',
value: `(${dir.value})`
})
addProp(el, 'innerHTML', `(${dir.value})`)
}

View File

@ -1,8 +1,6 @@
import { addHandler } from '../../helpers'
import { addHandler, addProp, getBindingAttr } from '../../helpers'
export function model (el, dir) {
if (!el.events) el.events = {}
if (!el.props) el.props = []
const value = dir.value
const modifiers = dir.modifiers
if (el.tag === 'select') {
@ -26,19 +24,13 @@ export function model (el, dir) {
}
function genCheckboxModel (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.checked`)
el.props.push({
name: 'checked',
value: `!!(${value})`
})
addProp(el, 'checked', `!!(${value})`)
addHandler(el, 'change', `${value}=$event.target.checked`)
}
function genRadioModel (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.value`)
el.props.push({
name: 'checked',
value: `(${value}==${getInputValue(el)})`
})
addProp(el, 'checked', `(${value}==${getBindingAttr(el, 'value')})`)
addHandler(el, 'change', `${value}=$event.target.value`)
}
function genDefaultModel (el, value, modifiers) {
@ -51,15 +43,11 @@ function genDefaultModel (el, value, modifiers) {
let code = number || type === 'number'
? `${value}=Number($event.target.value)`
: `${value}=$event.target.value`
if (needCompositionGuard) {
code = `if($event.target.composing)return;${code}`
}
addHandler(el.events, event, code)
el.props.push({
name: 'value',
value: `(${value})`
})
addProp(el, 'value', `(${value})`)
addHandler(el, event, code)
if (needCompositionGuard) {
// return runtime directive code to help with composition events
return '{def:__resolveDirective__("model")},'
@ -67,15 +55,12 @@ function genDefaultModel (el, value, modifiers) {
}
function genSelect (el, value) {
addHandler(el.events, 'change', `${value}=$event.target.value`)
el.props.push({
name: 'value',
value: `(${value})`
})
addProp(el, 'value', `(${value})`)
addHandler(el, 'change', `${value}=$event.target.value`)
}
function genMultiSelect (el, value) {
addHandler(el.events, 'change',
addHandler(el, 'change',
`${value}=Array.prototype.filter
.call($event.target.options,function(o){return o.selected})
.map(function(o){return o.value})`)
@ -83,16 +68,7 @@ function genMultiSelect (el, value) {
for (let i = 0; i < el.children.length; i++) {
let c = el.children[i]
if (c.tag === 'option') {
(c.props || (c.props = [])).push({
name: 'selected',
value: `(${value}).indexOf(${getInputValue(c)})>-1`
})
addProp(c, 'selected', `(${value}).indexOf(${getBindingAttr(c, 'value')})>-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'
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
if (modifiers && modifiers.capture) {
delete modifiers.capture
@ -16,3 +39,19 @@ export function addHandler (events, name, value, modifiers) {
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 { parseHTML } from './html-parser'
import { parseText } from './text-parser'
import { addHandler } from '../helpers'
import { hyphenate, makeMap } from '../../shared/util'
import {
getAndRemoveAttr,
addProp,
addAttr,
addHandler,
addDirective,
getBindingAttr
} from '../helpers'
const dirRE = /^v-|^@|^:/
const bindRE = /^:|^v-bind:/
@ -26,51 +33,6 @@ const baseWarn = msg => console.error(`[Vue parser]: ${msg}`)
/**
* 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 {Object} options
* @return {Object}
@ -295,33 +257,24 @@ function processRender (el) {
function processSlot (el) {
if (el.tag === 'slot') {
el.slotName = el.attrsMap.name
? `"${el.attrsMap.name}"`
: (el.attrsMap[':name'] || el.attrsMap['v-bind:name'])
el.slotName = getBindingAttr(el, 'name')
}
}
function processComponent (el) {
if (el.tag === 'component') {
let staticName = getAndRemoveAttr(el, 'is')
el.component = staticName
? JSON.stringify(staticName)
: (getAndRemoveAttr(el, ':is') || getAndRemoveAttr(el, 'v-bind:is'))
el.component = getBindingAttr(el, 'is')
}
}
function processClassBinding (el) {
const staticClass = getAndRemoveAttr(el, 'class')
el.staticClass = parseText(staticClass) || JSON.stringify(staticClass)
el.classBinding =
getAndRemoveAttr(el, ':class') ||
getAndRemoveAttr(el, 'v-bind:class')
el.classBinding = getBindingAttr(el, 'class', false /* getStatic */)
}
function processStyleBinding (el) {
el.styleBinding =
getAndRemoveAttr(el, ':style') ||
getAndRemoveAttr(el, 'v-bind:style')
el.styleBinding = getBindingAttr(el, 'style', false /* getStatic */)
}
function processAttrs (el) {
@ -339,32 +292,24 @@ function processAttrs (el) {
if (bindRE.test(name)) { // v-bind
name = name.replace(bindRE, '')
if (mustUseProp(name)) {
(el.props || (el.props = [])).push({ name, value })
addProp(el, name, value)
} else {
(el.attrs || (el.attrs = [])).push({ name, value })
addAttr(el, name, value)
}
} else if (onRE.test(name)) { // v-on
name = name.replace(onRE, '')
addHandler((el.events || (el.events = {})), name, value, modifiers)
addHandler(el, name, value, modifiers)
} else { // normal directives
name = name.replace(dirRE, '')
// parse arg
if ((arg = name.match(argRE)) && (arg = arg[1])) {
name = name.slice(0, -(arg.length + 1))
}
;(el.directives || (el.directives = [])).push({
name,
value,
arg,
modifiers
})
addDirective(el, name, value, arg, modifiers)
}
} else {
// literal attribute
(el.attrs || (el.attrs = [])).push({
name,
value: parseText(value) || JSON.stringify(value)
})
addAttr(el, name, parseText(value) || JSON.stringify(value))
}
}
}
@ -389,21 +334,6 @@ function makeAttrsMap (attrs) {
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) {
let i = children.length
while (i--) {

View File

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