浏览代码

Change svg parameter to namespace (#3)

* change svg parameter into namespace

* fixed svg to namespace bug

* change svg detecting into namespace detecting in parser

* fixed eslint error
Jinjiang 10 年之前
父节点
当前提交
6e251e0721

+ 1 - 1
src/compiler/codegen/index.js

@@ -29,7 +29,7 @@ function genElement (el) {
     // if the element is potentially a component,
     // wrap its children as a thunk.
     const children = genChildren(el, !isReservedTag(el.tag) /* asThunk */)
-    const code = `__h__('${el.tag}', ${genData(el)}, ${children}, ${el.svg})`
+    const code = `__h__('${el.tag}', ${genData(el)}, ${children}, '${el.namespace || ''}')`
     if (el.staticRoot) {
       // hoist static sub-trees out
       staticRenderFns.push(`with(this){return ${code}}`)

+ 19 - 15
src/compiler/parser/index.js

@@ -26,8 +26,8 @@ const decodeHTMLCached = cached(decodeHTML)
 // attributes that should be using props for binding
 const mustUseProp = makeMap('value,selected,checked,muted')
 
-// this map covers SVG elements that can appear as template root nodes
-const isSVG = makeMap('svg,g,defs,symbol,use,image,text,circle,ellipse,line,path,polygon,polyline,rect', true)
+// this map covers namespace elements that can appear as template root nodes
+const tagNamespace = makeMap('svg,g,defs,symbol,use,image,text,circle,ellipse,line,path,polygon,polyline,rect', true, 'svg')
 
 // make warning customizable depending on environment.
 let warn
@@ -47,8 +47,9 @@ export function parse (template, options) {
   const stack = []
   let root
   let currentParent
-  let inSvg = false
-  let svgIndex = -1
+  let inNamespace = false
+  let namespaceIndex = -1
+  let currentNamespace = ''
   let inPre = false
   let warned = false
   parseHTML(template, {
@@ -73,13 +74,15 @@ export function parse (template, options) {
         children: []
       }
 
-      // check svg
-      if (inSvg) {
-        element.svg = true
-      } else if (isSVG(tag)) {
-        element.svg = true
-        inSvg = true
-        svgIndex = stack.length
+      // check namespace
+      const namespace = tagNamespace(tag)
+      if (inNamespace) {
+        element.namespace = currentNamespace
+      } else if (namespace) {
+        element.namespace = namespace
+        inNamespace = true
+        currentNamespace = namespace
+        namespaceIndex = stack.length
       }
 
       if (!inPre) {
@@ -136,10 +139,11 @@ export function parse (template, options) {
       // pop stack
       stack.length -= 1
       currentParent = stack[stack.length - 1]
-      // check svg state
-      if (inSvg && stack.length <= svgIndex) {
-        inSvg = false
-        svgIndex = -1
+      // check namespace state
+      if (inNamespace && stack.length <= namespaceIndex) {
+        inNamespace = false
+        currentNamespace = ''
+        namespaceIndex = -1
       }
       // check pre state
       if (element.pre) {

+ 3 - 1
src/runtime/dom/class-util.js

@@ -1,5 +1,7 @@
 import { isIE9 } from '../util/index'
-import { svgNS } from './node-ops'
+import { namespaceMap } from './node-ops'
+
+const svgNS = namespaceMap.svg
 
 /**
  * In IE9, setAttribute('class') will result in empty class

+ 5 - 3
src/runtime/dom/node-ops.js

@@ -1,11 +1,13 @@
-export const svgNS = 'http://www.w3.org/2000/svg'
+export const namespaceMap = {
+  svg: 'http://www.w3.org/2000/svg'
+}
 
 export function createElement (tagName) {
   return document.createElement(tagName)
 }
 
-export function createSVGElement (tagName) {
-  return document.createElementNS(svgNS, tagName)
+export function createElementNS (namespace, tagName) {
+  return document.createElementNS(namespaceMap[namespace], tagName)
 }
 
 export function createTextNode (text) {

+ 4 - 4
src/runtime/vdom/create-element.js

@@ -4,18 +4,18 @@ import { flatten } from './helpers'
 import { renderState } from '../instance/render'
 import { warn, isReservedTag, isUnknownElement, resolveAsset } from '../util/index'
 
-export default function createElement (tag, data, children, svg) {
+export default function createElement (tag, data, children, namespace) {
   const context = this
   const parent = renderState.activeInstance
   if (typeof tag === 'string') {
     let Ctor
     if (isReservedTag(tag)) {
-      return VNode(tag, data, flatten(children), undefined, undefined, svg)
+      return VNode(tag, data, flatten(children), undefined, undefined, namespace)
     } else if ((Ctor = resolveAsset(context.$options, 'components', tag))) {
       return createComponent(Ctor, data, parent, children)
     } else {
       if (process.env.NODE_ENV !== 'production') {
-        if (!svg && isUnknownElement(tag)) {
+        if (!namespace && isUnknownElement(tag)) {
           warn(
             'Unknown custom element: <' + tag + '> - did you ' +
             'register the component correctly? For recursive components, ' +
@@ -23,7 +23,7 @@ export default function createElement (tag, data, children, svg) {
           )
         }
       }
-      return VNode(tag, data, flatten(children && children()), undefined, undefined, svg)
+      return VNode(tag, data, flatten(children && children()), undefined, undefined, namespace)
     }
   } else {
     return createComponent(tag, data, parent, children)

+ 2 - 2
src/runtime/vdom/patch.js

@@ -81,8 +81,8 @@ export default function createPatchFunction (backend) {
     const children = vnode.children
     const tag = vnode.tag
     if (isDef(tag)) {
-      elm = vnode.elm = vnode.svg
-        ? nodeOps.createSVGElement(tag)
+      elm = vnode.elm = vnode.namespace
+        ? nodeOps.createElementNS(vnode.namespace, tag)
         : nodeOps.createElement(tag)
       if (Array.isArray(children)) {
         for (i = 0; i < children.length; ++i) {

+ 2 - 2
src/runtime/vdom/vnode.js

@@ -1,11 +1,11 @@
-export default function VNode (tag, data, children, text, elm, svg) {
+export default function VNode (tag, data, children, text, elm, namespace) {
   return {
     tag,
     data,
     children,
     text,
     elm,
-    svg,
+    namespace,
     key: data && data.key
   }
 }

+ 2 - 2
src/shared/util.js

@@ -7,10 +7,10 @@
  * @return {Function}
  */
 
-export function makeMap (str, expectsLowerCase) {
+export function makeMap (str, expectsLowerCase, defaultValue = true) {
   const map = Object.create(null)
   str.split(',').forEach(key => {
-    map[key] = true
+    map[key] = defaultValue
   })
   return expectsLowerCase
     ? val => map[val.toLowerCase()]