mh-two-thousand-and-two
2024-04-12 3d2ec2fd0578d3ba0a414b0cc4e4a2ae60878596
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const {
  ID,
  isVar
} = require('./util')
 
const {
  isComponent
} = require('../util')
 
let isPlatformReservedTag
 
function no (a, b, c) {
  return false
}
 
function isBuiltInTag (tag) {
  if (
    tag === 'slot' ||
    tag === 'component' ||
    tag === 'keep-alive'
  ) {
    return true
  }
}
 
function isStatic (node) {
  if (node.type === 2) {
    return false
  }
  if (node.type === 3) {
    return true
  }
  if (node.staticClass || node.classBinding || node.styleBinding) {
    return false
  }
  return !!(node.pre || (
    !node.hasBindings && // no dynamic bindings
    !isBuiltInTag(node.tag) && // not a built-in
    isPlatformReservedTag(node.tag)
  ))
}
 
function markStatic (node) {
  if (isStatic(node)) { // 静态节点且仅包含 ID 属性
    if (
      node.attrs &&
      node.attrs.length === 1 &&
      !node.key &&
      !node.ref &&
      !node.slotTarget
    ) {
      node.plain = true
    }
    if (!node.attrsMap || !node.attrsMap.id) { // 保留 id 属性, selectComponent 需要使用
      delete node.attrs
    }
  }
  if (node.type === 1) {
    // 需要保留 staticClass , selectComponent,externalClasses
    // delete node.staticClass
    delete node.staticStyle
 
    const isCustomComponent = isComponent(node.tag)
    if (node.attrs && !isCustomComponent && node.tag !== 'keep-alive') { // 移除静态属性
      // 保留 id 属性, selectComponent 需要使用
      node.attrs = node.attrs.filter(attr => {
        const {
          name,
          value
        } = attr
        return name === 'id' ||
          name === ID ||
          // name.indexOf('data-') === 0 || // TODO dataset
          isVar(value)
      })
    }
 
    node.children = node.children.filter(child => { // 移除静态文本
      if (child.type === 3) { // ASTText
        if (!isCustomComponent) {
          return false
        }
        child.text = '' // slot <custom>ABCD</custom>
      }
      return true
    })
 
    for (let i = 0, l = node.children.length; i < l; i++) {
      const child = node.children[i]
      markStatic(child)
    }
    if (node.ifConditions) {
      for (let i = 1, l = node.ifConditions.length; i < l; i++) {
        const block = node.ifConditions[i].block
        markStatic(block)
      }
    }
  }
}
 
module.exports = function optimize (root, options) {
  isPlatformReservedTag = options.isReservedTag || no
  markStatic(root)
}