parse解析

194 阅读3分钟

开篇

下面主要将template里面包含的slot插槽,指令,属性,自定义事件,自定义指令,过滤器,组件,标签等转换为ast

slot插槽

匿名插槽

<!--template-->
Vue.component('slot1',{
    template : `<div>
        <slot></slot>
    </div>`
})
<slot1>匿名插槽</slot1><!--ast-->
{
    attrsList: []
    attrsMap: {},
    children : [
        {type: 3, text: '匿名插槽'}
    ],
    rawAttrsMap : {},
    tag: "slot1",
    type: 1
}

具名插槽

<!--template-->
Vue.component('slot2',{
    template : `
        <div>
            <slot name='header'></slot>
        </div>
    `
})
​
<slot2><template #header>具名插槽</template></slot2><!--ast-->
{
    attrsList: [],
    attrsMap: {},
    children: [],
    rawAttrsMap: {},
    scopedSlots : {
        "header" : {
            attrsList: [],
            attrsMap: {#header: ''},
            children : [{type: 3, text: '具名插槽'}],
            rawAttrsMap : {
                #header: {name: '#header', value: ''}
            },
            slotScope: "_empty_",
            slotTarget: ""header"",
            slotTargetDynamic: false,
            tag: "template",
            type: 1
        }
    },
    tag: "slot2",
    type: 1
}

作用域插槽

<!--template-->
<slot3><template v-slot:header="user">{{user}}</template></slot3>
Vue.component('slot3',{
    template : `
        <div>
            <slot :list='arr' name='header'></slot>
        </div>
    `,
    data(){
        return {
            arr : [1,2,3]
        }
    }
})
​
<!--ast-->
{
    ...,
    scopedSlots : {
        "header" : {
            attrsList: [],
            attrsMap: {v-slot:header: 'user'},
            children : [
                {
                        expression: "_s(user)",
                        text: "{{user}}",
                        tokens : [{@binding: 'user'}],
                        type: 2
                }
            ],
            rawAttrsMap : {
                v-slot:header : {
                    name: 'v-slot:header', value: 'user'
                }
            },
            slotScope: "user",
            slotTarget: ""header"",
            slotTargetDynamic: false,
            tag: "template",
            type: 1
        }
    },
    tag: "slot3",
    type: 1
}
​

指令:

v-text

<!--template-->
<span v-text="a"></span>
​
<!--ast-->
{
    attrsList : [{name: 'v-text', value: 'a'}],
    attrsMap : {v-text: 'a'},
    directives : [{
        arg: null,
        isDynamicArg: false,
        modifiers: undefined,
        name: "text",
        rawName: "v-text",
        value: "a"   
    }],
    rawAttrsMap : {v-text: {name: 'v-text', value: 'a'}},
    tag: "span",
    type: 1,
}

v-html

<!--template-->
<div v-html="c"></div>
​
<!--ast-->
{
    attrsList : [{name: 'v-html', value: 'c'}],
    attrsMap : {v-html: "c"},
    directives : [{
         name: "html",
         rawName: "v-html",
         value: "c"
    }],
    rawAttrsMap : {
        v-html: {name: 'v-html', value: 'c'}
    }
}

v-show

更上面差不多

v-if v-else-if v-else

<!--template-->
<div v-if="d">5</div>
<div v-else-if="g">6</div>
<div v-else>7</div><!--ast-->
{
    attrsList: [],
    attrsMap: {v-if: 'd'},
    if: "d",
    ifConditions : [
        {
            block : 当前节点,
            exp : "d"
        },
        {
            block : 当前节点,
            exp : "g"
        },
        {
            block : 当前节点,
            exp : undefined
        },
    ],
    rawAttrsMap : {v-if: {name: 'v-if', value: 'd'}}
}

v-for

<!--template-->
<span v-for="(item,index) in 3" :key='index'>{{item}}</span>
​
<!--ast-->
{
    alias: "item",
    attrsList: [],
    attrsMap: {v-for: '(item,index) in 3', :key: 'index'},
    children : [{
        expression: "_s(item)",
        static: false,
        text: "{{item}}",
        token : [{@binding: 'item'}],
        type: 2
    }],
    for: "3",
    iterator1: "index",
    key : "index"
    rawAttrsMap : {
        :key : {name: ':key', value: 'item.id'},
        v-for: {name: 'v-for', value: '(item,index) in 3'}
    }
}

v-on

<!--template-->
<button @click="onclicks">{{count}}</button>
​
<!--ast-->
{
    attrsList : [{name: '@click', value: 'onclicks'}],
    attrsMap: {@click: 'onclicks'},
    children : [
        {type: 2, expression: '_s(count)', tokens: Array(1), text: '{{count}}', tokens:[{@binding: 'count'}]}
    ],
    events : [{value: 'onclicks', dynamic: false}],
    rawAttrsMap : {
        @click : {
            name: "@click",
            value: "onclicks"
        }
    }
}

v-bind

<!--template-->
<img :src='t'/ alt="picture">
​
<!--ast-->
{
    attrs : [
        {name: 'src', value: 't', dynamic: false},
        {name: 'alt', value: '"picture"', dynamic: undefined}
    ],
    attrsList : [
        {name: ':src', value: 't'},
        {name: 'alt', value: 'picture'}
    ],
    attrsMap : {
        :src: "t",
         alt: "picture"
    },
    rawAttrsMap : {
        :src: {name: ':src', value: 't', start: 325, end: 333},
        alt: {name: 'alt', value: 'picture', start: 334, end: 347}
    }
}

v-model

<!--template-->
<input v-model='s'/><!--ast-->
{
    attrsList : [{name: 'v-model', value: 's'}],
    attrsMap: {v-model: 's'},
    directives : [
        {name: 'model', rawName: 'v-model', value: 's', arg: null, isDynamicArg: false}
    ],
    rawAttrsMap : {
        v-model: {name: 'v-model', value: 's'}
    }
}

v-slot

<!--template-->
<blog>
    <template v-slot:header>123</template>
</blog><!--ast-->
{
    attrsList: [],
    attrsMap: {},
    children: [],
    rawAttrsMap: {},
    scopedSlots : {
        "header": {
            attrsList: [],
            attrsMap: {v-slot:header: ''},
            rawAttrsMap : {
               v-slot:header: {name: 'v-slot:header', value: ''}
            },
            slotScope: "_empty_",
            slotTarget: ""header"",
            slotTargetDynamic: false
        }
    },
    tag: "blog"
}

v-pre

<!--template-->
<div v-pre>{{t}}</div><!--ast-->
{
    attrsList : [],
    attrsMap: {v-pre: ''},
    children : [
        {type: 3, text: '{{t}}',static: true}
    ],
    pre: true,
    rawAttrsMap : {
        v-pre: {name: 'v-pre', value: ''}
    },
    staticInFor: false
}

v-cloak

<!--template-->
<span v-cloak>{{t}}</span><!--ast-->
{
    attrsList : [
        {name: 'v-cloak', value: ''}
    ],
    attrsMap: {v-cloak: ''},
    directives : [
        {
            arg: null,
            isDynamicArg: false,
            modifiers: undefined,
            name: "cloak",
            rawName: "v-cloak",
            value: ""
        }
    ],
    rawAttrsMap : {
        v-cloak: {name: 'v-cloak', value: ''}
    }
}

v-once

<!--template-->
<div v-once>{{t}}</div><!--ast-->
{
    attrsList: []
    attrsMap: {v-once: ''},
    rawAttrsMap : [
        { v-once: {name: 'v-once', value: ''} }
    ]
}

Attribute(属性)

key

<!--template-->
<div v-for="(item,index) in 3" :key="index">{{item}}</div><!--ast-->
{
    alias: "item",
    attrsList: [],
    attrsMap: {v-for: '(item,index) in 3', :key: 'index'},
    for: "3",
    iterator1: "index",
    rawAttrsMap : {
        :key: {name: ':key', value: 'index'},
        v-for: {name: 'v-for', value: '(item,index) in 3'}
    }
}

ref

<!--template-->
<p ref="p"></p><!--ast-->
{
    attrsList: [],
    attrsMap: {ref: 'p'},
    rawAttrsMap : {
        ref: {name: 'ref', value: 'p'}
    },
    ref: ""p"",
    refInFor: false
}

is

<!--template-->
<component :is="g2"></component><!--ast-->
{
    attrsList: [],
    attrsMap: {:is: 'g2'},
    component: "g2",
    rawAttrsMap : {
        :is: {name: ':is', value: 'g2'}
    },
    tag: "component"
}

自定义事件

原生标签

<!--template-->
<button @click="() => count++">{{count}}</button><!--ast-->
{
    attrsList : [
        {name: '@click', value: '() => count++'}
    ],
    attrsMap: {@click: '() => count++'},
    events : {
        click: {value: '() => count++', dynamic: false}
    },
    rawAttrsMap : {
        @click: {name: '@click', value: '() => count++'}
    }
}

组件标签

<!--template-->
<blog-test @change="onclicks"></blog-test><!--ast-->
{
    attrsList : [{name: '@change', value: 'onclicks'}],
    attrsMap: {@change: 'onclicks'},
    events : {
        change: {value: 'onclicks', dynamic: false}
    },
    rawAttrsMap : {
        @change: {name: '@change', value: 'onclicks'}
    }
}

自定义指令

<!--template-->
<div v-test></div>
​
<!--ast-->
{
    attrsList : [
        {name: 'v-test', value: ''}
    ],
    attrsMap: {v-test: ''},
    children : [{...}],
    directives : [{name: 'test', rawName: 'v-test', value: '', arg: null, isDynamicArg: false, …}],
    rawAttrsMap : [{
        v-test: {name: 'v-test', value: ''}
    }]
}

过滤器

<!--template-->
<div v-for="(item,index) in arr" :key="item.id">{{ item | select}}</div><!--ast-->
{
    ...,
    children : [
        {
            expression: "_s(_f("select")(item))",
            text: "{{ item | select}}",
            tokens : [ {@binding: '_f("select")(item)'} ],
            type : 2
        }
    ]
}

组件

<!--template-->
<to></to><!--ast-->
{
    attrsList: [],
    attrsMap: {},
    children: [],
    rawAttrsMap: {},
    tag: "to",
    type: 1,
}

标签

表达式

<!--template-->
<div>{{t}}</div><!--ast-->
{
    ...,
    children : [
        {
            expression: "_s(t)",
            static: false,
            text: "{{t}}",
            tokens : [{@binding: 't'}]
        }
    ]
}

计算属性

<!--template-->
<div>{{gs}}</div><!--ast-->
{
    ...,
    children : [
        {
            expression: "_s(gs)",
            text: "{{gs}}",
            token : [{@binding: 'gs'}]
        }
    ]
}