Evan You 9 лет назад
Родитель
Сommit
35ee5b105e

+ 1 - 1
flow/compiler.js

@@ -71,11 +71,11 @@ declare type ASTElement = {
   static?: boolean;
   staticRoot?: boolean;
   staticProcessed?: boolean;
+  hasBindings?: boolean;
 
   text?: string;
   attrs?: Array<{ name: string; value: string }>;
   props?: Array<{ name: string; value: string }>;
-  staticAttrs?: Array<{ name: string; value: string }>;
   plain?: boolean;
   pre?: true;
   ns?: string;

+ 0 - 1
flow/vnode.js

@@ -42,7 +42,6 @@ declare interface VNodeData {
   props?: { [key: string]: any };
   attrs?: { [key: string]: string };
   domProps?: { [key: string]: any };
-  staticAttrs?: { [key: string]: string };
   hook?: { [key: string]: Function };
   on?: ?{ [key: string]: Function | Array<Function> };
   nativeOn?: { [key: string]: Function | Array<Function> };

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

@@ -31,6 +31,7 @@ export function generate (
   platformDirectives = options.directives || {}
   isPlatformReservedTag = options.isReservedTag || no
   const code = ast ? genElement(ast) : '_h("div")'
+  // console.log(code)
   staticRenderFns = prevStaticRenderFns
   return {
     render: `with(this){return ${code}}`,
@@ -150,10 +151,6 @@ function genData (el: ASTElement): string | void {
   if (el.attrs) {
     data += `attrs:{${genProps(el.attrs)}},`
   }
-  // static attributes
-  if (el.staticAttrs) {
-    data += `staticAttrs:{${genProps(el.staticAttrs)}},`
-  }
   // DOM props
   if (el.props) {
     data += `domProps:{${genProps(el.props)}},`

+ 0 - 4
src/compiler/helpers.js

@@ -21,10 +21,6 @@ export function addAttr (el: ASTElement, name: string, value: string) {
   (el.attrs || (el.attrs = [])).push({ name, value })
 }
 
-export function addStaticAttr (el: ASTElement, name: string, value: string) {
-  (el.staticAttrs || (el.staticAttrs = [])).push({ name, value })
-}
-
 export function addDirective (
   el: ASTElement,
   name: string,

+ 3 - 2
src/compiler/optimizer.js

@@ -30,7 +30,7 @@ export function optimize (root: ?ASTElement, options: CompilerOptions) {
 
 function genStaticKeys (keys: string): Function {
   return makeMap(
-    'type,tag,attrsList,attrsMap,plain,parent,children,staticAttrs' +
+    'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +
     (keys ? ',' + keys : '')
   )
 }
@@ -68,9 +68,10 @@ function isStatic (node: ASTNode): boolean {
     return true
   }
   return !!(node.pre || (
+    !node.hasBindings && // no dynamic bindings
     !node.if && !node.for && // not v-if or v-for or v-else
     !isBuiltInTag(node.tag) && // not a built-in
     isPlatformReservedTag(node.tag) && // not a component
-    (node.plain || Object.keys(node).every(isStaticKey)) // no dynamic bindings
+    Object.keys(node).every(isStaticKey)
   ))
 }

+ 4 - 3
src/compiler/parser/index.js

@@ -9,7 +9,6 @@ import {
   getAndRemoveAttr,
   addProp,
   addAttr,
-  addStaticAttr,
   addHandler,
   addDirective,
   getBindingAttr,
@@ -242,7 +241,7 @@ function processPre (el) {
 function processRawAttrs (el) {
   const l = el.attrsList.length
   if (l) {
-    const attrs = el.staticAttrs = new Array(l)
+    const attrs = el.attrs = new Array(l)
     for (let i = 0; i < l; i++) {
       attrs[i] = {
         name: el.attrsList[i].name,
@@ -361,6 +360,8 @@ function processAttrs (el) {
     name = list[i].name
     value = list[i].value
     if (dirRE.test(name)) {
+      // mark element as dynamic
+      el.hasBindings = true
       // modifiers
       modifiers = parseModifiers(name)
       if (modifiers) {
@@ -402,7 +403,7 @@ function processAttrs (el) {
           )
         }
       }
-      addStaticAttr(el, name, JSON.stringify(value))
+      addAttr(el, name, JSON.stringify(value))
     }
   }
 }

+ 3 - 4
src/core/vdom/create-component.js

@@ -234,14 +234,13 @@ function extractProps (data: VNodeData, Ctor: Class<Component>): ?Object {
     return
   }
   const res = {}
-  const { attrs, props, domProps, staticAttrs } = data
-  if (attrs || props || domProps || staticAttrs) {
+  const { attrs, props, domProps } = data
+  if (attrs || props || domProps) {
     for (const key in propOptions) {
       const altKey = hyphenate(key)
       checkProp(res, props, key, altKey, true) ||
       checkProp(res, attrs, key, altKey) ||
-      checkProp(res, domProps, key, altKey) ||
-      checkProp(res, staticAttrs, key, altKey)
+      checkProp(res, domProps, key, altKey)
     }
   }
   return res

+ 1 - 9
src/platforms/web/runtime/modules/attrs.js

@@ -64,14 +64,6 @@ function setAttr (el: Element, key: string, value: any) {
 }
 
 export default {
-  create: function (_: any, vnode: VNodeWithData) {
-    const attrs = vnode.data.staticAttrs
-    if (attrs) {
-      for (const key in attrs) {
-        setAttr(vnode.elm, key, attrs[key])
-      }
-    }
-    updateAttrs(_, vnode)
-  },
+  create: updateAttrs,
   update: updateAttrs
 }

+ 0 - 3
src/platforms/web/server/modules/attrs.js

@@ -8,9 +8,6 @@ import {
 
 export default function renderAttrs (node: VNodeWithData): string {
   let res = ''
-  if (node.data.staticAttrs) {
-    res += render(node.data.staticAttrs)
-  }
   if (node.data.attrs) {
     res += render(node.data.attrs)
   }

+ 1 - 1
src/platforms/web/server/modules/style.js

@@ -3,7 +3,7 @@
 import { hyphenate, toObject } from 'shared/util'
 
 export default function renderStyle (node: VNodeWithData): ?string {
-  const staticStyle = node.data.staticAttrs && node.data.staticAttrs.style
+  const staticStyle = node.data.attrs && node.data.attrs.style
   if (node.data.style || staticStyle) {
     let styles = node.data.style
     let res = ' style="'

+ 3 - 3
test/unit/modules/compiler/codegen.spec.js

@@ -167,11 +167,11 @@ describe('codegen', () => {
     )
   })
 
-  it('generate staticAttrs', () => {
+  it('generate static attrs', () => {
     assertCodegen(
       '<input name="field1">',
       `with(this){return _m(0)}`,
-      [`with(this){return _h('input',{staticAttrs:{"name":"field1"}})}`]
+      [`with(this){return _h('input',{attrs:{"name":"field1"}})}`]
     )
   })
 
@@ -260,7 +260,7 @@ describe('codegen', () => {
   it('generate component', () => {
     assertCodegen(
       '<my-component name="mycomponent1" :msg="msg" @notify="onNotify"><div>hi</div></my-component>',
-      `with(this){return _h('my-component',{attrs:{"msg":msg},staticAttrs:{"name":"mycomponent1"},on:{"notify":onNotify}},function(){return [_m(0)]})}`,
+      `with(this){return _h('my-component',{attrs:{"name":"mycomponent1","msg":msg},on:{"notify":onNotify}},function(){return [_m(0)]})}`,
       [`with(this){return _h('div',["hi"])}`]
     )
   })

+ 13 - 13
test/unit/modules/compiler/parser.spec.js

@@ -123,8 +123,8 @@ describe('parser', () => {
   it('v-pre directive', () => {
     const ast = parse('<div v-pre id="message1"><p>{{msg}}</p></div>', baseOptions)
     expect(ast.pre).toBe(true)
-    expect(ast.staticAttrs[0].name).toBe('id')
-    expect(ast.staticAttrs[0].value).toBe('"message1"')
+    expect(ast.attrs[0].name).toBe('id')
+    expect(ast.attrs[0].value).toBe('"message1"')
     expect(ast.children[0].children[0].text).toBe('{{msg}}')
   })
 
@@ -248,10 +248,10 @@ describe('parser', () => {
     expect(ast.attrsList[1].value).toBe('field1')
     expect(ast.attrsMap['type']).toBe('text')
     expect(ast.attrsMap['name']).toBe('field1')
-    expect(ast.staticAttrs[0].name).toBe('type')
-    expect(ast.staticAttrs[0].value).toBe('"text"')
-    expect(ast.staticAttrs[1].name).toBe('name')
-    expect(ast.staticAttrs[1].value).toBe('"field1"')
+    expect(ast.attrs[0].name).toBe('type')
+    expect(ast.attrs[0].value).toBe('"text"')
+    expect(ast.attrs[1].name).toBe('name')
+    expect(ast.attrs[1].value).toBe('"field1"')
     expect(ast.props[0].name).toBe('value')
     expect(ast.props[0].value).toBe('msg')
   })
@@ -286,12 +286,12 @@ describe('parser', () => {
     expect(ast1.attrsMap['type']).toBe('text')
     expect(ast1.attrsMap['name']).toBe('field1')
     expect(ast1.attrsMap['value']).toBe('hello world')
-    expect(ast1.staticAttrs[0].name).toBe('type')
-    expect(ast1.staticAttrs[0].value).toBe('"text"')
-    expect(ast1.staticAttrs[1].name).toBe('name')
-    expect(ast1.staticAttrs[1].value).toBe('"field1"')
-    expect(ast1.staticAttrs[2].name).toBe('value')
-    expect(ast1.staticAttrs[2].value).toBe('"hello world"')
+    expect(ast1.attrs[0].name).toBe('type')
+    expect(ast1.attrs[0].value).toBe('"text"')
+    expect(ast1.attrs[1].name).toBe('name')
+    expect(ast1.attrs[1].value).toBe('"field1"')
+    expect(ast1.attrs[2].name).toBe('value')
+    expect(ast1.attrs[2].value).toBe('"hello world"')
     // interpolation warning
     parse('<input type="text" name="field1" value="{{msg}}">', baseOptions)
     expect('Interpolation inside attributes has been deprecated').toHaveBeenWarned()
@@ -331,7 +331,7 @@ describe('parser', () => {
         spy1(el.tag)
       },
       postTransformNode (el) {
-        expect(el.staticAttrs.length).toBe(1)
+        expect(el.attrs.length).toBe(1)
         spy2(el.tag)
       }
     }])

+ 16 - 14
test/unit/modules/vdom/modules/attrs.spec.js

@@ -3,13 +3,6 @@ import VNode from 'core/vdom/vnode'
 import { xlinkNS } from 'web/util/index'
 
 describe('vdom attrs module', () => {
-  it('should create an element with staticAttrs', () => {
-    const vnode = new VNode('p', { staticAttrs: { id: 1, class: 'class1' }})
-    const elm = patch(null, vnode)
-    expect(elm.id).toBe('1')
-    expect(elm).toHaveClass('class1')
-  })
-
   it('should create an element with attrs', () => {
     const vnode = new VNode('p', { attrs: { id: 1, class: 'class1' }})
     const elm = patch(null, vnode)
@@ -18,7 +11,7 @@ describe('vdom attrs module', () => {
   })
 
   it('should change the elements attrs', () => {
-    const vnode1 = new VNode('i', { staticAttrs: { id: '1', class: 'i am vdom' }})
+    const vnode1 = new VNode('i', { attrs: { id: '1', class: 'i am vdom' }})
     const vnode2 = new VNode('i', { attrs: { id: '2', class: 'i am' }})
     patch(null, vnode1)
     const elm = patch(vnode1, vnode2)
@@ -37,38 +30,47 @@ describe('vdom attrs module', () => {
     expect(elm.className).toBe('')
   })
 
+  it('should remove the elements attrs for new nodes without attrs data', () => {
+    const vnode1 = new VNode('i', { attrs: { id: '1', class: 'i am vdom' }})
+    const vnode2 = new VNode('i', {})
+    patch(null, vnode1)
+    const elm = patch(vnode1, vnode2)
+    expect(elm.id).toBe('')
+    expect(elm.className).toBe('')
+  })
+
   it('should remove the falsy value from boolean attr', () => {
-    const vnode = new VNode('option', { staticAttrs: { disabled: null }})
+    const vnode = new VNode('option', { attrs: { disabled: null }})
     const elm = patch(null, vnode)
     expect(elm.getAttribute('disabled')).toBe(null)
   })
 
   it('should set the attr name to boolean attr', () => {
-    const vnode = new VNode('option', { staticAttrs: { disabled: true }})
+    const vnode = new VNode('option', { attrs: { disabled: true }})
     const elm = patch(null, vnode)
     expect(elm.getAttribute('disabled')).toBe('disabled')
   })
 
   it('should set the falsy value to enumerated attr', () => {
-    const vnode = new VNode('div', { staticAttrs: { contenteditable: null }})
+    const vnode = new VNode('div', { attrs: { contenteditable: null }})
     const elm = patch(null, vnode)
     expect(elm.getAttribute('contenteditable')).toBe('false')
   })
 
   it('should set the boolean string value to enumerated attr', () => {
-    const vnode = new VNode('div', { staticAttrs: { contenteditable: 'true' }})
+    const vnode = new VNode('div', { attrs: { contenteditable: 'true' }})
     const elm = patch(null, vnode)
     expect(elm.getAttribute('contenteditable')).toBe('true')
   })
 
   it('should set the xlink value to attr', () => {
-    const vnode = new VNode('a', { staticAttrs: { 'xlink:href': '#id1' }})
+    const vnode = new VNode('a', { attrs: { 'xlink:href': '#id1' }})
     const elm = patch(null, vnode)
     expect(elm.getAttributeNS(xlinkNS, 'href')).toBe('#id1')
   })
 
   it('should set the xlink boolean string value to attr', () => {
-    const vnode = new VNode('option', { staticAttrs: { 'xlink:disabled': true }})
+    const vnode = new VNode('option', { attrs: { 'xlink:disabled': true }})
     const elm = patch(null, vnode)
     expect(elm.getAttributeNS(xlinkNS, 'disabled')).toBe('true')
   })